mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#118 refactoring of comms types
This commit is contained in:
parent
34cac6a8b8
commit
6e0dde3f30
@ -14,13 +14,13 @@ local println = util.println
|
|||||||
local print_ts = util.print_ts
|
local print_ts = util.print_ts
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPES = comms.DEVICE_TYPES
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||||
local SCADA_CRDN_TYPES = comms.SCADA_CRDN_TYPES
|
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
||||||
local UNIT_COMMANDS = comms.UNIT_COMMANDS
|
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||||
local FAC_COMMANDS = comms.FAC_COMMANDS
|
local FAC_COMMAND = comms.FAC_COMMAND
|
||||||
|
|
||||||
local coordinator = {}
|
local coordinator = {}
|
||||||
|
|
||||||
@ -225,15 +225,15 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
_conf_channels()
|
_conf_channels()
|
||||||
|
|
||||||
-- send a packet to the supervisor
|
-- send a packet to the supervisor
|
||||||
---@param msg_type SCADA_MGMT_TYPES|SCADA_CRDN_TYPES
|
---@param msg_type SCADA_MGMT_TYPE|SCADA_CRDN_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_sv(protocol, msg_type, msg)
|
local function _send_sv(protocol, msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local pkt = nil ---@type mgmt_packet|crdn_packet
|
local pkt = nil ---@type mgmt_packet|crdn_packet
|
||||||
|
|
||||||
if protocol == PROTOCOLS.SCADA_MGMT then
|
if protocol == PROTOCOL.SCADA_MGMT then
|
||||||
pkt = comms.mgmt_packet()
|
pkt = comms.mgmt_packet()
|
||||||
elseif protocol == PROTOCOLS.SCADA_CRDN then
|
elseif protocol == PROTOCOL.SCADA_CRDN then
|
||||||
pkt = comms.crdn_packet()
|
pkt = comms.crdn_packet()
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
@ -248,13 +248,13 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
|
|
||||||
-- attempt connection establishment
|
-- attempt connection establishment
|
||||||
local function _send_establish()
|
local function _send_establish()
|
||||||
_send_sv(PROTOCOLS.SCADA_MGMT, SCADA_MGMT_TYPES.ESTABLISH, { comms.version, version, DEVICE_TYPES.CRDN })
|
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.CRDN })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- keep alive ack
|
-- keep alive ack
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_keep_alive_ack(srv_time)
|
local function _send_keep_alive_ack(srv_time)
|
||||||
_send_sv(PROTOCOLS.SCADA_MGMT, SCADA_MGMT_TYPES.KEEP_ALIVE, { srv_time, util.time() })
|
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- PUBLIC FUNCTIONS --
|
-- PUBLIC FUNCTIONS --
|
||||||
@ -271,7 +271,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
function public.close()
|
function public.close()
|
||||||
sv_watchdog.cancel()
|
sv_watchdog.cancel()
|
||||||
self.sv_linked = false
|
self.sv_linked = false
|
||||||
_send_sv(PROTOCOLS.SCADA_MGMT, SCADA_MGMT_TYPES.CLOSE, {})
|
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.CLOSE, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- attempt to connect to the subervisor
|
-- attempt to connect to the subervisor
|
||||||
@ -300,7 +300,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
elseif event == "modem_message" then
|
elseif event == "modem_message" then
|
||||||
-- handle message
|
-- handle message
|
||||||
local packet = public.parse_packet(p1, p2, p3, p4, p5)
|
local packet = public.parse_packet(p1, p2, p3, p4, p5)
|
||||||
if packet ~= nil and packet.type == SCADA_MGMT_TYPES.ESTABLISH then
|
if packet ~= nil and packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||||
public.handle_packet(packet)
|
public.handle_packet(packet)
|
||||||
end
|
end
|
||||||
elseif event == "terminate" then
|
elseif event == "terminate" then
|
||||||
@ -329,25 +329,25 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send a facility command
|
-- send a facility command
|
||||||
---@param cmd FAC_COMMANDS command
|
---@param cmd FAC_COMMAND command
|
||||||
function public.send_fac_command(cmd)
|
function public.send_fac_command(cmd)
|
||||||
_send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.FAC_CMD, { cmd })
|
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, { cmd })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send the auto process control configuration with a start command
|
-- send the auto process control configuration with a start command
|
||||||
---@param config coord_auto_config configuration
|
---@param config coord_auto_config configuration
|
||||||
function public.send_auto_start(config)
|
function public.send_auto_start(config)
|
||||||
_send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.FAC_CMD, {
|
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, {
|
||||||
FAC_COMMANDS.START, config.mode, config.burn_target, config.charge_target, config.gen_target, config.limits
|
FAC_COMMAND.START, config.mode, config.burn_target, config.charge_target, config.gen_target, config.limits
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send a unit command
|
-- send a unit command
|
||||||
---@param cmd UNIT_COMMANDS command
|
---@param cmd UNIT_COMMAND command
|
||||||
---@param unit integer unit ID
|
---@param unit integer unit ID
|
||||||
---@param option any? optional option options for the optional options (like burn rate) (does option still look like a word?)
|
---@param option any? optional option options for the optional options (like burn rate) (does option still look like a word?)
|
||||||
function public.send_unit_command(cmd, unit, option)
|
function public.send_unit_command(cmd, unit, option)
|
||||||
_send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.UNIT_CMD, { cmd, unit, option })
|
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_CMD, { cmd, unit, option })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- parse a packet
|
-- parse a packet
|
||||||
@ -366,19 +366,19 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
|
|
||||||
if s_pkt.is_valid() then
|
if s_pkt.is_valid() then
|
||||||
-- get as SCADA management packet
|
-- get as SCADA management packet
|
||||||
if s_pkt.protocol() == PROTOCOLS.SCADA_MGMT then
|
if s_pkt.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
local mgmt_pkt = comms.mgmt_packet()
|
local mgmt_pkt = comms.mgmt_packet()
|
||||||
if mgmt_pkt.decode(s_pkt) then
|
if mgmt_pkt.decode(s_pkt) then
|
||||||
pkt = mgmt_pkt.get()
|
pkt = mgmt_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as coordinator packet
|
-- get as coordinator packet
|
||||||
elseif s_pkt.protocol() == PROTOCOLS.SCADA_CRDN then
|
elseif s_pkt.protocol() == PROTOCOL.SCADA_CRDN then
|
||||||
local crdn_pkt = comms.crdn_packet()
|
local crdn_pkt = comms.crdn_packet()
|
||||||
if crdn_pkt.decode(s_pkt) then
|
if crdn_pkt.decode(s_pkt) then
|
||||||
pkt = crdn_pkt.get()
|
pkt = crdn_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as coordinator API packet
|
-- get as coordinator API packet
|
||||||
elseif s_pkt.protocol() == PROTOCOLS.COORD_API then
|
elseif s_pkt.protocol() == PROTOCOL.COORD_API then
|
||||||
local capi_pkt = comms.capi_packet()
|
local capi_pkt = comms.capi_packet()
|
||||||
if capi_pkt.decode(s_pkt) then
|
if capi_pkt.decode(s_pkt) then
|
||||||
pkt = capi_pkt.get()
|
pkt = capi_pkt.get()
|
||||||
@ -399,7 +399,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
local l_port = packet.scada_frame.local_port()
|
local l_port = packet.scada_frame.local_port()
|
||||||
|
|
||||||
if l_port == api_listen then
|
if l_port == api_listen then
|
||||||
if protocol == PROTOCOLS.COORD_API then
|
if protocol == PROTOCOL.COORD_API then
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
apisessions.handle_packet(packet)
|
apisessions.handle_packet(packet)
|
||||||
else
|
else
|
||||||
@ -420,9 +420,9 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
sv_watchdog.feed()
|
sv_watchdog.feed()
|
||||||
|
|
||||||
-- handle packet
|
-- handle packet
|
||||||
if protocol == PROTOCOLS.SCADA_CRDN then
|
if protocol == PROTOCOL.SCADA_CRDN then
|
||||||
if self.sv_linked then
|
if self.sv_linked then
|
||||||
if packet.type == SCADA_CRDN_TYPES.INITIAL_BUILDS then
|
if packet.type == SCADA_CRDN_TYPE.INITIAL_BUILDS then
|
||||||
if packet.length == 2 then
|
if packet.length == 2 then
|
||||||
-- record builds
|
-- record builds
|
||||||
local fac_builds = iocontrol.record_facility_builds(packet.data[1])
|
local fac_builds = iocontrol.record_facility_builds(packet.data[1])
|
||||||
@ -430,47 +430,47 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
|
|
||||||
if fac_builds and unit_builds then
|
if fac_builds and unit_builds then
|
||||||
-- acknowledge receipt of builds
|
-- acknowledge receipt of builds
|
||||||
_send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.INITIAL_BUILDS, {})
|
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.INITIAL_BUILDS, {})
|
||||||
else
|
else
|
||||||
log.error("received invalid INITIAL_BUILDS packet")
|
log.error("received invalid INITIAL_BUILDS packet")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug("INITIAL_BUILDS packet length mismatch")
|
log.debug("INITIAL_BUILDS packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPES.FAC_BUILDS then
|
elseif packet.type == SCADA_CRDN_TYPE.FAC_BUILDS then
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
-- record facility builds
|
-- record facility builds
|
||||||
if iocontrol.record_facility_builds(packet.data[1]) then
|
if iocontrol.record_facility_builds(packet.data[1]) then
|
||||||
-- acknowledge receipt of builds
|
-- acknowledge receipt of builds
|
||||||
_send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.FAC_BUILDS, {})
|
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_BUILDS, {})
|
||||||
else
|
else
|
||||||
log.error("received invalid FAC_BUILDS packet")
|
log.error("received invalid FAC_BUILDS packet")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug("FAC_BUILDS packet length mismatch")
|
log.debug("FAC_BUILDS packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPES.FAC_STATUS then
|
elseif packet.type == SCADA_CRDN_TYPE.FAC_STATUS then
|
||||||
-- update facility status
|
-- update facility status
|
||||||
if not iocontrol.update_facility_status(packet.data) then
|
if not iocontrol.update_facility_status(packet.data) then
|
||||||
log.error("received invalid FAC_STATUS packet")
|
log.error("received invalid FAC_STATUS packet")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPES.FAC_CMD then
|
elseif packet.type == SCADA_CRDN_TYPE.FAC_CMD then
|
||||||
-- facility command acknowledgement
|
-- facility command acknowledgement
|
||||||
if packet.length >= 2 then
|
if packet.length >= 2 then
|
||||||
local cmd = packet.data[1]
|
local cmd = packet.data[1]
|
||||||
local ack = packet.data[2] == true
|
local ack = packet.data[2] == true
|
||||||
|
|
||||||
if cmd == FAC_COMMANDS.SCRAM_ALL then
|
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||||
iocontrol.get_db().facility.scram_ack(ack)
|
iocontrol.get_db().facility.scram_ack(ack)
|
||||||
elseif cmd == FAC_COMMANDS.STOP then
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
iocontrol.get_db().facility.stop_ack(ack)
|
iocontrol.get_db().facility.stop_ack(ack)
|
||||||
elseif cmd == FAC_COMMANDS.START then
|
elseif cmd == FAC_COMMAND.START then
|
||||||
if packet.length == 7 then
|
if packet.length == 7 then
|
||||||
process.start_ack_handle({ table.unpack(packet.data, 2) })
|
process.start_ack_handle({ table.unpack(packet.data, 2) })
|
||||||
else
|
else
|
||||||
log.debug("SCADA_CRDN process start (with configuration) ack echo packet length mismatch")
|
log.debug("SCADA_CRDN process start (with configuration) ack echo packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif cmd == FAC_COMMANDS.ACK_ALL_ALARMS then
|
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||||
iocontrol.get_db().facility.ack_alarms_ack(ack)
|
iocontrol.get_db().facility.ack_alarms_ack(ack)
|
||||||
else
|
else
|
||||||
log.debug(util.c("received facility command ack with unknown command ", cmd))
|
log.debug(util.c("received facility command ack with unknown command ", cmd))
|
||||||
@ -478,24 +478,24 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
else
|
else
|
||||||
log.debug("SCADA_CRDN facility command ack packet length mismatch")
|
log.debug("SCADA_CRDN facility command ack packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPES.UNIT_BUILDS then
|
elseif packet.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
||||||
-- record builds
|
-- record builds
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
if iocontrol.record_unit_builds(packet.data[1]) then
|
if iocontrol.record_unit_builds(packet.data[1]) then
|
||||||
-- acknowledge receipt of builds
|
-- acknowledge receipt of builds
|
||||||
_send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.UNIT_BUILDS, {})
|
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_BUILDS, {})
|
||||||
else
|
else
|
||||||
log.error("received invalid UNIT_BUILDS packet")
|
log.error("received invalid UNIT_BUILDS packet")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug("UNIT_BUILDS packet length mismatch")
|
log.debug("UNIT_BUILDS packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPES.UNIT_STATUSES then
|
elseif packet.type == SCADA_CRDN_TYPE.UNIT_STATUSES then
|
||||||
-- update statuses
|
-- update statuses
|
||||||
if not iocontrol.update_unit_statuses(packet.data) then
|
if not iocontrol.update_unit_statuses(packet.data) then
|
||||||
log.error("received invalid UNIT_STATUSES packet")
|
log.error("received invalid UNIT_STATUSES packet")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPES.UNIT_CMD then
|
elseif packet.type == SCADA_CRDN_TYPE.UNIT_CMD then
|
||||||
-- unit command acknowledgement
|
-- unit command acknowledgement
|
||||||
if packet.length == 3 then
|
if packet.length == 3 then
|
||||||
local cmd = packet.data[1]
|
local cmd = packet.data[1]
|
||||||
@ -505,19 +505,19 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
local unit = iocontrol.get_db().units[unit_id] ---@type ioctl_unit
|
local unit = iocontrol.get_db().units[unit_id] ---@type ioctl_unit
|
||||||
|
|
||||||
if unit ~= nil then
|
if unit ~= nil then
|
||||||
if cmd == UNIT_COMMANDS.SCRAM then
|
if cmd == UNIT_COMMAND.SCRAM then
|
||||||
unit.scram_ack(ack)
|
unit.scram_ack(ack)
|
||||||
elseif cmd == UNIT_COMMANDS.START then
|
elseif cmd == UNIT_COMMAND.START then
|
||||||
unit.start_ack(ack)
|
unit.start_ack(ack)
|
||||||
elseif cmd == UNIT_COMMANDS.RESET_RPS then
|
elseif cmd == UNIT_COMMAND.RESET_RPS then
|
||||||
unit.reset_rps_ack(ack)
|
unit.reset_rps_ack(ack)
|
||||||
elseif cmd == UNIT_COMMANDS.SET_BURN then
|
elseif cmd == UNIT_COMMAND.SET_BURN then
|
||||||
unit.set_burn_ack(ack)
|
unit.set_burn_ack(ack)
|
||||||
elseif cmd == UNIT_COMMANDS.SET_WASTE then
|
elseif cmd == UNIT_COMMAND.SET_WASTE then
|
||||||
unit.set_waste_ack(ack)
|
unit.set_waste_ack(ack)
|
||||||
elseif cmd == UNIT_COMMANDS.ACK_ALL_ALARMS then
|
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||||
unit.ack_alarms_ack(ack)
|
unit.ack_alarms_ack(ack)
|
||||||
elseif cmd == UNIT_COMMANDS.SET_GROUP then
|
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
||||||
---@todo how is this going to be handled?
|
---@todo how is this going to be handled?
|
||||||
else
|
else
|
||||||
log.debug(util.c("received unit command ack with unknown command ", cmd))
|
log.debug(util.c("received unit command ack with unknown command ", cmd))
|
||||||
@ -534,8 +534,8 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
else
|
else
|
||||||
log.debug("discarding SCADA_CRDN packet before linked")
|
log.debug("discarding SCADA_CRDN packet before linked")
|
||||||
end
|
end
|
||||||
elseif protocol == PROTOCOLS.SCADA_MGMT then
|
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||||
if packet.type == SCADA_MGMT_TYPES.ESTABLISH then
|
if packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||||
-- connection with supervisor established
|
-- connection with supervisor established
|
||||||
if packet.length == 2 then
|
if packet.length == 2 then
|
||||||
local est_ack = packet.data[1]
|
local est_ack = packet.data[1]
|
||||||
@ -596,7 +596,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
log.debug("SCADA_MGMT establish packet length mismatch")
|
log.debug("SCADA_MGMT establish packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif self.sv_linked then
|
elseif self.sv_linked then
|
||||||
if packet.type == SCADA_MGMT_TYPES.KEEP_ALIVE then
|
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive request received, echo back
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -614,7 +614,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
|||||||
else
|
else
|
||||||
log.debug("SCADA keep alive packet length mismatch")
|
log.debug("SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.CLOSE then
|
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||||
-- handle session close
|
-- handle session close
|
||||||
sv_watchdog.cancel()
|
sv_watchdog.cancel()
|
||||||
self.sv_linked = false
|
self.sv_linked = false
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
local comms = require("scada-common.comms")
|
|
||||||
local log = require("scada-common.log")
|
local log = require("scada-common.log")
|
||||||
local psil = require("scada-common.psil")
|
local psil = require("scada-common.psil")
|
||||||
local types = require("scada-common.types")
|
local types = require("scada-common.types")
|
||||||
@ -7,8 +6,6 @@ local util = require("scada-common.util")
|
|||||||
local process = require("coordinator.process")
|
local process = require("coordinator.process")
|
||||||
local sounder = require("coordinator.sounder")
|
local sounder = require("coordinator.sounder")
|
||||||
|
|
||||||
local UNIT_COMMANDS = comms.UNIT_COMMANDS
|
|
||||||
|
|
||||||
local ALARM_STATE = types.ALARM_STATE
|
local ALARM_STATE = types.ALARM_STATE
|
||||||
|
|
||||||
local iocontrol = {}
|
local iocontrol = {}
|
||||||
|
@ -4,8 +4,8 @@ local log = require("scada-common.log")
|
|||||||
local types = require("scada-common.types")
|
local types = require("scada-common.types")
|
||||||
local util = require("scada-common.util")
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
local FAC_COMMANDS = comms.FAC_COMMANDS
|
local FAC_COMMAND = comms.FAC_COMMAND
|
||||||
local UNIT_COMMANDS = comms.UNIT_COMMANDS
|
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||||
|
|
||||||
local PROCESS = types.PROCESS
|
local PROCESS = types.PROCESS
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ function process.init(iocontrol, comms)
|
|||||||
|
|
||||||
if type(waste_mode) == "table" then
|
if type(waste_mode) == "table" then
|
||||||
for id, mode in pairs(waste_mode) do
|
for id, mode in pairs(waste_mode) do
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.SET_WASTE, id, mode)
|
self.comms.send_unit_command(UNIT_COMMAND.SET_WASTE, id, mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
log.info("PROCESS: loaded waste mode settings from coord.settings")
|
log.info("PROCESS: loaded waste mode settings from coord.settings")
|
||||||
@ -81,7 +81,7 @@ function process.init(iocontrol, comms)
|
|||||||
|
|
||||||
if type(prio_groups) == "table" then
|
if type(prio_groups) == "table" then
|
||||||
for id, group in pairs(prio_groups) do
|
for id, group in pairs(prio_groups) do
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.SET_GROUP, id, group)
|
self.comms.send_unit_command(UNIT_COMMAND.SET_GROUP, id, group)
|
||||||
end
|
end
|
||||||
|
|
||||||
log.info("PROCESS: loaded priority groups settings from coord.settings")
|
log.info("PROCESS: loaded priority groups settings from coord.settings")
|
||||||
@ -90,13 +90,13 @@ end
|
|||||||
|
|
||||||
-- facility SCRAM command
|
-- facility SCRAM command
|
||||||
function process.fac_scram()
|
function process.fac_scram()
|
||||||
self.comms.send_fac_command(FAC_COMMANDS.SCRAM_ALL)
|
self.comms.send_fac_command(FAC_COMMAND.SCRAM_ALL)
|
||||||
log.debug("FAC: SCRAM ALL")
|
log.debug("FAC: SCRAM ALL")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- facility alarm acknowledge command
|
-- facility alarm acknowledge command
|
||||||
function process.fac_ack_alarms()
|
function process.fac_ack_alarms()
|
||||||
self.comms.send_fac_command(FAC_COMMANDS.ACK_ALL_ALARMS)
|
self.comms.send_fac_command(FAC_COMMAND.ACK_ALL_ALARMS)
|
||||||
log.debug("FAC: ACK ALL ALARMS")
|
log.debug("FAC: ACK ALL ALARMS")
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.start(id)
|
function process.start(id)
|
||||||
self.io.units[id].control_state = true
|
self.io.units[id].control_state = true
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.START, id)
|
self.comms.send_unit_command(UNIT_COMMAND.START, id)
|
||||||
log.debug(util.c("UNIT[", id, "]: START"))
|
log.debug(util.c("UNIT[", id, "]: START"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -112,14 +112,14 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.scram(id)
|
function process.scram(id)
|
||||||
self.io.units[id].control_state = false
|
self.io.units[id].control_state = false
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.SCRAM, id)
|
self.comms.send_unit_command(UNIT_COMMAND.SCRAM, id)
|
||||||
log.debug(util.c("UNIT[", id, "]: SCRAM"))
|
log.debug(util.c("UNIT[", id, "]: SCRAM"))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- reset reactor protection system
|
-- reset reactor protection system
|
||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.reset_rps(id)
|
function process.reset_rps(id)
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.RESET_RPS, id)
|
self.comms.send_unit_command(UNIT_COMMAND.RESET_RPS, id)
|
||||||
log.debug(util.c("UNIT[", id, "]: RESET RPS"))
|
log.debug(util.c("UNIT[", id, "]: RESET RPS"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
---@param rate number burn rate
|
---@param rate number burn rate
|
||||||
function process.set_rate(id, rate)
|
function process.set_rate(id, rate)
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.SET_BURN, id, rate)
|
self.comms.send_unit_command(UNIT_COMMAND.SET_BURN, id, rate)
|
||||||
log.debug(util.c("UNIT[", id, "]: SET BURN = ", rate))
|
log.debug(util.c("UNIT[", id, "]: SET BURN = ", rate))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ function process.set_waste(id, mode)
|
|||||||
-- publish so that if it fails then it gets reset
|
-- publish so that if it fails then it gets reset
|
||||||
self.io.units[id].unit_ps.publish("U_WasteMode", mode)
|
self.io.units[id].unit_ps.publish("U_WasteMode", mode)
|
||||||
|
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.SET_WASTE, id, mode)
|
self.comms.send_unit_command(UNIT_COMMAND.SET_WASTE, id, mode)
|
||||||
log.debug(util.c("UNIT[", id, "]: SET WASTE = ", mode))
|
log.debug(util.c("UNIT[", id, "]: SET WASTE = ", mode))
|
||||||
|
|
||||||
local waste_mode = settings.get("WASTE_MODES") ---@type table|nil
|
local waste_mode = settings.get("WASTE_MODES") ---@type table|nil
|
||||||
@ -159,7 +159,7 @@ end
|
|||||||
-- acknowledge all alarms
|
-- acknowledge all alarms
|
||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
function process.ack_all_alarms(id)
|
function process.ack_all_alarms(id)
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.ACK_ALL_ALARMS, id)
|
self.comms.send_unit_command(UNIT_COMMAND.ACK_ALL_ALARMS, id)
|
||||||
log.debug(util.c("UNIT[", id, "]: ACK ALL ALARMS"))
|
log.debug(util.c("UNIT[", id, "]: ACK ALL ALARMS"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
---@param alarm integer alarm ID
|
---@param alarm integer alarm ID
|
||||||
function process.ack_alarm(id, alarm)
|
function process.ack_alarm(id, alarm)
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.ACK_ALARM, id, alarm)
|
self.comms.send_unit_command(UNIT_COMMAND.ACK_ALARM, id, alarm)
|
||||||
log.debug(util.c("UNIT[", id, "]: ACK ALARM ", alarm))
|
log.debug(util.c("UNIT[", id, "]: ACK ALARM ", alarm))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ end
|
|||||||
---@param id integer unit ID
|
---@param id integer unit ID
|
||||||
---@param alarm integer alarm ID
|
---@param alarm integer alarm ID
|
||||||
function process.reset_alarm(id, alarm)
|
function process.reset_alarm(id, alarm)
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.RESET_ALARM, id, alarm)
|
self.comms.send_unit_command(UNIT_COMMAND.RESET_ALARM, id, alarm)
|
||||||
log.debug(util.c("UNIT[", id, "]: RESET ALARM ", alarm))
|
log.debug(util.c("UNIT[", id, "]: RESET ALARM ", alarm))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ end
|
|||||||
---@param unit_id integer unit ID
|
---@param unit_id integer unit ID
|
||||||
---@param group_id integer|0 group ID or 0 for independent
|
---@param group_id integer|0 group ID or 0 for independent
|
||||||
function process.set_group(unit_id, group_id)
|
function process.set_group(unit_id, group_id)
|
||||||
self.comms.send_unit_command(UNIT_COMMANDS.SET_GROUP, unit_id, group_id)
|
self.comms.send_unit_command(UNIT_COMMAND.SET_GROUP, unit_id, group_id)
|
||||||
log.debug(util.c("UNIT[", unit_id, "]: SET GROUP ", group_id))
|
log.debug(util.c("UNIT[", unit_id, "]: SET GROUP ", group_id))
|
||||||
|
|
||||||
local prio_groups = settings.get("PRIORITY_GROUPS") ---@type table|nil
|
local prio_groups = settings.get("PRIORITY_GROUPS") ---@type table|nil
|
||||||
@ -207,7 +207,7 @@ end
|
|||||||
|
|
||||||
-- stop automatic process control
|
-- stop automatic process control
|
||||||
function process.stop_auto()
|
function process.stop_auto()
|
||||||
self.comms.send_fac_command(FAC_COMMANDS.STOP)
|
self.comms.send_fac_command(FAC_COMMAND.STOP)
|
||||||
log.debug("FAC: STOP AUTO")
|
log.debug("FAC: STOP AUTO")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@ local plc = {}
|
|||||||
|
|
||||||
local rps_status_t = types.rps_status_t
|
local rps_status_t = types.rps_status_t
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPES = comms.DEVICE_TYPES
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||||
local RPLC_TYPES = comms.RPLC_TYPES
|
local RPLC_TYPE = comms.RPLC_TYPE
|
||||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||||
local AUTO_ACK = comms.PLC_AUTO_ACK
|
local AUTO_ACK = comms.PLC_AUTO_ACK
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
@ -444,28 +444,28 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
_conf_channels()
|
_conf_channels()
|
||||||
|
|
||||||
-- send an RPLC packet
|
-- send an RPLC packet
|
||||||
---@param msg_type RPLC_TYPES
|
---@param msg_type RPLC_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send(msg_type, msg)
|
local function _send(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local r_pkt = comms.rplc_packet()
|
local r_pkt = comms.rplc_packet()
|
||||||
|
|
||||||
r_pkt.make(id, msg_type, msg)
|
r_pkt.make(id, msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.RPLC, r_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.RPLC, r_pkt.raw_sendable())
|
||||||
|
|
||||||
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPES
|
---@param msg_type SCADA_MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_packet()
|
local m_pkt = comms.mgmt_packet()
|
||||||
|
|
||||||
m_pkt.make(msg_type, msg)
|
m_pkt.make(msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.SCADA_MGMT, m_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||||
|
|
||||||
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
@ -569,11 +569,11 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
-- keep alive ack
|
-- keep alive ack
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_keep_alive_ack(srv_time)
|
local function _send_keep_alive_ack(srv_time)
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.KEEP_ALIVE, { srv_time, util.time() })
|
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- general ack
|
-- general ack
|
||||||
---@param msg_type RPLC_TYPES
|
---@param msg_type RPLC_TYPE
|
||||||
---@param status boolean|integer
|
---@param status boolean|integer
|
||||||
local function _send_ack(msg_type, status)
|
local function _send_ack(msg_type, status)
|
||||||
_send(msg_type, { status })
|
_send(msg_type, { status })
|
||||||
@ -605,7 +605,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
parallel.waitForAll(table.unpack(tasks))
|
parallel.waitForAll(table.unpack(tasks))
|
||||||
|
|
||||||
if not self.reactor.__p_is_faulted() then
|
if not self.reactor.__p_is_faulted() then
|
||||||
_send(RPLC_TYPES.MEK_STRUCT, mek_data)
|
_send(RPLC_TYPE.MEK_STRUCT, mek_data)
|
||||||
self.resend_build = false
|
self.resend_build = false
|
||||||
else
|
else
|
||||||
log.error("failed to send structure: PPM fault")
|
log.error("failed to send structure: PPM fault")
|
||||||
@ -643,12 +643,12 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
function public.close()
|
function public.close()
|
||||||
conn_watchdog.cancel()
|
conn_watchdog.cancel()
|
||||||
public.unlink()
|
public.unlink()
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.CLOSE, {})
|
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- attempt to establish link with supervisor
|
-- attempt to establish link with supervisor
|
||||||
function public.send_link_req()
|
function public.send_link_req()
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.ESTABLISH, { comms.version, version, DEVICE_TYPES.PLC, id })
|
_send_mgmt(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PLC, id })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send live status information
|
-- send live status information
|
||||||
@ -677,7 +677,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
mek_data -- mekanism status data
|
mek_data -- mekanism status data
|
||||||
}
|
}
|
||||||
|
|
||||||
_send(RPLC_TYPES.STATUS, sys_status)
|
_send(RPLC_TYPE.STATUS, sys_status)
|
||||||
|
|
||||||
if self.resend_build then
|
if self.resend_build then
|
||||||
_send_struct()
|
_send_struct()
|
||||||
@ -688,7 +688,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
-- send reactor protection system status
|
-- send reactor protection system status
|
||||||
function public.send_rps_status()
|
function public.send_rps_status()
|
||||||
if self.linked then
|
if self.linked then
|
||||||
_send(RPLC_TYPES.RPS_STATUS, { rps.is_tripped(), rps.get_trip_cause(), table.unpack(rps.status()) })
|
_send(RPLC_TYPE.RPS_STATUS, { rps.is_tripped(), rps.get_trip_cause(), table.unpack(rps.status()) })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -701,7 +701,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
table.unpack(rps.status())
|
table.unpack(rps.status())
|
||||||
}
|
}
|
||||||
|
|
||||||
_send(RPLC_TYPES.RPS_ALARM, rps_alarm)
|
_send(RPLC_TYPE.RPS_ALARM, rps_alarm)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -721,13 +721,13 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
|
|
||||||
if s_pkt.is_valid() then
|
if s_pkt.is_valid() then
|
||||||
-- get as RPLC packet
|
-- get as RPLC packet
|
||||||
if s_pkt.protocol() == PROTOCOLS.RPLC then
|
if s_pkt.protocol() == PROTOCOL.RPLC then
|
||||||
local rplc_pkt = comms.rplc_packet()
|
local rplc_pkt = comms.rplc_packet()
|
||||||
if rplc_pkt.decode(s_pkt) then
|
if rplc_pkt.decode(s_pkt) then
|
||||||
pkt = rplc_pkt.get()
|
pkt = rplc_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as SCADA management packet
|
-- get as SCADA management packet
|
||||||
elseif s_pkt.protocol() == PROTOCOLS.SCADA_MGMT then
|
elseif s_pkt.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
local mgmt_pkt = comms.mgmt_packet()
|
local mgmt_pkt = comms.mgmt_packet()
|
||||||
if mgmt_pkt.decode(s_pkt) then
|
if mgmt_pkt.decode(s_pkt) then
|
||||||
pkt = mgmt_pkt.get()
|
pkt = mgmt_pkt.get()
|
||||||
@ -762,18 +762,18 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
local protocol = packet.scada_frame.protocol()
|
local protocol = packet.scada_frame.protocol()
|
||||||
|
|
||||||
-- handle packet
|
-- handle packet
|
||||||
if protocol == PROTOCOLS.RPLC then
|
if protocol == PROTOCOL.RPLC then
|
||||||
if self.linked then
|
if self.linked then
|
||||||
if packet.type == RPLC_TYPES.STATUS then
|
if packet.type == RPLC_TYPE.STATUS then
|
||||||
-- request of full status, clear cache first
|
-- request of full status, clear cache first
|
||||||
self.status_cache = nil
|
self.status_cache = nil
|
||||||
public.send_status(plc_state.no_reactor, plc_state.reactor_formed)
|
public.send_status(plc_state.no_reactor, plc_state.reactor_formed)
|
||||||
log.debug("sent out status cache again, did supervisor miss it?")
|
log.debug("sent out status cache again, did supervisor miss it?")
|
||||||
elseif packet.type == RPLC_TYPES.MEK_STRUCT then
|
elseif packet.type == RPLC_TYPE.MEK_STRUCT then
|
||||||
-- request for physical structure
|
-- request for physical structure
|
||||||
_send_struct()
|
_send_struct()
|
||||||
log.debug("sent out structure again, did supervisor miss it?")
|
log.debug("sent out structure again, did supervisor miss it?")
|
||||||
elseif packet.type == RPLC_TYPES.MEK_BURN_RATE then
|
elseif packet.type == RPLC_TYPE.MEK_BURN_RATE then
|
||||||
-- set the burn rate
|
-- set the burn rate
|
||||||
if (packet.length == 2) and (type(packet.data[1]) == "number") then
|
if (packet.length == 2) and (type(packet.data[1]) == "number") then
|
||||||
local success = false
|
local success = false
|
||||||
@ -805,29 +805,29 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
else
|
else
|
||||||
log.debug("RPLC set burn rate packet length mismatch or non-numeric burn rate")
|
log.debug("RPLC set burn rate packet length mismatch or non-numeric burn rate")
|
||||||
end
|
end
|
||||||
elseif packet.type == RPLC_TYPES.RPS_ENABLE then
|
elseif packet.type == RPLC_TYPE.RPS_ENABLE then
|
||||||
-- enable the reactor
|
-- enable the reactor
|
||||||
self.scrammed = false
|
self.scrammed = false
|
||||||
_send_ack(packet.type, rps.activate())
|
_send_ack(packet.type, rps.activate())
|
||||||
elseif packet.type == RPLC_TYPES.RPS_SCRAM then
|
elseif packet.type == RPLC_TYPE.RPS_SCRAM then
|
||||||
-- disable the reactor per manual request
|
-- disable the reactor per manual request
|
||||||
self.scrammed = true
|
self.scrammed = true
|
||||||
rps.trip_manual()
|
rps.trip_manual()
|
||||||
_send_ack(packet.type, true)
|
_send_ack(packet.type, true)
|
||||||
elseif packet.type == RPLC_TYPES.RPS_ASCRAM then
|
elseif packet.type == RPLC_TYPE.RPS_ASCRAM then
|
||||||
-- disable the reactor per automatic request
|
-- disable the reactor per automatic request
|
||||||
self.scrammed = true
|
self.scrammed = true
|
||||||
rps.trip_auto()
|
rps.trip_auto()
|
||||||
_send_ack(packet.type, true)
|
_send_ack(packet.type, true)
|
||||||
elseif packet.type == RPLC_TYPES.RPS_RESET then
|
elseif packet.type == RPLC_TYPE.RPS_RESET then
|
||||||
-- reset the RPS status
|
-- reset the RPS status
|
||||||
rps.reset()
|
rps.reset()
|
||||||
_send_ack(packet.type, true)
|
_send_ack(packet.type, true)
|
||||||
elseif packet.type == RPLC_TYPES.RPS_AUTO_RESET then
|
elseif packet.type == RPLC_TYPE.RPS_AUTO_RESET then
|
||||||
-- reset automatic SCRAM and timeout trips
|
-- reset automatic SCRAM and timeout trips
|
||||||
rps.auto_reset()
|
rps.auto_reset()
|
||||||
_send_ack(packet.type, true)
|
_send_ack(packet.type, true)
|
||||||
elseif packet.type == RPLC_TYPES.AUTO_BURN_RATE then
|
elseif packet.type == RPLC_TYPE.AUTO_BURN_RATE then
|
||||||
-- automatic control requested a new burn rate
|
-- automatic control requested a new burn rate
|
||||||
if (packet.length == 3) and (type(packet.data[1]) == "number") and (type(packet.data[3]) == "number") then
|
if (packet.length == 3) and (type(packet.data[1]) == "number") and (type(packet.data[3]) == "number") then
|
||||||
local ack = AUTO_ACK.FAIL
|
local ack = AUTO_ACK.FAIL
|
||||||
@ -898,9 +898,9 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
else
|
else
|
||||||
log.debug("discarding RPLC packet before linked")
|
log.debug("discarding RPLC packet before linked")
|
||||||
end
|
end
|
||||||
elseif protocol == PROTOCOLS.SCADA_MGMT then
|
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||||
if self.linked then
|
if self.linked then
|
||||||
if packet.type == SCADA_MGMT_TYPES.ESTABLISH then
|
if packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||||
-- link request confirmation
|
-- link request confirmation
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
log.debug("received unsolicited establish response")
|
log.debug("received unsolicited establish response")
|
||||||
@ -933,7 +933,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
else
|
else
|
||||||
log.debug("SCADA_MGMT establish packet length mismatch")
|
log.debug("SCADA_MGMT establish packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.KEEP_ALIVE then
|
elseif packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive request received, echo back
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -949,7 +949,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
else
|
else
|
||||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.CLOSE then
|
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||||
-- handle session close
|
-- handle session close
|
||||||
conn_watchdog.cancel()
|
conn_watchdog.cancel()
|
||||||
public.unlink()
|
public.unlink()
|
||||||
@ -958,7 +958,7 @@ function plc.comms(id, version, modem, local_port, server_port, range, reactor,
|
|||||||
else
|
else
|
||||||
log.warning("received unsupported SCADA_MGMT packet type " .. packet.type)
|
log.warning("received unsupported SCADA_MGMT packet type " .. packet.type)
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.ESTABLISH then
|
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||||
-- link request confirmation
|
-- link request confirmation
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local est_ack = packet.data[1]
|
local est_ack = packet.data[1]
|
||||||
|
42
rtu/rtu.lua
42
rtu/rtu.lua
@ -7,11 +7,11 @@ local modbus = require("rtu.modbus")
|
|||||||
|
|
||||||
local rtu = {}
|
local rtu = {}
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPES = comms.DEVICE_TYPES
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
@ -197,14 +197,14 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
_conf_channels()
|
_conf_channels()
|
||||||
|
|
||||||
-- send a scada management packet
|
-- send a scada management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPES
|
---@param msg_type SCADA_MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send(msg_type, msg)
|
local function _send(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_packet()
|
local m_pkt = comms.mgmt_packet()
|
||||||
|
|
||||||
m_pkt.make(msg_type, msg)
|
m_pkt.make(msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.SCADA_MGMT, m_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||||
|
|
||||||
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
@ -213,7 +213,7 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
-- keep alive ack
|
-- keep alive ack
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_keep_alive_ack(srv_time)
|
local function _send_keep_alive_ack(srv_time)
|
||||||
_send(SCADA_MGMT_TYPES.KEEP_ALIVE, { srv_time, util.time() })
|
_send(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate device advertisement table
|
-- generate device advertisement table
|
||||||
@ -233,7 +233,7 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
unit.reactor
|
unit.reactor
|
||||||
}
|
}
|
||||||
|
|
||||||
if type == RTU_UNIT_TYPES.REDSTONE then
|
if type == RTU_UNIT_TYPE.REDSTONE then
|
||||||
insert(advert, unit.device)
|
insert(advert, unit.device)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
---@param m_pkt modbus_packet
|
---@param m_pkt modbus_packet
|
||||||
function public.send_modbus(m_pkt)
|
function public.send_modbus(m_pkt)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.MODBUS_TCP, m_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.MODBUS_TCP, m_pkt.raw_sendable())
|
||||||
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
self.modem.transmit(self.s_port, self.l_port, s_pkt.raw_sendable())
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
end
|
end
|
||||||
@ -275,25 +275,25 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
function public.close(rtu_state)
|
function public.close(rtu_state)
|
||||||
self.conn_watchdog.cancel()
|
self.conn_watchdog.cancel()
|
||||||
public.unlink(rtu_state)
|
public.unlink(rtu_state)
|
||||||
_send(SCADA_MGMT_TYPES.CLOSE, {})
|
_send(SCADA_MGMT_TYPE.CLOSE, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send establish request (includes advertisement)
|
-- send establish request (includes advertisement)
|
||||||
---@param units table
|
---@param units table
|
||||||
function public.send_establish(units)
|
function public.send_establish(units)
|
||||||
_send(SCADA_MGMT_TYPES.ESTABLISH, { comms.version, self.version, DEVICE_TYPES.RTU, _generate_advertisement(units) })
|
_send(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, self.version, DEVICE_TYPE.RTU, _generate_advertisement(units) })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send capability advertisement
|
-- send capability advertisement
|
||||||
---@param units table
|
---@param units table
|
||||||
function public.send_advertisement(units)
|
function public.send_advertisement(units)
|
||||||
_send(SCADA_MGMT_TYPES.RTU_ADVERT, _generate_advertisement(units))
|
_send(SCADA_MGMT_TYPE.RTU_ADVERT, _generate_advertisement(units))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- notify that a peripheral was remounted
|
-- notify that a peripheral was remounted
|
||||||
---@param unit_index integer RTU unit ID
|
---@param unit_index integer RTU unit ID
|
||||||
function public.send_remounted(unit_index)
|
function public.send_remounted(unit_index)
|
||||||
_send(SCADA_MGMT_TYPES.RTU_DEV_REMOUNT, { unit_index })
|
_send(SCADA_MGMT_TYPE.RTU_DEV_REMOUNT, { unit_index })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- parse a MODBUS/SCADA packet
|
-- parse a MODBUS/SCADA packet
|
||||||
@ -312,13 +312,13 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
|
|
||||||
if s_pkt.is_valid() then
|
if s_pkt.is_valid() then
|
||||||
-- get as MODBUS TCP packet
|
-- get as MODBUS TCP packet
|
||||||
if s_pkt.protocol() == PROTOCOLS.MODBUS_TCP then
|
if s_pkt.protocol() == PROTOCOL.MODBUS_TCP then
|
||||||
local m_pkt = comms.modbus_packet()
|
local m_pkt = comms.modbus_packet()
|
||||||
if m_pkt.decode(s_pkt) then
|
if m_pkt.decode(s_pkt) then
|
||||||
pkt = m_pkt.get()
|
pkt = m_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as SCADA management packet
|
-- get as SCADA management packet
|
||||||
elseif s_pkt.protocol() == PROTOCOLS.SCADA_MGMT then
|
elseif s_pkt.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
local mgmt_pkt = comms.mgmt_packet()
|
local mgmt_pkt = comms.mgmt_packet()
|
||||||
if mgmt_pkt.decode(s_pkt) then
|
if mgmt_pkt.decode(s_pkt) then
|
||||||
pkt = mgmt_pkt.get()
|
pkt = mgmt_pkt.get()
|
||||||
@ -352,7 +352,7 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
|
|
||||||
local protocol = packet.scada_frame.protocol()
|
local protocol = packet.scada_frame.protocol()
|
||||||
|
|
||||||
if protocol == PROTOCOLS.MODBUS_TCP then
|
if protocol == PROTOCOL.MODBUS_TCP then
|
||||||
if rtu_state.linked then
|
if rtu_state.linked then
|
||||||
local return_code = false
|
local return_code = false
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
@ -401,9 +401,9 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
else
|
else
|
||||||
log.debug("discarding MODBUS packet before linked")
|
log.debug("discarding MODBUS packet before linked")
|
||||||
end
|
end
|
||||||
elseif protocol == PROTOCOLS.SCADA_MGMT then
|
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||||
-- SCADA management packet
|
-- SCADA management packet
|
||||||
if packet.type == SCADA_MGMT_TYPES.ESTABLISH then
|
if packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local est_ack = packet.data[1]
|
local est_ack = packet.data[1]
|
||||||
|
|
||||||
@ -434,7 +434,7 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
log.debug("SCADA_MGMT establish packet length mismatch")
|
log.debug("SCADA_MGMT establish packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif rtu_state.linked then
|
elseif rtu_state.linked then
|
||||||
if packet.type == SCADA_MGMT_TYPES.KEEP_ALIVE then
|
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive request received, echo back
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -450,13 +450,13 @@ function rtu.comms(version, modem, local_port, server_port, range, conn_watchdog
|
|||||||
else
|
else
|
||||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.CLOSE then
|
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||||
-- close connection
|
-- close connection
|
||||||
self.conn_watchdog.cancel()
|
self.conn_watchdog.cancel()
|
||||||
public.unlink(rtu_state)
|
public.unlink(rtu_state)
|
||||||
println_ts("server connection closed by remote host")
|
println_ts("server connection closed by remote host")
|
||||||
log.warning("server connection closed by remote host")
|
log.warning("server connection closed by remote host")
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.RTU_ADVERT then
|
elseif packet.type == SCADA_MGMT_TYPE.RTU_ADVERT then
|
||||||
-- request for capabilities again
|
-- request for capabilities again
|
||||||
public.send_advertisement(units)
|
public.send_advertisement(units)
|
||||||
else
|
else
|
||||||
|
@ -16,8 +16,8 @@ local max_distance = nil
|
|||||||
|
|
||||||
comms.version = "1.4.0"
|
comms.version = "1.4.0"
|
||||||
|
|
||||||
---@enum PROTOCOLS
|
---@enum PROTOCOL
|
||||||
local PROTOCOLS = {
|
local PROTOCOL = {
|
||||||
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
||||||
RPLC = 1, -- reactor PLC protocol
|
RPLC = 1, -- reactor PLC protocol
|
||||||
SCADA_MGMT = 2, -- SCADA supervisor management, device advertisements, etc
|
SCADA_MGMT = 2, -- SCADA supervisor management, device advertisements, etc
|
||||||
@ -25,8 +25,8 @@ local PROTOCOLS = {
|
|||||||
COORD_API = 4 -- data/control packets for pocket computers to/from coordinators
|
COORD_API = 4 -- data/control packets for pocket computers to/from coordinators
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum RPLC_TYPES
|
---@enum RPLC_TYPE
|
||||||
local RPLC_TYPES = {
|
local RPLC_TYPE = {
|
||||||
STATUS = 0, -- reactor/system status
|
STATUS = 0, -- reactor/system status
|
||||||
MEK_STRUCT = 1, -- mekanism build structure
|
MEK_STRUCT = 1, -- mekanism build structure
|
||||||
MEK_BURN_RATE = 2, -- set burn rate
|
MEK_BURN_RATE = 2, -- set burn rate
|
||||||
@ -40,8 +40,8 @@ local RPLC_TYPES = {
|
|||||||
AUTO_BURN_RATE = 10 -- set an automatic burn rate, PLC will respond with status, enable toggle speed limited
|
AUTO_BURN_RATE = 10 -- set an automatic burn rate, PLC will respond with status, enable toggle speed limited
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum SCADA_MGMT_TYPES
|
---@enum SCADA_MGMT_TYPE
|
||||||
local SCADA_MGMT_TYPES = {
|
local SCADA_MGMT_TYPE = {
|
||||||
ESTABLISH = 0, -- establish new connection
|
ESTABLISH = 0, -- establish new connection
|
||||||
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
||||||
CLOSE = 2, -- close a connection
|
CLOSE = 2, -- close a connection
|
||||||
@ -49,8 +49,8 @@ local SCADA_MGMT_TYPES = {
|
|||||||
RTU_DEV_REMOUNT = 4 -- RTU multiblock possbily changed (formed, unformed) due to PPM remount
|
RTU_DEV_REMOUNT = 4 -- RTU multiblock possbily changed (formed, unformed) due to PPM remount
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum SCADA_CRDN_TYPES
|
---@enum SCADA_CRDN_TYPE
|
||||||
local SCADA_CRDN_TYPES = {
|
local SCADA_CRDN_TYPE = {
|
||||||
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
||||||
FAC_BUILDS = 1, -- facility RTU builds
|
FAC_BUILDS = 1, -- facility RTU builds
|
||||||
FAC_STATUS = 2, -- state of facility and facility devices
|
FAC_STATUS = 2, -- state of facility and facility devices
|
||||||
@ -60,8 +60,8 @@ local SCADA_CRDN_TYPES = {
|
|||||||
UNIT_CMD = 6 -- command a reactor unit
|
UNIT_CMD = 6 -- command a reactor unit
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum CAPI_TYPES
|
---@enum CAPI_TYPE
|
||||||
local CAPI_TYPES = {
|
local CAPI_TYPE = {
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum ESTABLISH_ACK
|
---@enum ESTABLISH_ACK
|
||||||
@ -72,16 +72,16 @@ local ESTABLISH_ACK = {
|
|||||||
BAD_VERSION = 3 -- link denied due to comms version mismatch
|
BAD_VERSION = 3 -- link denied due to comms version mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum DEVICE_TYPES
|
---@enum DEVICE_TYPE
|
||||||
local DEVICE_TYPES = {
|
local DEVICE_TYPE = {
|
||||||
PLC = 0, -- PLC device type for establish
|
PLC = 0, -- PLC device type for establish
|
||||||
RTU = 1, -- RTU device type for establish
|
RTU = 1, -- RTU device type for establish
|
||||||
SV = 2, -- supervisor device type for establish
|
SV = 2, -- supervisor device type for establish
|
||||||
CRDN = 3 -- coordinator device type for establish
|
CRDN = 3 -- coordinator device type for establish
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum RTU_UNIT_TYPES
|
---@enum RTU_UNIT_TYPE
|
||||||
local RTU_UNIT_TYPES = {
|
local RTU_UNIT_TYPE = {
|
||||||
REDSTONE = 0, -- redstone I/O
|
REDSTONE = 0, -- redstone I/O
|
||||||
BOILER_VALVE = 1, -- boiler mekanism 10.1+
|
BOILER_VALVE = 1, -- boiler mekanism 10.1+
|
||||||
TURBINE_VALVE = 2, -- turbine, mekanism 10.1+
|
TURBINE_VALVE = 2, -- turbine, mekanism 10.1+
|
||||||
@ -99,16 +99,16 @@ local PLC_AUTO_ACK = {
|
|||||||
ZERO_DIS_OK = 3 -- successfully disabled reactor with < 0.01 burn rate
|
ZERO_DIS_OK = 3 -- successfully disabled reactor with < 0.01 burn rate
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum FAC_COMMANDS
|
---@enum FAC_COMMAND
|
||||||
local FAC_COMMANDS = {
|
local FAC_COMMAND = {
|
||||||
SCRAM_ALL = 0, -- SCRAM all reactors
|
SCRAM_ALL = 0, -- SCRAM all reactors
|
||||||
STOP = 1, -- stop automatic control
|
STOP = 1, -- stop automatic control
|
||||||
START = 2, -- start automatic control
|
START = 2, -- start automatic control
|
||||||
ACK_ALL_ALARMS = 3 -- acknowledge all alarms on all units
|
ACK_ALL_ALARMS = 3 -- acknowledge all alarms on all units
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum UNIT_COMMANDS
|
---@enum UNIT_COMMAND
|
||||||
local UNIT_COMMANDS = {
|
local UNIT_COMMAND = {
|
||||||
SCRAM = 0, -- SCRAM the reactor
|
SCRAM = 0, -- SCRAM the reactor
|
||||||
START = 1, -- start the reactor
|
START = 1, -- start the reactor
|
||||||
RESET_RPS = 2, -- reset the RPS
|
RESET_RPS = 2, -- reset the RPS
|
||||||
@ -120,26 +120,26 @@ local UNIT_COMMANDS = {
|
|||||||
SET_GROUP = 8 -- assign this unit to a group
|
SET_GROUP = 8 -- assign this unit to a group
|
||||||
}
|
}
|
||||||
|
|
||||||
comms.PROTOCOLS = PROTOCOLS
|
comms.PROTOCOL = PROTOCOL
|
||||||
|
|
||||||
comms.RPLC_TYPES = RPLC_TYPES
|
comms.RPLC_TYPE = RPLC_TYPE
|
||||||
comms.SCADA_MGMT_TYPES = SCADA_MGMT_TYPES
|
comms.SCADA_MGMT_TYPE = SCADA_MGMT_TYPE
|
||||||
comms.SCADA_CRDN_TYPES = SCADA_CRDN_TYPES
|
comms.SCADA_CRDN_TYPE = SCADA_CRDN_TYPE
|
||||||
comms.CAPI_TYPES = CAPI_TYPES
|
comms.CAPI_TYPE = CAPI_TYPE
|
||||||
|
|
||||||
comms.ESTABLISH_ACK = ESTABLISH_ACK
|
comms.ESTABLISH_ACK = ESTABLISH_ACK
|
||||||
comms.DEVICE_TYPES = DEVICE_TYPES
|
comms.DEVICE_TYPE = DEVICE_TYPE
|
||||||
comms.RTU_UNIT_TYPES = RTU_UNIT_TYPES
|
comms.RTU_UNIT_TYPE = RTU_UNIT_TYPE
|
||||||
|
|
||||||
comms.PLC_AUTO_ACK = PLC_AUTO_ACK
|
comms.PLC_AUTO_ACK = PLC_AUTO_ACK
|
||||||
|
|
||||||
comms.UNIT_COMMANDS = UNIT_COMMANDS
|
comms.UNIT_COMMAND = UNIT_COMMAND
|
||||||
comms.FAC_COMMANDS = FAC_COMMANDS
|
comms.FAC_COMMAND = FAC_COMMAND
|
||||||
|
|
||||||
---@alias packet scada_packet|modbus_packet|rplc_packet|mgmt_packet|crdn_packet|capi_packet
|
---@alias packet scada_packet|modbus_packet|rplc_packet|mgmt_packet|crdn_packet|capi_packet
|
||||||
---@alias frame modbus_frame|rplc_frame|mgmt_frame|crdn_frame|capi_frame
|
---@alias frame modbus_frame|rplc_frame|mgmt_frame|crdn_frame|capi_frame
|
||||||
|
|
||||||
-- configure the maximum allowable message receive distance <br/>
|
-- configure the maximum allowable message receive distance<br>
|
||||||
-- packets received with distances greater than this will be silently discarded
|
-- packets received with distances greater than this will be silently discarded
|
||||||
---@param distance integer max modem message distance (less than 1 disables the limit)
|
---@param distance integer max modem message distance (less than 1 disables the limit)
|
||||||
function comms.set_trusted_range(distance)
|
function comms.set_trusted_range(distance)
|
||||||
@ -168,7 +168,7 @@ function comms.scada_packet()
|
|||||||
|
|
||||||
-- make a SCADA packet
|
-- make a SCADA packet
|
||||||
---@param seq_num integer
|
---@param seq_num integer
|
||||||
---@param protocol PROTOCOLS
|
---@param protocol PROTOCOL
|
||||||
---@param payload table
|
---@param payload table
|
||||||
function public.make(seq_num, protocol, payload)
|
function public.make(seq_num, protocol, payload)
|
||||||
self.valid = true
|
self.valid = true
|
||||||
@ -296,7 +296,7 @@ function comms.modbus_packet()
|
|||||||
if frame then
|
if frame then
|
||||||
self.frame = frame
|
self.frame = frame
|
||||||
|
|
||||||
if frame.protocol() == PROTOCOLS.MODBUS_TCP then
|
if frame.protocol() == PROTOCOL.MODBUS_TCP then
|
||||||
local size_ok = frame.length() >= 3
|
local size_ok = frame.length() >= 3
|
||||||
|
|
||||||
if size_ok then
|
if size_ok then
|
||||||
@ -359,22 +359,22 @@ function comms.rplc_packet()
|
|||||||
|
|
||||||
-- check that type is known
|
-- check that type is known
|
||||||
local function _rplc_type_valid()
|
local function _rplc_type_valid()
|
||||||
return self.type == RPLC_TYPES.STATUS or
|
return self.type == RPLC_TYPE.STATUS or
|
||||||
self.type == RPLC_TYPES.MEK_STRUCT or
|
self.type == RPLC_TYPE.MEK_STRUCT or
|
||||||
self.type == RPLC_TYPES.MEK_BURN_RATE or
|
self.type == RPLC_TYPE.MEK_BURN_RATE or
|
||||||
self.type == RPLC_TYPES.RPS_ENABLE or
|
self.type == RPLC_TYPE.RPS_ENABLE or
|
||||||
self.type == RPLC_TYPES.RPS_SCRAM or
|
self.type == RPLC_TYPE.RPS_SCRAM or
|
||||||
self.type == RPLC_TYPES.RPS_ASCRAM or
|
self.type == RPLC_TYPE.RPS_ASCRAM or
|
||||||
self.type == RPLC_TYPES.RPS_STATUS or
|
self.type == RPLC_TYPE.RPS_STATUS or
|
||||||
self.type == RPLC_TYPES.RPS_ALARM or
|
self.type == RPLC_TYPE.RPS_ALARM or
|
||||||
self.type == RPLC_TYPES.RPS_RESET or
|
self.type == RPLC_TYPE.RPS_RESET or
|
||||||
self.type == RPLC_TYPES.RPS_AUTO_RESET or
|
self.type == RPLC_TYPE.RPS_AUTO_RESET or
|
||||||
self.type == RPLC_TYPES.AUTO_BURN_RATE
|
self.type == RPLC_TYPE.AUTO_BURN_RATE
|
||||||
end
|
end
|
||||||
|
|
||||||
-- make an RPLC packet
|
-- make an RPLC packet
|
||||||
---@param id integer
|
---@param id integer
|
||||||
---@param packet_type RPLC_TYPES
|
---@param packet_type RPLC_TYPE
|
||||||
---@param data table
|
---@param data table
|
||||||
function public.make(id, packet_type, data)
|
function public.make(id, packet_type, data)
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
@ -401,7 +401,7 @@ function comms.rplc_packet()
|
|||||||
if frame then
|
if frame then
|
||||||
self.frame = frame
|
self.frame = frame
|
||||||
|
|
||||||
if frame.protocol() == PROTOCOLS.RPLC then
|
if frame.protocol() == PROTOCOL.RPLC then
|
||||||
local ok = frame.length() >= 2
|
local ok = frame.length() >= 2
|
||||||
|
|
||||||
if ok then
|
if ok then
|
||||||
@ -461,16 +461,16 @@ function comms.mgmt_packet()
|
|||||||
|
|
||||||
-- check that type is known
|
-- check that type is known
|
||||||
local function _scada_type_valid()
|
local function _scada_type_valid()
|
||||||
return self.type == SCADA_MGMT_TYPES.ESTABLISH or
|
return self.type == SCADA_MGMT_TYPE.ESTABLISH or
|
||||||
self.type == SCADA_MGMT_TYPES.KEEP_ALIVE or
|
self.type == SCADA_MGMT_TYPE.KEEP_ALIVE or
|
||||||
self.type == SCADA_MGMT_TYPES.CLOSE or
|
self.type == SCADA_MGMT_TYPE.CLOSE or
|
||||||
self.type == SCADA_MGMT_TYPES.REMOTE_LINKED or
|
self.type == SCADA_MGMT_TYPE.REMOTE_LINKED or
|
||||||
self.type == SCADA_MGMT_TYPES.RTU_ADVERT or
|
self.type == SCADA_MGMT_TYPE.RTU_ADVERT or
|
||||||
self.type == SCADA_MGMT_TYPES.RTU_DEV_REMOUNT
|
self.type == SCADA_MGMT_TYPE.RTU_DEV_REMOUNT
|
||||||
end
|
end
|
||||||
|
|
||||||
-- make a SCADA management packet
|
-- make a SCADA management packet
|
||||||
---@param packet_type SCADA_MGMT_TYPES
|
---@param packet_type SCADA_MGMT_TYPE
|
||||||
---@param data table
|
---@param data table
|
||||||
function public.make(packet_type, data)
|
function public.make(packet_type, data)
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
@ -496,7 +496,7 @@ function comms.mgmt_packet()
|
|||||||
if frame then
|
if frame then
|
||||||
self.frame = frame
|
self.frame = frame
|
||||||
|
|
||||||
if frame.protocol() == PROTOCOLS.SCADA_MGMT then
|
if frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
local ok = frame.length() >= 1
|
local ok = frame.length() >= 1
|
||||||
|
|
||||||
if ok then
|
if ok then
|
||||||
@ -554,17 +554,17 @@ function comms.crdn_packet()
|
|||||||
-- check that type is known
|
-- check that type is known
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
local function _crdn_type_valid()
|
local function _crdn_type_valid()
|
||||||
return self.type == SCADA_CRDN_TYPES.INITIAL_BUILDS or
|
return self.type == SCADA_CRDN_TYPE.INITIAL_BUILDS or
|
||||||
self.type == SCADA_CRDN_TYPES.FAC_BUILDS or
|
self.type == SCADA_CRDN_TYPE.FAC_BUILDS or
|
||||||
self.type == SCADA_CRDN_TYPES.FAC_STATUS or
|
self.type == SCADA_CRDN_TYPE.FAC_STATUS or
|
||||||
self.type == SCADA_CRDN_TYPES.FAC_CMD or
|
self.type == SCADA_CRDN_TYPE.FAC_CMD or
|
||||||
self.type == SCADA_CRDN_TYPES.UNIT_BUILDS or
|
self.type == SCADA_CRDN_TYPE.UNIT_BUILDS or
|
||||||
self.type == SCADA_CRDN_TYPES.UNIT_STATUSES or
|
self.type == SCADA_CRDN_TYPE.UNIT_STATUSES or
|
||||||
self.type == SCADA_CRDN_TYPES.UNIT_CMD
|
self.type == SCADA_CRDN_TYPE.UNIT_CMD
|
||||||
end
|
end
|
||||||
|
|
||||||
-- make a coordinator packet
|
-- make a coordinator packet
|
||||||
---@param packet_type SCADA_CRDN_TYPES
|
---@param packet_type SCADA_CRDN_TYPE
|
||||||
---@param data table
|
---@param data table
|
||||||
function public.make(packet_type, data)
|
function public.make(packet_type, data)
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
@ -590,7 +590,7 @@ function comms.crdn_packet()
|
|||||||
if frame then
|
if frame then
|
||||||
self.frame = frame
|
self.frame = frame
|
||||||
|
|
||||||
if frame.protocol() == PROTOCOLS.SCADA_CRDN then
|
if frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||||
local ok = frame.length() >= 1
|
local ok = frame.length() >= 1
|
||||||
|
|
||||||
if ok then
|
if ok then
|
||||||
@ -652,7 +652,7 @@ function comms.capi_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- make a coordinator API packet
|
-- make a coordinator API packet
|
||||||
---@param packet_type CAPI_TYPES
|
---@param packet_type CAPI_TYPE
|
||||||
---@param data table
|
---@param data table
|
||||||
function public.make(packet_type, data)
|
function public.make(packet_type, data)
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
@ -678,7 +678,7 @@ function comms.capi_packet()
|
|||||||
if frame then
|
if frame then
|
||||||
self.frame = frame
|
self.frame = frame
|
||||||
|
|
||||||
if frame.protocol() == PROTOCOLS.COORD_API then
|
if frame.protocol() == PROTOCOL.COORD_API then
|
||||||
local ok = frame.length() >= 1
|
local ok = frame.length() >= 1
|
||||||
|
|
||||||
if ok then
|
if ok then
|
||||||
@ -722,22 +722,22 @@ end
|
|||||||
-- convert rtu_t to RTU unit type
|
-- convert rtu_t to RTU unit type
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param type rtu_t
|
---@param type rtu_t
|
||||||
---@return RTU_UNIT_TYPES|nil
|
---@return RTU_UNIT_TYPE|nil
|
||||||
function comms.rtu_t_to_unit_type(type)
|
function comms.rtu_t_to_unit_type(type)
|
||||||
if type == rtu_t.redstone then
|
if type == rtu_t.redstone then
|
||||||
return RTU_UNIT_TYPES.REDSTONE
|
return RTU_UNIT_TYPE.REDSTONE
|
||||||
elseif type == rtu_t.boiler_valve then
|
elseif type == rtu_t.boiler_valve then
|
||||||
return RTU_UNIT_TYPES.BOILER_VALVE
|
return RTU_UNIT_TYPE.BOILER_VALVE
|
||||||
elseif type == rtu_t.turbine_valve then
|
elseif type == rtu_t.turbine_valve then
|
||||||
return RTU_UNIT_TYPES.TURBINE_VALVE
|
return RTU_UNIT_TYPE.TURBINE_VALVE
|
||||||
elseif type == rtu_t.induction_matrix then
|
elseif type == rtu_t.induction_matrix then
|
||||||
return RTU_UNIT_TYPES.IMATRIX
|
return RTU_UNIT_TYPE.IMATRIX
|
||||||
elseif type == rtu_t.sps then
|
elseif type == rtu_t.sps then
|
||||||
return RTU_UNIT_TYPES.SPS
|
return RTU_UNIT_TYPE.SPS
|
||||||
elseif type == rtu_t.sna then
|
elseif type == rtu_t.sna then
|
||||||
return RTU_UNIT_TYPES.SNA
|
return RTU_UNIT_TYPE.SNA
|
||||||
elseif type == rtu_t.env_detector then
|
elseif type == rtu_t.env_detector then
|
||||||
return RTU_UNIT_TYPES.ENV_DETECTOR
|
return RTU_UNIT_TYPE.ENV_DETECTOR
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -745,22 +745,22 @@ end
|
|||||||
|
|
||||||
-- convert RTU unit type to rtu_t
|
-- convert RTU unit type to rtu_t
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param utype RTU_UNIT_TYPES
|
---@param utype RTU_UNIT_TYPE
|
||||||
---@return rtu_t|nil
|
---@return rtu_t|nil
|
||||||
function comms.advert_type_to_rtu_t(utype)
|
function comms.advert_type_to_rtu_t(utype)
|
||||||
if utype == RTU_UNIT_TYPES.REDSTONE then
|
if utype == RTU_UNIT_TYPE.REDSTONE then
|
||||||
return rtu_t.redstone
|
return rtu_t.redstone
|
||||||
elseif utype == RTU_UNIT_TYPES.BOILER_VALVE then
|
elseif utype == RTU_UNIT_TYPE.BOILER_VALVE then
|
||||||
return rtu_t.boiler_valve
|
return rtu_t.boiler_valve
|
||||||
elseif utype == RTU_UNIT_TYPES.TURBINE_VALVE then
|
elseif utype == RTU_UNIT_TYPE.TURBINE_VALVE then
|
||||||
return rtu_t.turbine_valve
|
return rtu_t.turbine_valve
|
||||||
elseif utype == RTU_UNIT_TYPES.IMATRIX then
|
elseif utype == RTU_UNIT_TYPE.IMATRIX then
|
||||||
return rtu_t.induction_matrix
|
return rtu_t.induction_matrix
|
||||||
elseif utype == RTU_UNIT_TYPES.SPS then
|
elseif utype == RTU_UNIT_TYPE.SPS then
|
||||||
return rtu_t.sps
|
return rtu_t.sps
|
||||||
elseif utype == RTU_UNIT_TYPES.SNA then
|
elseif utype == RTU_UNIT_TYPE.SNA then
|
||||||
return rtu_t.sna
|
return rtu_t.sna
|
||||||
elseif utype == RTU_UNIT_TYPES.ENV_DETECTOR then
|
elseif utype == RTU_UNIT_TYPE.ENV_DETECTOR then
|
||||||
return rtu_t.env_detector
|
return rtu_t.env_detector
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ function types.new_coordinate(x, y, z) return { x = x, y = y, z = z } end
|
|||||||
function types.new_zero_coordinate() return { x = 0, y = 0, z = 0 } end
|
function types.new_zero_coordinate() return { x = 0, y = 0, z = 0 } end
|
||||||
|
|
||||||
---@class rtu_advertisement
|
---@class rtu_advertisement
|
||||||
---@field type RTU_UNIT_TYPES
|
---@field type RTU_UNIT_TYPE
|
||||||
---@field index integer
|
---@field index integer
|
||||||
---@field reactor integer
|
---@field reactor integer
|
||||||
---@field rsio table|nil
|
---@field rsio table|nil
|
||||||
|
@ -12,7 +12,7 @@ local PROCESS_NAMES = types.PROCESS_NAMES
|
|||||||
|
|
||||||
local IO = rsio.IO
|
local IO = rsio.IO
|
||||||
|
|
||||||
-- 7.14 kJ per blade for 1 mB of fissile fuel<br/>
|
-- 7.14 kJ per blade for 1 mB of fissile fuel<br>
|
||||||
-- 2856 FE per blade per 1 mB, 285.6 FE per blade per 0.1 mB (minimum)
|
-- 2856 FE per blade per 1 mB, 285.6 FE per blade per 0.1 mB (minimum)
|
||||||
local POWER_PER_BLADE = util.joules_to_fe(7140)
|
local POWER_PER_BLADE = util.joules_to_fe(7140)
|
||||||
|
|
||||||
|
@ -7,12 +7,12 @@ local svqtypes = require("supervisor.session.svqtypes")
|
|||||||
|
|
||||||
local coordinator = {}
|
local coordinator = {}
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||||
local SCADA_CRDN_TYPES = comms.SCADA_CRDN_TYPES
|
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
||||||
local UNIT_COMMANDS = comms.UNIT_COMMANDS
|
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||||
local FAC_COMMANDS = comms.FAC_COMMANDS
|
local FAC_COMMAND = comms.FAC_COMMAND
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
|
|
||||||
local SV_Q_CMDS = svqtypes.SV_Q_CMDS
|
local SV_Q_CMDS = svqtypes.SV_Q_CMDS
|
||||||
local SV_Q_DATA = svqtypes.SV_Q_DATA
|
local SV_Q_DATA = svqtypes.SV_Q_DATA
|
||||||
@ -90,28 +90,28 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send a CRDN packet
|
-- send a CRDN packet
|
||||||
---@param msg_type SCADA_CRDN_TYPES
|
---@param msg_type SCADA_CRDN_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send(msg_type, msg)
|
local function _send(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local c_pkt = comms.crdn_packet()
|
local c_pkt = comms.crdn_packet()
|
||||||
|
|
||||||
c_pkt.make(msg_type, msg)
|
c_pkt.make(msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.SCADA_CRDN, c_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.SCADA_CRDN, c_pkt.raw_sendable())
|
||||||
|
|
||||||
self.out_q.push_packet(s_pkt)
|
self.out_q.push_packet(s_pkt)
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPES
|
---@param msg_type SCADA_MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_packet()
|
local m_pkt = comms.mgmt_packet()
|
||||||
|
|
||||||
m_pkt.make(msg_type, msg)
|
m_pkt.make(msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.SCADA_MGMT, m_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||||
|
|
||||||
self.out_q.push_packet(s_pkt)
|
self.out_q.push_packet(s_pkt)
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
@ -126,12 +126,12 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
unit_builds[unit.get_id()] = unit.get_build()
|
unit_builds[unit.get_id()] = unit.get_build()
|
||||||
end
|
end
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
_send(SCADA_CRDN_TYPE.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send facility builds
|
-- send facility builds
|
||||||
local function _send_fac_builds()
|
local function _send_fac_builds()
|
||||||
_send(SCADA_CRDN_TYPES.FAC_BUILDS, { facility.get_build() })
|
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build() })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send unit builds
|
-- send unit builds
|
||||||
@ -143,7 +143,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
builds[unit.get_id()] = unit.get_build()
|
builds[unit.get_id()] = unit.get_build()
|
||||||
end
|
end
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.UNIT_BUILDS, { builds })
|
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send facility status
|
-- send facility status
|
||||||
@ -153,7 +153,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
facility.get_rtu_statuses()
|
facility.get_rtu_statuses()
|
||||||
}
|
}
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.FAC_STATUS, status)
|
_send(SCADA_CRDN_TYPE.FAC_STATUS, status)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send unit statuses
|
-- send unit statuses
|
||||||
@ -172,7 +172,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.UNIT_STATUSES, status)
|
_send(SCADA_CRDN_TYPE.UNIT_STATUSES, status)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- handle a packet
|
-- handle a packet
|
||||||
@ -192,8 +192,8 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
self.conn_watchdog.feed()
|
self.conn_watchdog.feed()
|
||||||
|
|
||||||
-- process packet
|
-- process packet
|
||||||
if pkt.scada_frame.protocol() == PROTOCOLS.SCADA_MGMT then
|
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
if pkt.type == SCADA_MGMT_TYPES.KEEP_ALIVE then
|
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
@ -210,30 +210,30 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPES.CLOSE then
|
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_close()
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
||||||
end
|
end
|
||||||
elseif pkt.scada_frame.protocol() == PROTOCOLS.SCADA_CRDN then
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||||
if pkt.type == SCADA_CRDN_TYPES.INITIAL_BUILDS then
|
if pkt.type == SCADA_CRDN_TYPE.INITIAL_BUILDS then
|
||||||
-- acknowledgement to coordinator receiving builds
|
-- acknowledgement to coordinator receiving builds
|
||||||
self.acks.builds = true
|
self.acks.builds = true
|
||||||
elseif pkt.type == SCADA_CRDN_TYPES.FAC_BUILDS then
|
elseif pkt.type == SCADA_CRDN_TYPE.FAC_BUILDS then
|
||||||
-- acknowledgement to coordinator receiving builds
|
-- acknowledgement to coordinator receiving builds
|
||||||
self.acks.fac_builds = true
|
self.acks.fac_builds = true
|
||||||
elseif pkt.type == SCADA_CRDN_TYPES.FAC_CMD then
|
elseif pkt.type == SCADA_CRDN_TYPE.FAC_CMD then
|
||||||
if pkt.length >= 1 then
|
if pkt.length >= 1 then
|
||||||
local cmd = pkt.data[1]
|
local cmd = pkt.data[1]
|
||||||
|
|
||||||
if cmd == FAC_COMMANDS.SCRAM_ALL then
|
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||||
facility.scram_all()
|
facility.scram_all()
|
||||||
_send(SCADA_CRDN_TYPES.FAC_CMD, { cmd, true })
|
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||||
elseif cmd == FAC_COMMANDS.STOP then
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
facility.auto_stop()
|
facility.auto_stop()
|
||||||
_send(SCADA_CRDN_TYPES.FAC_CMD, { cmd, true })
|
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||||
elseif cmd == FAC_COMMANDS.START then
|
elseif cmd == FAC_COMMAND.START then
|
||||||
if pkt.length == 6 then
|
if pkt.length == 6 then
|
||||||
---@type coord_auto_config
|
---@type coord_auto_config
|
||||||
local config = {
|
local config = {
|
||||||
@ -244,23 +244,23 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
limits = pkt.data[6]
|
limits = pkt.data[6]
|
||||||
}
|
}
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.FAC_CMD, { cmd, table.unpack(facility.auto_start(config)) })
|
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, table.unpack(facility.auto_start(config)) })
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN auto start (with configuration) packet length mismatch")
|
log.debug(log_header .. "CRDN auto start (with configuration) packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif cmd == FAC_COMMANDS.ACK_ALL_ALARMS then
|
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||||
facility.ack_all()
|
facility.ack_all()
|
||||||
_send(SCADA_CRDN_TYPES.FAC_CMD, { cmd, true })
|
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN facility command unknown")
|
log.debug(log_header .. "CRDN facility command unknown")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN facility command packet length mismatch")
|
log.debug(log_header .. "CRDN facility command packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_CRDN_TYPES.UNIT_BUILDS then
|
elseif pkt.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
||||||
-- acknowledgement to coordinator receiving builds
|
-- acknowledgement to coordinator receiving builds
|
||||||
self.acks.unit_builds = true
|
self.acks.unit_builds = true
|
||||||
elseif pkt.type == SCADA_CRDN_TYPES.UNIT_CMD then
|
elseif pkt.type == SCADA_CRDN_TYPE.UNIT_CMD then
|
||||||
if pkt.length >= 2 then
|
if pkt.length >= 2 then
|
||||||
-- get command and unit id
|
-- get command and unit id
|
||||||
local cmd = pkt.data[1]
|
local cmd = pkt.data[1]
|
||||||
@ -273,43 +273,43 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
if util.is_int(uid) and uid > 0 and uid <= #self.units then
|
if util.is_int(uid) and uid > 0 and uid <= #self.units then
|
||||||
local unit = self.units[uid] ---@type reactor_unit
|
local unit = self.units[uid] ---@type reactor_unit
|
||||||
|
|
||||||
if cmd == UNIT_COMMANDS.START then
|
if cmd == UNIT_COMMAND.START then
|
||||||
self.out_q.push_data(SV_Q_DATA.START, data)
|
self.out_q.push_data(SV_Q_DATA.START, data)
|
||||||
elseif cmd == UNIT_COMMANDS.SCRAM then
|
elseif cmd == UNIT_COMMAND.SCRAM then
|
||||||
self.out_q.push_data(SV_Q_DATA.SCRAM, data)
|
self.out_q.push_data(SV_Q_DATA.SCRAM, data)
|
||||||
elseif cmd == UNIT_COMMANDS.RESET_RPS then
|
elseif cmd == UNIT_COMMAND.RESET_RPS then
|
||||||
self.out_q.push_data(SV_Q_DATA.RESET_RPS, data)
|
self.out_q.push_data(SV_Q_DATA.RESET_RPS, data)
|
||||||
elseif cmd == UNIT_COMMANDS.SET_BURN then
|
elseif cmd == UNIT_COMMAND.SET_BURN then
|
||||||
if pkt.length == 3 then
|
if pkt.length == 3 then
|
||||||
self.out_q.push_data(SV_Q_DATA.SET_BURN, data)
|
self.out_q.push_data(SV_Q_DATA.SET_BURN, data)
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command burn rate missing option")
|
log.debug(log_header .. "CRDN unit command burn rate missing option")
|
||||||
end
|
end
|
||||||
elseif cmd == UNIT_COMMANDS.SET_WASTE then
|
elseif cmd == UNIT_COMMAND.SET_WASTE then
|
||||||
if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] > 0) and (pkt.data[3] <= 4) then
|
if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] > 0) and (pkt.data[3] <= 4) then
|
||||||
unit.set_waste(pkt.data[3])
|
unit.set_waste(pkt.data[3])
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command set waste missing option")
|
log.debug(log_header .. "CRDN unit command set waste missing option")
|
||||||
end
|
end
|
||||||
elseif cmd == UNIT_COMMANDS.ACK_ALL_ALARMS then
|
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||||
unit.ack_all()
|
unit.ack_all()
|
||||||
_send(SCADA_CRDN_TYPES.UNIT_CMD, { cmd, uid, true })
|
_send(SCADA_CRDN_TYPE.UNIT_CMD, { cmd, uid, true })
|
||||||
elseif cmd == UNIT_COMMANDS.ACK_ALARM then
|
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
||||||
if pkt.length == 3 then
|
if pkt.length == 3 then
|
||||||
unit.ack_alarm(pkt.data[3])
|
unit.ack_alarm(pkt.data[3])
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command ack alarm missing alarm id")
|
log.debug(log_header .. "CRDN unit command ack alarm missing alarm id")
|
||||||
end
|
end
|
||||||
elseif cmd == UNIT_COMMANDS.RESET_ALARM then
|
elseif cmd == UNIT_COMMAND.RESET_ALARM then
|
||||||
if pkt.length == 3 then
|
if pkt.length == 3 then
|
||||||
unit.reset_alarm(pkt.data[3])
|
unit.reset_alarm(pkt.data[3])
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command reset alarm missing alarm id")
|
log.debug(log_header .. "CRDN unit command reset alarm missing alarm id")
|
||||||
end
|
end
|
||||||
elseif cmd == UNIT_COMMANDS.SET_GROUP then
|
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
||||||
if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] >= 0) and (pkt.data[3] <= 4) then
|
if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] >= 0) and (pkt.data[3] <= 4) then
|
||||||
facility.set_group(unit.get_id(), pkt.data[3])
|
facility.set_group(unit.get_id(), pkt.data[3])
|
||||||
_send(SCADA_CRDN_TYPES.UNIT_CMD, { cmd, uid, pkt.data[3] })
|
_send(SCADA_CRDN_TYPE.UNIT_CMD, { cmd, uid, pkt.data[3] })
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command set group missing group id")
|
log.debug(log_header .. "CRDN unit command set group missing group id")
|
||||||
end
|
end
|
||||||
@ -342,7 +342,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
-- close the connection
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.CLOSE, {})
|
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||||
println("connection to coordinator " .. id .. " closed by server")
|
println("connection to coordinator " .. id .. " closed by server")
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
end
|
||||||
@ -373,7 +373,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
|
|
||||||
if cmd.key == CRD_S_DATA.CMD_ACK then
|
if cmd.key == CRD_S_DATA.CMD_ACK then
|
||||||
local ack = cmd.val ---@type coord_ack
|
local ack = cmd.val ---@type coord_ack
|
||||||
_send(SCADA_CRDN_TYPES.UNIT_CMD, { ack.cmd, ack.unit, ack.ack })
|
_send(SCADA_CRDN_TYPE.UNIT_CMD, { ack.cmd, ack.unit, ack.ack })
|
||||||
elseif cmd.key == CRD_S_DATA.RESEND_PLC_BUILD then
|
elseif cmd.key == CRD_S_DATA.RESEND_PLC_BUILD then
|
||||||
-- re-send PLC build
|
-- re-send PLC build
|
||||||
-- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update
|
-- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update
|
||||||
@ -386,7 +386,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
local unit = self.units[unit_id] ---@type reactor_unit
|
local unit = self.units[unit_id] ---@type reactor_unit
|
||||||
builds[unit_id] = unit.get_build(true, false, false)
|
builds[unit_id] = unit.get_build(true, false, false)
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.UNIT_BUILDS, { builds })
|
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||||
elseif cmd.key == CRD_S_DATA.RESEND_RTU_BUILD then
|
elseif cmd.key == CRD_S_DATA.RESEND_RTU_BUILD then
|
||||||
local unit_id = cmd.val.unit
|
local unit_id = cmd.val.unit
|
||||||
if unit_id > 0 then
|
if unit_id > 0 then
|
||||||
@ -398,16 +398,16 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
local builds = {}
|
local builds = {}
|
||||||
|
|
||||||
local unit = self.units[unit_id] ---@type reactor_unit
|
local unit = self.units[unit_id] ---@type reactor_unit
|
||||||
builds[unit_id] = unit.get_build(false, cmd.val.type == RTU_UNIT_TYPES.BOILER_VALVE, cmd.val.type == RTU_UNIT_TYPES.TURBINE_VALVE)
|
builds[unit_id] = unit.get_build(false, cmd.val.type == RTU_UNIT_TYPE.BOILER_VALVE, cmd.val.type == RTU_UNIT_TYPE.TURBINE_VALVE)
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.UNIT_BUILDS, { builds })
|
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||||
else
|
else
|
||||||
-- re-send facility RTU builds
|
-- re-send facility RTU builds
|
||||||
-- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update
|
-- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update
|
||||||
self.retry_times.f_builds_packet = util.time() + PARTIAL_RETRY_PERIOD
|
self.retry_times.f_builds_packet = util.time() + PARTIAL_RETRY_PERIOD
|
||||||
self.acks.fac_builds = false
|
self.acks.fac_builds = false
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPES.FAC_BUILDS, { facility.get_build(cmd.val.type == RTU_UNIT_TYPES.IMATRIX) })
|
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type == RTU_UNIT_TYPE.IMATRIX) })
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.warning(log_header .. "unsupported data command received in in_queue (this is a bug)")
|
log.warning(log_header .. "unsupported data command received in in_queue (this is a bug)")
|
||||||
@ -441,7 +441,7 @@ function coordinator.new_session(id, in_queue, out_queue, timeout, facility)
|
|||||||
|
|
||||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.KEEP_ALIVE, { util.time() })
|
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||||
periodics.keep_alive = 0
|
periodics.keep_alive = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -8,12 +8,12 @@ local svqtypes = require("supervisor.session.svqtypes")
|
|||||||
|
|
||||||
local plc = {}
|
local plc = {}
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local RPLC_TYPES = comms.RPLC_TYPES
|
local RPLC_TYPE = comms.RPLC_TYPE
|
||||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||||
local PLC_AUTO_ACK = comms.PLC_AUTO_ACK
|
local PLC_AUTO_ACK = comms.PLC_AUTO_ACK
|
||||||
|
|
||||||
local UNIT_COMMANDS = comms.UNIT_COMMANDS
|
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
@ -244,28 +244,28 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send an RPLC packet
|
-- send an RPLC packet
|
||||||
---@param msg_type RPLC_TYPES
|
---@param msg_type RPLC_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send(msg_type, msg)
|
local function _send(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local r_pkt = comms.rplc_packet()
|
local r_pkt = comms.rplc_packet()
|
||||||
|
|
||||||
r_pkt.make(for_reactor, msg_type, msg)
|
r_pkt.make(for_reactor, msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.RPLC, r_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.RPLC, r_pkt.raw_sendable())
|
||||||
|
|
||||||
self.out_q.push_packet(s_pkt)
|
self.out_q.push_packet(s_pkt)
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPES
|
---@param msg_type SCADA_MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_packet()
|
local m_pkt = comms.mgmt_packet()
|
||||||
|
|
||||||
m_pkt.make(msg_type, msg)
|
m_pkt.make(msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.SCADA_MGMT, m_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||||
|
|
||||||
self.out_q.push_packet(s_pkt)
|
self.out_q.push_packet(s_pkt)
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
@ -297,7 +297,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- process packet
|
-- process packet
|
||||||
if pkt.scada_frame.protocol() == PROTOCOLS.RPLC then
|
if pkt.scada_frame.protocol() == PROTOCOL.RPLC then
|
||||||
-- check reactor ID
|
-- check reactor ID
|
||||||
if pkt.id ~= for_reactor then
|
if pkt.id ~= for_reactor then
|
||||||
log.warning(log_header .. "RPLC packet with ID not matching reactor ID: reactor " .. self.for_reactor .. " != " .. pkt.id)
|
log.warning(log_header .. "RPLC packet with ID not matching reactor ID: reactor " .. self.for_reactor .. " != " .. pkt.id)
|
||||||
@ -308,7 +308,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
self.plc_conn_watchdog.feed()
|
self.plc_conn_watchdog.feed()
|
||||||
|
|
||||||
-- handle packet by type
|
-- handle packet by type
|
||||||
if pkt.type == RPLC_TYPES.STATUS then
|
if pkt.type == RPLC_TYPE.STATUS then
|
||||||
-- status packet received, update data
|
-- status packet received, update data
|
||||||
if pkt.length >= 5 then
|
if pkt.length >= 5 then
|
||||||
self.sDB.last_status_update = pkt.data[1]
|
self.sDB.last_status_update = pkt.data[1]
|
||||||
@ -335,7 +335,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "RPLC status packet length mismatch")
|
log.debug(log_header .. "RPLC status packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == RPLC_TYPES.MEK_STRUCT then
|
elseif pkt.type == RPLC_TYPE.MEK_STRUCT then
|
||||||
-- received reactor structure, record it
|
-- received reactor structure, record it
|
||||||
if pkt.length == 14 then
|
if pkt.length == 14 then
|
||||||
local status = pcall(_copy_struct, pkt.data)
|
local status = pcall(_copy_struct, pkt.data)
|
||||||
@ -350,7 +350,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "RPLC struct packet length mismatch")
|
log.debug(log_header .. "RPLC struct packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == RPLC_TYPES.MEK_BURN_RATE then
|
elseif pkt.type == RPLC_TYPE.MEK_BURN_RATE then
|
||||||
-- burn rate acknowledgement
|
-- burn rate acknowledgement
|
||||||
local ack = _get_ack(pkt)
|
local ack = _get_ack(pkt)
|
||||||
if ack then
|
if ack then
|
||||||
@ -362,10 +362,10 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
-- send acknowledgement to coordinator
|
-- send acknowledgement to coordinator
|
||||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||||
unit = self.for_reactor,
|
unit = self.for_reactor,
|
||||||
cmd = UNIT_COMMANDS.SET_BURN,
|
cmd = UNIT_COMMAND.SET_BURN,
|
||||||
ack = ack
|
ack = ack
|
||||||
})
|
})
|
||||||
elseif pkt.type == RPLC_TYPES.RPS_ENABLE then
|
elseif pkt.type == RPLC_TYPE.RPS_ENABLE then
|
||||||
-- enable acknowledgement
|
-- enable acknowledgement
|
||||||
local ack = _get_ack(pkt)
|
local ack = _get_ack(pkt)
|
||||||
if ack then
|
if ack then
|
||||||
@ -377,10 +377,10 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
-- send acknowledgement to coordinator
|
-- send acknowledgement to coordinator
|
||||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||||
unit = self.for_reactor,
|
unit = self.for_reactor,
|
||||||
cmd = UNIT_COMMANDS.START,
|
cmd = UNIT_COMMAND.START,
|
||||||
ack = ack
|
ack = ack
|
||||||
})
|
})
|
||||||
elseif pkt.type == RPLC_TYPES.RPS_SCRAM then
|
elseif pkt.type == RPLC_TYPE.RPS_SCRAM then
|
||||||
-- manual SCRAM acknowledgement
|
-- manual SCRAM acknowledgement
|
||||||
local ack = _get_ack(pkt)
|
local ack = _get_ack(pkt)
|
||||||
if ack then
|
if ack then
|
||||||
@ -393,10 +393,10 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
-- send acknowledgement to coordinator
|
-- send acknowledgement to coordinator
|
||||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||||
unit = self.for_reactor,
|
unit = self.for_reactor,
|
||||||
cmd = UNIT_COMMANDS.SCRAM,
|
cmd = UNIT_COMMAND.SCRAM,
|
||||||
ack = ack
|
ack = ack
|
||||||
})
|
})
|
||||||
elseif pkt.type == RPLC_TYPES.RPS_ASCRAM then
|
elseif pkt.type == RPLC_TYPE.RPS_ASCRAM then
|
||||||
-- automatic SCRAM acknowledgement
|
-- automatic SCRAM acknowledgement
|
||||||
local ack = _get_ack(pkt)
|
local ack = _get_ack(pkt)
|
||||||
if ack then
|
if ack then
|
||||||
@ -405,7 +405,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
elseif ack == false then
|
elseif ack == false then
|
||||||
log.debug(log_header .. " automatic SCRAM failed!")
|
log.debug(log_header .. " automatic SCRAM failed!")
|
||||||
end
|
end
|
||||||
elseif pkt.type == RPLC_TYPES.RPS_STATUS then
|
elseif pkt.type == RPLC_TYPE.RPS_STATUS then
|
||||||
-- RPS status packet received, copy data
|
-- RPS status packet received, copy data
|
||||||
if pkt.length == 14 then
|
if pkt.length == 14 then
|
||||||
local status = pcall(_copy_rps_status, pkt.data)
|
local status = pcall(_copy_rps_status, pkt.data)
|
||||||
@ -418,7 +418,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "RPLC RPS status packet length mismatch")
|
log.debug(log_header .. "RPLC RPS status packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == RPLC_TYPES.RPS_ALARM then
|
elseif pkt.type == RPLC_TYPE.RPS_ALARM then
|
||||||
-- RPS alarm
|
-- RPS alarm
|
||||||
if pkt.length == 13 then
|
if pkt.length == 13 then
|
||||||
local status = pcall(_copy_rps_status, { true, table.unpack(pkt.data) })
|
local status = pcall(_copy_rps_status, { true, table.unpack(pkt.data) })
|
||||||
@ -431,7 +431,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "RPLC RPS alarm packet length mismatch")
|
log.debug(log_header .. "RPLC RPS alarm packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == RPLC_TYPES.RPS_RESET then
|
elseif pkt.type == RPLC_TYPE.RPS_RESET then
|
||||||
-- RPS reset acknowledgement
|
-- RPS reset acknowledgement
|
||||||
local ack = _get_ack(pkt)
|
local ack = _get_ack(pkt)
|
||||||
if ack then
|
if ack then
|
||||||
@ -445,16 +445,16 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
-- send acknowledgement to coordinator
|
-- send acknowledgement to coordinator
|
||||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||||
unit = self.for_reactor,
|
unit = self.for_reactor,
|
||||||
cmd = UNIT_COMMANDS.RESET_RPS,
|
cmd = UNIT_COMMAND.RESET_RPS,
|
||||||
ack = ack
|
ack = ack
|
||||||
})
|
})
|
||||||
elseif pkt.type == RPLC_TYPES.RPS_AUTO_RESET then
|
elseif pkt.type == RPLC_TYPE.RPS_AUTO_RESET then
|
||||||
-- RPS auto control reset acknowledgement
|
-- RPS auto control reset acknowledgement
|
||||||
local ack = _get_ack(pkt)
|
local ack = _get_ack(pkt)
|
||||||
if not ack then
|
if not ack then
|
||||||
log.debug(log_header .. "RPS auto reset failed")
|
log.debug(log_header .. "RPS auto reset failed")
|
||||||
end
|
end
|
||||||
elseif pkt.type == RPLC_TYPES.AUTO_BURN_RATE then
|
elseif pkt.type == RPLC_TYPE.AUTO_BURN_RATE then
|
||||||
if pkt.length == 1 then
|
if pkt.length == 1 then
|
||||||
local ack = pkt.data[1]
|
local ack = pkt.data[1]
|
||||||
|
|
||||||
@ -473,8 +473,8 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "handler received unsupported RPLC packet type " .. pkt.type)
|
log.debug(log_header .. "handler received unsupported RPLC packet type " .. pkt.type)
|
||||||
end
|
end
|
||||||
elseif pkt.scada_frame.protocol() == PROTOCOLS.SCADA_MGMT then
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
if pkt.type == SCADA_MGMT_TYPES.KEEP_ALIVE then
|
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
@ -491,7 +491,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPES.CLOSE then
|
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_close()
|
||||||
else
|
else
|
||||||
@ -575,7 +575,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
-- close the connection
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.CLOSE, {})
|
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||||
println("connection to reactor " .. self.for_reactor .. " PLC closed by server")
|
println("connection to reactor " .. self.for_reactor .. " PLC closed by server")
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
end
|
||||||
@ -604,27 +604,27 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
if cmd == PLC_S_CMDS.ENABLE then
|
if cmd == PLC_S_CMDS.ENABLE then
|
||||||
-- enable reactor
|
-- enable reactor
|
||||||
if not self.auto_lock then
|
if not self.auto_lock then
|
||||||
_send(RPLC_TYPES.RPS_ENABLE, {})
|
_send(RPLC_TYPE.RPS_ENABLE, {})
|
||||||
end
|
end
|
||||||
elseif cmd == PLC_S_CMDS.SCRAM then
|
elseif cmd == PLC_S_CMDS.SCRAM then
|
||||||
-- SCRAM reactor
|
-- SCRAM reactor
|
||||||
self.acks.scram = false
|
self.acks.scram = false
|
||||||
self.retry_times.scram_req = util.time() + INITIAL_WAIT
|
self.retry_times.scram_req = util.time() + INITIAL_WAIT
|
||||||
_send(RPLC_TYPES.RPS_SCRAM, {})
|
_send(RPLC_TYPE.RPS_SCRAM, {})
|
||||||
elseif cmd == PLC_S_CMDS.ASCRAM then
|
elseif cmd == PLC_S_CMDS.ASCRAM then
|
||||||
-- SCRAM reactor
|
-- SCRAM reactor
|
||||||
self.acks.ascram = false
|
self.acks.ascram = false
|
||||||
self.retry_times.ascram_req = util.time() + INITIAL_WAIT
|
self.retry_times.ascram_req = util.time() + INITIAL_WAIT
|
||||||
_send(RPLC_TYPES.RPS_ASCRAM, {})
|
_send(RPLC_TYPE.RPS_ASCRAM, {})
|
||||||
elseif cmd == PLC_S_CMDS.RPS_RESET then
|
elseif cmd == PLC_S_CMDS.RPS_RESET then
|
||||||
-- reset RPS
|
-- reset RPS
|
||||||
self.acks.ascram = true
|
self.acks.ascram = true
|
||||||
self.acks.rps_reset = false
|
self.acks.rps_reset = false
|
||||||
self.retry_times.rps_reset_req = util.time() + INITIAL_WAIT
|
self.retry_times.rps_reset_req = util.time() + INITIAL_WAIT
|
||||||
_send(RPLC_TYPES.RPS_RESET, {})
|
_send(RPLC_TYPE.RPS_RESET, {})
|
||||||
elseif cmd == PLC_S_CMDS.RPS_AUTO_RESET then
|
elseif cmd == PLC_S_CMDS.RPS_AUTO_RESET then
|
||||||
if self.sDB.rps_status.automatic or self.sDB.rps_status.timeout then
|
if self.sDB.rps_status.automatic or self.sDB.rps_status.timeout then
|
||||||
_send(RPLC_TYPES.RPS_AUTO_RESET, {})
|
_send(RPLC_TYPE.RPS_AUTO_RESET, {})
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.warning(log_header .. "unsupported command received in in_queue (this is a bug)")
|
log.warning(log_header .. "unsupported command received in in_queue (this is a bug)")
|
||||||
@ -642,7 +642,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
self.ramping_rate = false
|
self.ramping_rate = false
|
||||||
self.acks.burn_rate = false
|
self.acks.burn_rate = false
|
||||||
self.retry_times.burn_rate_req = util.time() + INITIAL_WAIT
|
self.retry_times.burn_rate_req = util.time() + INITIAL_WAIT
|
||||||
_send(RPLC_TYPES.MEK_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
_send(RPLC_TYPE.MEK_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif cmd.key == PLC_S_DATA.RAMP_BURN_RATE then
|
elseif cmd.key == PLC_S_DATA.RAMP_BURN_RATE then
|
||||||
@ -655,7 +655,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
self.ramping_rate = true
|
self.ramping_rate = true
|
||||||
self.acks.burn_rate = false
|
self.acks.burn_rate = false
|
||||||
self.retry_times.burn_rate_req = util.time() + INITIAL_WAIT
|
self.retry_times.burn_rate_req = util.time() + INITIAL_WAIT
|
||||||
_send(RPLC_TYPES.MEK_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
_send(RPLC_TYPE.MEK_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif cmd.key == PLC_S_DATA.AUTO_BURN_RATE then
|
elseif cmd.key == PLC_S_DATA.AUTO_BURN_RATE then
|
||||||
@ -670,7 +670,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
self.acks.burn_rate = not self.ramping_rate
|
self.acks.burn_rate = not self.ramping_rate
|
||||||
self.retry_times.burn_rate_req = util.time() + INITIAL_AUTO_WAIT
|
self.retry_times.burn_rate_req = util.time() + INITIAL_AUTO_WAIT
|
||||||
|
|
||||||
_send(RPLC_TYPES.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate, self.auto_cmd_token })
|
_send(RPLC_TYPE.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate, self.auto_cmd_token })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -705,7 +705,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.KEEP_ALIVE, { util.time() })
|
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||||
periodics.keep_alive = 0
|
periodics.keep_alive = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -722,7 +722,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
if not self.received_struct then
|
if not self.received_struct then
|
||||||
if rtimes.struct_req - util.time() <= 0 then
|
if rtimes.struct_req - util.time() <= 0 then
|
||||||
_send(RPLC_TYPES.MEK_STRUCT, {})
|
_send(RPLC_TYPE.MEK_STRUCT, {})
|
||||||
rtimes.struct_req = util.time() + RETRY_PERIOD
|
rtimes.struct_req = util.time() + RETRY_PERIOD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -731,7 +731,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
if not self.received_status_cache then
|
if not self.received_status_cache then
|
||||||
if rtimes.status_req - util.time() <= 0 then
|
if rtimes.status_req - util.time() <= 0 then
|
||||||
_send(RPLC_TYPES.MEK_STATUS, {})
|
_send(RPLC_TYPE.MEK_STATUS, {})
|
||||||
rtimes.status_req = util.time() + RETRY_PERIOD
|
rtimes.status_req = util.time() + RETRY_PERIOD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -742,13 +742,13 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
if rtimes.burn_rate_req - util.time() <= 0 then
|
if rtimes.burn_rate_req - util.time() <= 0 then
|
||||||
if self.auto_cmd_token > 0 then
|
if self.auto_cmd_token > 0 then
|
||||||
if self.auto_lock then
|
if self.auto_lock then
|
||||||
_send(RPLC_TYPES.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate, self.auto_cmd_token })
|
_send(RPLC_TYPE.AUTO_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate, self.auto_cmd_token })
|
||||||
else
|
else
|
||||||
-- would have been an auto command, but disengaged, so stop retrying
|
-- would have been an auto command, but disengaged, so stop retrying
|
||||||
self.acks.burn_rate = true
|
self.acks.burn_rate = true
|
||||||
end
|
end
|
||||||
elseif not self.auto_lock then
|
elseif not self.auto_lock then
|
||||||
_send(RPLC_TYPES.MEK_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
_send(RPLC_TYPE.MEK_BURN_RATE, { self.commanded_burn_rate, self.ramping_rate })
|
||||||
else
|
else
|
||||||
-- shouldn't be in this state, just pretend it was acknowledged
|
-- shouldn't be in this state, just pretend it was acknowledged
|
||||||
self.acks.burn_rate = true
|
self.acks.burn_rate = true
|
||||||
@ -763,7 +763,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
if not self.acks.scram then
|
if not self.acks.scram then
|
||||||
if rtimes.scram_req - util.time() <= 0 then
|
if rtimes.scram_req - util.time() <= 0 then
|
||||||
_send(RPLC_TYPES.RPS_SCRAM, {})
|
_send(RPLC_TYPE.RPS_SCRAM, {})
|
||||||
rtimes.scram_req = util.time() + RETRY_PERIOD
|
rtimes.scram_req = util.time() + RETRY_PERIOD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -772,7 +772,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
if not self.acks.ascram then
|
if not self.acks.ascram then
|
||||||
if rtimes.ascram_req - util.time() <= 0 then
|
if rtimes.ascram_req - util.time() <= 0 then
|
||||||
_send(RPLC_TYPES.RPS_ASCRAM, {})
|
_send(RPLC_TYPE.RPS_ASCRAM, {})
|
||||||
rtimes.ascram_req = util.time() + RETRY_PERIOD
|
rtimes.ascram_req = util.time() + RETRY_PERIOD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -781,7 +781,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
if not self.acks.rps_reset then
|
if not self.acks.rps_reset then
|
||||||
if rtimes.rps_reset_req - util.time() <= 0 then
|
if rtimes.rps_reset_req - util.time() <= 0 then
|
||||||
_send(RPLC_TYPES.RPS_RESET, {})
|
_send(RPLC_TYPE.RPS_RESET, {})
|
||||||
rtimes.rps_reset_req = util.time() + RETRY_PERIOD
|
rtimes.rps_reset_req = util.time() + RETRY_PERIOD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -18,9 +18,9 @@ local svrs_turbinev = require("supervisor.session.rtu.turbinev")
|
|||||||
|
|
||||||
local rtu = {}
|
local rtu = {}
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
@ -99,7 +99,7 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
advert_validator.assert_type_int(unit_advert.index)
|
advert_validator.assert_type_int(unit_advert.index)
|
||||||
advert_validator.assert_type_int(unit_advert.reactor)
|
advert_validator.assert_type_int(unit_advert.reactor)
|
||||||
|
|
||||||
if u_type == RTU_UNIT_TYPES.REDSTONE then
|
if u_type == RTU_UNIT_TYPE.REDSTONE then
|
||||||
advert_validator.assert_type_table(unit_advert.rsio)
|
advert_validator.assert_type_table(unit_advert.rsio)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -124,19 +124,19 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
if unit_advert.reactor > 0 then
|
if unit_advert.reactor > 0 then
|
||||||
local target_unit = self.fac_units[unit_advert.reactor] ---@type reactor_unit
|
local target_unit = self.fac_units[unit_advert.reactor] ---@type reactor_unit
|
||||||
|
|
||||||
if u_type == RTU_UNIT_TYPES.REDSTONE then
|
if u_type == RTU_UNIT_TYPE.REDSTONE then
|
||||||
-- redstone
|
-- redstone
|
||||||
unit = svrs_redstone.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_redstone.new(id, i, unit_advert, self.modbus_q)
|
||||||
if type(unit) ~= "nil" then target_unit.add_redstone(unit) end
|
if type(unit) ~= "nil" then target_unit.add_redstone(unit) end
|
||||||
elseif u_type == RTU_UNIT_TYPES.BOILER_VALVE then
|
elseif u_type == RTU_UNIT_TYPE.BOILER_VALVE then
|
||||||
-- boiler (Mekanism 10.1+)
|
-- boiler (Mekanism 10.1+)
|
||||||
unit = svrs_boilerv.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_boilerv.new(id, i, unit_advert, self.modbus_q)
|
||||||
if type(unit) ~= "nil" then target_unit.add_boiler(unit) end
|
if type(unit) ~= "nil" then target_unit.add_boiler(unit) end
|
||||||
elseif u_type == RTU_UNIT_TYPES.TURBINE_VALVE then
|
elseif u_type == RTU_UNIT_TYPE.TURBINE_VALVE then
|
||||||
-- turbine (Mekanism 10.1+)
|
-- turbine (Mekanism 10.1+)
|
||||||
unit = svrs_turbinev.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_turbinev.new(id, i, unit_advert, self.modbus_q)
|
||||||
if type(unit) ~= "nil" then target_unit.add_turbine(unit) end
|
if type(unit) ~= "nil" then target_unit.add_turbine(unit) end
|
||||||
elseif u_type == RTU_UNIT_TYPES.ENV_DETECTOR then
|
elseif u_type == RTU_UNIT_TYPE.ENV_DETECTOR then
|
||||||
-- environment detector
|
-- environment detector
|
||||||
unit = svrs_envd.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_envd.new(id, i, unit_advert, self.modbus_q)
|
||||||
if type(unit) ~= "nil" then target_unit.add_envd(unit) end
|
if type(unit) ~= "nil" then target_unit.add_envd(unit) end
|
||||||
@ -144,21 +144,21 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
log.error(util.c(log_header, "bad advertisement: encountered unsupported reactor-specific RTU type ", type_string))
|
log.error(util.c(log_header, "bad advertisement: encountered unsupported reactor-specific RTU type ", type_string))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if u_type == RTU_UNIT_TYPES.REDSTONE then
|
if u_type == RTU_UNIT_TYPE.REDSTONE then
|
||||||
-- redstone
|
-- redstone
|
||||||
unit = svrs_redstone.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_redstone.new(id, i, unit_advert, self.modbus_q)
|
||||||
if type(unit) ~= "nil" then facility.add_redstone(unit) end
|
if type(unit) ~= "nil" then facility.add_redstone(unit) end
|
||||||
elseif u_type == RTU_UNIT_TYPES.IMATRIX then
|
elseif u_type == RTU_UNIT_TYPE.IMATRIX then
|
||||||
-- induction matrix
|
-- induction matrix
|
||||||
unit = svrs_imatrix.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_imatrix.new(id, i, unit_advert, self.modbus_q)
|
||||||
if type(unit) ~= "nil" then facility.add_imatrix(unit) end
|
if type(unit) ~= "nil" then facility.add_imatrix(unit) end
|
||||||
elseif u_type == RTU_UNIT_TYPES.SPS then
|
elseif u_type == RTU_UNIT_TYPE.SPS then
|
||||||
-- super-critical phase shifter
|
-- super-critical phase shifter
|
||||||
unit = svrs_sps.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_sps.new(id, i, unit_advert, self.modbus_q)
|
||||||
elseif u_type == RTU_UNIT_TYPES.SNA then
|
elseif u_type == RTU_UNIT_TYPE.SNA then
|
||||||
-- solar neutron activator
|
-- solar neutron activator
|
||||||
unit = svrs_sna.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_sna.new(id, i, unit_advert, self.modbus_q)
|
||||||
elseif u_type == RTU_UNIT_TYPES.ENV_DETECTOR then
|
elseif u_type == RTU_UNIT_TYPE.ENV_DETECTOR then
|
||||||
-- environment detector
|
-- environment detector
|
||||||
unit = svrs_envd.new(id, i, unit_advert, self.modbus_q)
|
unit = svrs_envd.new(id, i, unit_advert, self.modbus_q)
|
||||||
if type(unit) ~= "nil" then facility.add_envd(unit) end
|
if type(unit) ~= "nil" then facility.add_envd(unit) end
|
||||||
@ -194,21 +194,21 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
local function _send_modbus(m_pkt)
|
local function _send_modbus(m_pkt)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
|
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.MODBUS_TCP, m_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.MODBUS_TCP, m_pkt.raw_sendable())
|
||||||
|
|
||||||
self.out_q.push_packet(s_pkt)
|
self.out_q.push_packet(s_pkt)
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPES
|
---@param msg_type SCADA_MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_packet()
|
local m_pkt = comms.mgmt_packet()
|
||||||
|
|
||||||
m_pkt.make(msg_type, msg)
|
m_pkt.make(msg_type, msg)
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.SCADA_MGMT, m_pkt.raw_sendable())
|
s_pkt.make(self.seq_num, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||||
|
|
||||||
self.out_q.push_packet(s_pkt)
|
self.out_q.push_packet(s_pkt)
|
||||||
self.seq_num = self.seq_num + 1
|
self.seq_num = self.seq_num + 1
|
||||||
@ -231,15 +231,15 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
self.rtu_conn_watchdog.feed()
|
self.rtu_conn_watchdog.feed()
|
||||||
|
|
||||||
-- process packet
|
-- process packet
|
||||||
if pkt.scada_frame.protocol() == PROTOCOLS.MODBUS_TCP then
|
if pkt.scada_frame.protocol() == PROTOCOL.MODBUS_TCP then
|
||||||
if self.units[pkt.unit_id] ~= nil then
|
if self.units[pkt.unit_id] ~= nil then
|
||||||
local unit = self.units[pkt.unit_id] ---@type unit_session
|
local unit = self.units[pkt.unit_id] ---@type unit_session
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
unit.handle_packet(pkt)
|
unit.handle_packet(pkt)
|
||||||
end
|
end
|
||||||
elseif pkt.scada_frame.protocol() == PROTOCOLS.SCADA_MGMT then
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
-- handle management packet
|
-- handle management packet
|
||||||
if pkt.type == SCADA_MGMT_TYPES.KEEP_ALIVE then
|
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
@ -256,10 +256,10 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPES.CLOSE then
|
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_close()
|
||||||
elseif pkt.type == SCADA_MGMT_TYPES.RTU_ADVERT then
|
elseif pkt.type == SCADA_MGMT_TYPE.RTU_ADVERT then
|
||||||
-- RTU unit advertisement
|
-- RTU unit advertisement
|
||||||
log.debug(log_header .. "received updated advertisement")
|
log.debug(log_header .. "received updated advertisement")
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
|
|
||||||
-- handle advertisement; this will re-create all unit sub-sessions
|
-- handle advertisement; this will re-create all unit sub-sessions
|
||||||
_handle_advertisement()
|
_handle_advertisement()
|
||||||
elseif pkt.type == SCADA_MGMT_TYPES.RTU_DEV_REMOUNT then
|
elseif pkt.type == SCADA_MGMT_TYPE.RTU_DEV_REMOUNT then
|
||||||
if pkt.length == 1 then
|
if pkt.length == 1 then
|
||||||
local unit_id = pkt.data[1]
|
local unit_id = pkt.data[1]
|
||||||
if self.units[unit_id] ~= nil then
|
if self.units[unit_id] ~= nil then
|
||||||
@ -299,7 +299,7 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
-- close the connection
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.CLOSE, {})
|
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||||
println(log_header .. "connection to RTU closed by server")
|
println(log_header .. "connection to RTU closed by server")
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
end
|
||||||
@ -365,7 +365,7 @@ function rtu.new_session(id, in_queue, out_queue, timeout, advertisement, facili
|
|||||||
|
|
||||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||||
_send_mgmt(SCADA_MGMT_TYPES.KEEP_ALIVE, { util.time() })
|
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||||
periodics.keep_alive = 0
|
periodics.keep_alive = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ local unit_session = require("supervisor.session.rtu.unit_session")
|
|||||||
|
|
||||||
local boilerv = {}
|
local boilerv = {}
|
||||||
|
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
|
|
||||||
local TXN_TYPES = {
|
local TXN_TYPES = {
|
||||||
@ -38,7 +38,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue RTU unit message out queue
|
---@param out_queue mqueue RTU unit message out queue
|
||||||
function boilerv.new(session_id, unit_id, advert, out_queue)
|
function boilerv.new(session_id, unit_id, advert, out_queue)
|
||||||
-- type check
|
-- type check
|
||||||
if advert.type ~= RTU_UNIT_TYPES.BOILER_VALVE then
|
if advert.type ~= RTU_UNIT_TYPE.BOILER_VALVE then
|
||||||
log.error("attempt to instantiate boilerv RTU for type '" .. advert.type .. "'. this is a bug.")
|
log.error("attempt to instantiate boilerv RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ local unit_session = require("supervisor.session.rtu.unit_session")
|
|||||||
|
|
||||||
local envd = {}
|
local envd = {}
|
||||||
|
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
|
|
||||||
local TXN_TYPES = {
|
local TXN_TYPES = {
|
||||||
@ -29,7 +29,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue
|
---@param out_queue mqueue
|
||||||
function envd.new(session_id, unit_id, advert, out_queue)
|
function envd.new(session_id, unit_id, advert, out_queue)
|
||||||
-- type check
|
-- type check
|
||||||
if advert.type ~= RTU_UNIT_TYPES.ENV_DETECTOR then
|
if advert.type ~= RTU_UNIT_TYPE.ENV_DETECTOR then
|
||||||
log.error("attempt to instantiate envd RTU for type '" .. advert.type .. "'. this is a bug.")
|
log.error("attempt to instantiate envd RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ local unit_session = require("supervisor.session.rtu.unit_session")
|
|||||||
|
|
||||||
local imatrix = {}
|
local imatrix = {}
|
||||||
|
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
|
|
||||||
local TXN_TYPES = {
|
local TXN_TYPES = {
|
||||||
@ -38,7 +38,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue RTU unit message out queue
|
---@param out_queue mqueue RTU unit message out queue
|
||||||
function imatrix.new(session_id, unit_id, advert, out_queue)
|
function imatrix.new(session_id, unit_id, advert, out_queue)
|
||||||
-- type check
|
-- type check
|
||||||
if advert.type ~= RTU_UNIT_TYPES.IMATRIX then
|
if advert.type ~= RTU_UNIT_TYPE.IMATRIX then
|
||||||
log.error("attempt to instantiate imatrix RTU for type '" .. advert.type .. "'. this is a bug.")
|
log.error("attempt to instantiate imatrix RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -9,7 +9,7 @@ local unit_session = require("supervisor.session.rtu.unit_session")
|
|||||||
|
|
||||||
local redstone = {}
|
local redstone = {}
|
||||||
|
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
|
|
||||||
local IO_PORT = rsio.IO
|
local IO_PORT = rsio.IO
|
||||||
@ -53,7 +53,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue
|
---@param out_queue mqueue
|
||||||
function redstone.new(session_id, unit_id, advert, out_queue)
|
function redstone.new(session_id, unit_id, advert, out_queue)
|
||||||
-- type check
|
-- type check
|
||||||
if advert.type ~= RTU_UNIT_TYPES.REDSTONE then
|
if advert.type ~= RTU_UNIT_TYPE.REDSTONE then
|
||||||
log.error("attempt to instantiate redstone RTU for type '" .. advert.type .. "'. this is a bug.")
|
log.error("attempt to instantiate redstone RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ local unit_session = require("supervisor.session.rtu.unit_session")
|
|||||||
|
|
||||||
local sna = {}
|
local sna = {}
|
||||||
|
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
|
|
||||||
local TXN_TYPES = {
|
local TXN_TYPES = {
|
||||||
@ -35,7 +35,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue RTU unit message out queue
|
---@param out_queue mqueue RTU unit message out queue
|
||||||
function sna.new(session_id, unit_id, advert, out_queue)
|
function sna.new(session_id, unit_id, advert, out_queue)
|
||||||
-- type check
|
-- type check
|
||||||
if advert.type ~= RTU_UNIT_TYPES.SNA then
|
if advert.type ~= RTU_UNIT_TYPE.SNA then
|
||||||
log.error("attempt to instantiate sna RTU for type '" .. advert.type .. "'. this is a bug.")
|
log.error("attempt to instantiate sna RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ local unit_session = require("supervisor.session.rtu.unit_session")
|
|||||||
|
|
||||||
local sps = {}
|
local sps = {}
|
||||||
|
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
|
|
||||||
local TXN_TYPES = {
|
local TXN_TYPES = {
|
||||||
@ -38,7 +38,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue RTU unit message out queue
|
---@param out_queue mqueue RTU unit message out queue
|
||||||
function sps.new(session_id, unit_id, advert, out_queue)
|
function sps.new(session_id, unit_id, advert, out_queue)
|
||||||
-- type check
|
-- type check
|
||||||
if advert.type ~= RTU_UNIT_TYPES.SPS then
|
if advert.type ~= RTU_UNIT_TYPE.SPS then
|
||||||
log.error("attempt to instantiate sps RTU for type '" .. advert.type .. "'. this is a bug.")
|
log.error("attempt to instantiate sps RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -9,7 +9,7 @@ local unit_session = require("supervisor.session.rtu.unit_session")
|
|||||||
|
|
||||||
local turbinev = {}
|
local turbinev = {}
|
||||||
|
|
||||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
local RTU_UNIT_TYPE = comms.RTU_UNIT_TYPE
|
||||||
local DUMPING_MODE = types.DUMPING_MODE
|
local DUMPING_MODE = types.DUMPING_MODE
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue RTU unit message out queue
|
---@param out_queue mqueue RTU unit message out queue
|
||||||
function turbinev.new(session_id, unit_id, advert, out_queue)
|
function turbinev.new(session_id, unit_id, advert, out_queue)
|
||||||
-- type check
|
-- type check
|
||||||
if advert.type ~= RTU_UNIT_TYPES.TURBINE_VALVE then
|
if advert.type ~= RTU_UNIT_TYPE.TURBINE_VALVE then
|
||||||
log.error("attempt to instantiate turbinev RTU for type '" .. advert.type .. "'. this is a bug.")
|
log.error("attempt to instantiate turbinev RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,7 @@ local txnctrl = require("supervisor.session.rtu.txnctrl")
|
|||||||
|
|
||||||
local unit_session = {}
|
local unit_session = {}
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||||
local MODBUS_EXCODE = types.MODBUS_EXCODE
|
local MODBUS_EXCODE = types.MODBUS_EXCODE
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ function unit_session.new(session_id, unit_id, advert, out_queue, log_tag, txn_t
|
|||||||
---@param m_pkt modbus_frame MODBUS packet
|
---@param m_pkt modbus_frame MODBUS packet
|
||||||
---@return integer|false txn_type, integer txn_id transaction type or false on error/busy, transaction ID
|
---@return integer|false txn_type, integer txn_id transaction type or false on error/busy, transaction ID
|
||||||
function protected.try_resolve(m_pkt)
|
function protected.try_resolve(m_pkt)
|
||||||
if m_pkt.scada_frame.protocol() == PROTOCOLS.MODBUS_TCP then
|
if m_pkt.scada_frame.protocol() == PROTOCOL.MODBUS_TCP then
|
||||||
if m_pkt.unit_id == self.unit_id then
|
if m_pkt.unit_id == self.unit_id then
|
||||||
local txn_type = self.transaction_controller.resolve(m_pkt.txn_id)
|
local txn_type = self.transaction_controller.resolve(m_pkt.txn_id)
|
||||||
local txn_tag = " (" .. util.strval(self.txn_tags[txn_type]) .. ")"
|
local txn_tag = " (" .. util.strval(self.txn_tags[txn_type]) .. ")"
|
||||||
|
@ -6,10 +6,10 @@ local svsessions = require("supervisor.session.svsessions")
|
|||||||
|
|
||||||
local supervisor = {}
|
local supervisor = {}
|
||||||
|
|
||||||
local PROTOCOLS = comms.PROTOCOLS
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPES = comms.DEVICE_TYPES
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
@ -60,8 +60,8 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_packet()
|
local m_pkt = comms.mgmt_packet()
|
||||||
|
|
||||||
m_pkt.make(SCADA_MGMT_TYPES.ESTABLISH, msg)
|
m_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, msg)
|
||||||
s_pkt.make(seq_id, PROTOCOLS.SCADA_MGMT, m_pkt.raw_sendable())
|
s_pkt.make(seq_id, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||||
|
|
||||||
self.modem.transmit(dest, self.dev_listen, s_pkt.raw_sendable())
|
self.modem.transmit(dest, self.dev_listen, s_pkt.raw_sendable())
|
||||||
end
|
end
|
||||||
@ -74,8 +74,8 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local c_pkt = comms.mgmt_packet()
|
local c_pkt = comms.mgmt_packet()
|
||||||
|
|
||||||
c_pkt.make(SCADA_MGMT_TYPES.ESTABLISH, msg)
|
c_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, msg)
|
||||||
s_pkt.make(seq_id, PROTOCOLS.SCADA_MGMT, c_pkt.raw_sendable())
|
s_pkt.make(seq_id, PROTOCOL.SCADA_MGMT, c_pkt.raw_sendable())
|
||||||
|
|
||||||
self.modem.transmit(dest, self.coord_listen, s_pkt.raw_sendable())
|
self.modem.transmit(dest, self.coord_listen, s_pkt.raw_sendable())
|
||||||
end
|
end
|
||||||
@ -107,25 +107,25 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
|
|
||||||
if s_pkt.is_valid() then
|
if s_pkt.is_valid() then
|
||||||
-- get as MODBUS TCP packet
|
-- get as MODBUS TCP packet
|
||||||
if s_pkt.protocol() == PROTOCOLS.MODBUS_TCP then
|
if s_pkt.protocol() == PROTOCOL.MODBUS_TCP then
|
||||||
local m_pkt = comms.modbus_packet()
|
local m_pkt = comms.modbus_packet()
|
||||||
if m_pkt.decode(s_pkt) then
|
if m_pkt.decode(s_pkt) then
|
||||||
pkt = m_pkt.get()
|
pkt = m_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as RPLC packet
|
-- get as RPLC packet
|
||||||
elseif s_pkt.protocol() == PROTOCOLS.RPLC then
|
elseif s_pkt.protocol() == PROTOCOL.RPLC then
|
||||||
local rplc_pkt = comms.rplc_packet()
|
local rplc_pkt = comms.rplc_packet()
|
||||||
if rplc_pkt.decode(s_pkt) then
|
if rplc_pkt.decode(s_pkt) then
|
||||||
pkt = rplc_pkt.get()
|
pkt = rplc_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as SCADA management packet
|
-- get as SCADA management packet
|
||||||
elseif s_pkt.protocol() == PROTOCOLS.SCADA_MGMT then
|
elseif s_pkt.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
local mgmt_pkt = comms.mgmt_packet()
|
local mgmt_pkt = comms.mgmt_packet()
|
||||||
if mgmt_pkt.decode(s_pkt) then
|
if mgmt_pkt.decode(s_pkt) then
|
||||||
pkt = mgmt_pkt.get()
|
pkt = mgmt_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as coordinator packet
|
-- get as coordinator packet
|
||||||
elseif s_pkt.protocol() == PROTOCOLS.SCADA_CRDN then
|
elseif s_pkt.protocol() == PROTOCOL.SCADA_CRDN then
|
||||||
local crdn_pkt = comms.crdn_packet()
|
local crdn_pkt = comms.crdn_packet()
|
||||||
if crdn_pkt.decode(s_pkt) then
|
if crdn_pkt.decode(s_pkt) then
|
||||||
pkt = crdn_pkt.get()
|
pkt = crdn_pkt.get()
|
||||||
@ -148,7 +148,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
|
|
||||||
-- device (RTU/PLC) listening channel
|
-- device (RTU/PLC) listening channel
|
||||||
if l_port == self.dev_listen then
|
if l_port == self.dev_listen then
|
||||||
if protocol == PROTOCOLS.MODBUS_TCP then
|
if protocol == PROTOCOL.MODBUS_TCP then
|
||||||
-- look for an associated session
|
-- look for an associated session
|
||||||
local session = svsessions.find_rtu_session(r_port)
|
local session = svsessions.find_rtu_session(r_port)
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
-- any other packet should be session related, discard it
|
-- any other packet should be session related, discard it
|
||||||
log.debug("discarding MODBUS_TCP packet without a known session")
|
log.debug("discarding MODBUS_TCP packet without a known session")
|
||||||
end
|
end
|
||||||
elseif protocol == PROTOCOLS.RPLC then
|
elseif protocol == PROTOCOL.RPLC then
|
||||||
-- look for an associated session
|
-- look for an associated session
|
||||||
local session = svsessions.find_plc_session(r_port)
|
local session = svsessions.find_plc_session(r_port)
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
log.debug("PLC_ESTABLISH: no session but not an establish, forcing relink")
|
log.debug("PLC_ESTABLISH: no session but not an establish, forcing relink")
|
||||||
_send_dev_establish(packet.scada_frame.seq_num() + 1, r_port, { ESTABLISH_ACK.DENY })
|
_send_dev_establish(packet.scada_frame.seq_num() + 1, r_port, { ESTABLISH_ACK.DENY })
|
||||||
end
|
end
|
||||||
elseif protocol == PROTOCOLS.SCADA_MGMT then
|
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||||
-- look for an associated session
|
-- look for an associated session
|
||||||
local session = svsessions.find_device_session(r_port)
|
local session = svsessions.find_device_session(r_port)
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
session.in_queue.push_packet(packet)
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.ESTABLISH then
|
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||||
-- establish a new session
|
-- establish a new session
|
||||||
local next_seq_id = packet.scada_frame.seq_num() + 1
|
local next_seq_id = packet.scada_frame.seq_num() + 1
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if dev_type == DEVICE_TYPES.PLC then
|
if dev_type == DEVICE_TYPE.PLC then
|
||||||
-- PLC linking request
|
-- PLC linking request
|
||||||
if packet.length == 4 and type(packet.data[4]) == "number" then
|
if packet.length == 4 and type(packet.data[4]) == "number" then
|
||||||
local reactor_id = packet.data[4]
|
local reactor_id = packet.data[4]
|
||||||
@ -218,7 +218,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
log.debug("PLC_ESTABLISH: packet length mismatch/bad parameter type")
|
log.debug("PLC_ESTABLISH: packet length mismatch/bad parameter type")
|
||||||
_send_dev_establish(next_seq_id, r_port, { ESTABLISH_ACK.DENY })
|
_send_dev_establish(next_seq_id, r_port, { ESTABLISH_ACK.DENY })
|
||||||
end
|
end
|
||||||
elseif dev_type == DEVICE_TYPES.RTU then
|
elseif dev_type == DEVICE_TYPE.RTU then
|
||||||
if packet.length == 4 then
|
if packet.length == 4 then
|
||||||
-- this is an RTU advertisement for a new session
|
-- this is an RTU advertisement for a new session
|
||||||
local rtu_advert = packet.data[4]
|
local rtu_advert = packet.data[4]
|
||||||
@ -251,12 +251,12 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
-- look for an associated session
|
-- look for an associated session
|
||||||
local session = svsessions.find_coord_session(r_port)
|
local session = svsessions.find_coord_session(r_port)
|
||||||
|
|
||||||
if protocol == PROTOCOLS.SCADA_MGMT then
|
if protocol == PROTOCOL.SCADA_MGMT then
|
||||||
-- SCADA management packet
|
-- SCADA management packet
|
||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
session.in_queue.push_packet(packet)
|
||||||
elseif packet.type == SCADA_MGMT_TYPES.ESTABLISH then
|
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||||
-- establish a new session
|
-- establish a new session
|
||||||
local next_seq_id = packet.scada_frame.seq_num() + 1
|
local next_seq_id = packet.scada_frame.seq_num() + 1
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
" (expected v", comms.version, ")"))
|
" (expected v", comms.version, ")"))
|
||||||
_send_crdn_establish(next_seq_id, r_port, { ESTABLISH_ACK.BAD_VERSION })
|
_send_crdn_establish(next_seq_id, r_port, { ESTABLISH_ACK.BAD_VERSION })
|
||||||
return
|
return
|
||||||
elseif dev_type ~= DEVICE_TYPES.CRDN then
|
elseif dev_type ~= DEVICE_TYPE.CRDN then
|
||||||
log.debug(util.c("illegal establish packet for device ", dev_type, " on CRDN listening channel"))
|
log.debug(util.c("illegal establish packet for device ", dev_type, " on CRDN listening channel"))
|
||||||
_send_crdn_establish(next_seq_id, r_port, { ESTABLISH_ACK.DENY })
|
_send_crdn_establish(next_seq_id, r_port, { ESTABLISH_ACK.DENY })
|
||||||
return
|
return
|
||||||
@ -302,7 +302,7 @@ function supervisor.comms(version, num_reactors, cooling_conf, modem, dev_listen
|
|||||||
-- any other packet should be session related, discard it
|
-- any other packet should be session related, discard it
|
||||||
log.debug(r_port .. "->" .. l_port .. ": discarding SCADA_MGMT packet without a known session")
|
log.debug(r_port .. "->" .. l_port .. ": discarding SCADA_MGMT packet without a known session")
|
||||||
end
|
end
|
||||||
elseif protocol == PROTOCOLS.SCADA_CRDN then
|
elseif protocol == PROTOCOL.SCADA_CRDN then
|
||||||
-- coordinator packet
|
-- coordinator packet
|
||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
|
Loading…
Reference in New Issue
Block a user