mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#300 comms cleanup
This commit is contained in:
parent
f7766d8cba
commit
cfc6479dd5
@ -17,8 +17,8 @@ local println = util.println
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local CRDN_TYPE = comms.CRDN_TYPE
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
local FAC_COMMAND = comms.FAC_COMMAND
|
||||
|
||||
@ -279,7 +279,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
apisessions.init(nic)
|
||||
|
||||
-- send a packet to the supervisor
|
||||
---@param msg_type SCADA_MGMT_TYPE|SCADA_CRDN_TYPE
|
||||
---@param msg_type MGMT_TYPE|CRDN_TYPE
|
||||
---@param msg table
|
||||
local function _send_sv(protocol, msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -307,7 +307,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
local s_pkt = comms.scada_packet()
|
||||
local m_pkt = comms.mgmt_packet()
|
||||
|
||||
m_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, { ack })
|
||||
m_pkt.make(MGMT_TYPE.ESTABLISH, { ack })
|
||||
s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||
|
||||
nic.transmit(pkt_channel, crd_channel, s_pkt)
|
||||
@ -316,13 +316,13 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
|
||||
-- attempt connection establishment
|
||||
local function _send_establish()
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.CRDN })
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.CRDN })
|
||||
end
|
||||
|
||||
-- keep alive ack
|
||||
---@param srv_time integer
|
||||
local function _send_keep_alive_ack(srv_time)
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -394,20 +394,20 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
self.sv_linked = false
|
||||
self.sv_r_seq_num = nil
|
||||
iocontrol.fp_link_state(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- send a facility command
|
||||
---@param cmd FAC_COMMAND command
|
||||
---@param option any? optional option options for the optional options (like waste mode)
|
||||
function public.send_fac_command(cmd, option)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, { cmd, option })
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_CMD, { cmd, option })
|
||||
end
|
||||
|
||||
-- send the auto process control configuration with a start command
|
||||
---@param config coord_auto_config configuration
|
||||
function public.send_auto_start(config)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, {
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_CMD, {
|
||||
FAC_COMMAND.START, config.mode, config.burn_target, config.charge_target, config.gen_target, config.limits
|
||||
})
|
||||
end
|
||||
@ -417,7 +417,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
---@param unit integer unit ID
|
||||
---@param option any? optional option options for the optional options (like burn rate)
|
||||
function public.send_unit_command(cmd, unit, option)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_CMD, { cmd, unit, option })
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.UNIT_CMD, { cmd, unit, option })
|
||||
end
|
||||
|
||||
-- parse a packet
|
||||
@ -426,7 +426,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
---@param reply_to integer
|
||||
---@param message any
|
||||
---@param distance integer
|
||||
---@return mgmt_frame|crdn_frame|capi_frame|nil packet
|
||||
---@return mgmt_frame|crdn_frame|nil packet
|
||||
function public.parse_packet(side, sender, reply_to, message, distance)
|
||||
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
||||
local pkt = nil
|
||||
@ -444,12 +444,6 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
if crdn_pkt.decode(s_pkt) then
|
||||
pkt = crdn_pkt.get()
|
||||
end
|
||||
-- get as coordinator API packet
|
||||
elseif s_pkt.protocol() == PROTOCOL.COORD_API then
|
||||
local capi_pkt = comms.capi_packet()
|
||||
if capi_pkt.decode(s_pkt) then
|
||||
pkt = capi_pkt.get()
|
||||
end
|
||||
else
|
||||
log.debug("attempted parse of illegal packet type " .. s_pkt.protocol(), true)
|
||||
end
|
||||
@ -459,7 +453,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
---@param packet mgmt_frame|crdn_frame|capi_frame|nil
|
||||
---@param packet mgmt_frame|crdn_frame|nil
|
||||
---@return boolean close_ui
|
||||
function public.handle_packet(packet)
|
||||
local was_linked = self.sv_linked
|
||||
@ -475,18 +469,18 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
elseif r_chan == pkt_channel then
|
||||
if not self.sv_linked then
|
||||
log.debug("discarding pocket API packet before linked to supervisor")
|
||||
elseif protocol == PROTOCOL.COORD_API then
|
||||
---@cast packet capi_frame
|
||||
elseif protocol == PROTOCOL.SCADA_CRDN then
|
||||
---@cast packet crdn_frame
|
||||
-- look for an associated session
|
||||
local session = apisessions.find_session(src_addr)
|
||||
|
||||
-- API packet
|
||||
-- coordinator packet
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
else
|
||||
-- any other packet should be session related, discard it
|
||||
log.debug("discarding COORD_API packet without a known session")
|
||||
log.debug("discarding SCADA_CRDN packet without a known session")
|
||||
end
|
||||
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
@ -497,7 +491,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
-- validate packet and continue
|
||||
if packet.length == 3 and type(packet.data[1]) == "string" and type(packet.data[2]) == "string" then
|
||||
@ -553,7 +547,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
if protocol == PROTOCOL.SCADA_CRDN then
|
||||
---@cast packet crdn_frame
|
||||
if self.sv_linked then
|
||||
if packet.type == SCADA_CRDN_TYPE.INITIAL_BUILDS then
|
||||
if packet.type == CRDN_TYPE.INITIAL_BUILDS then
|
||||
if packet.length == 2 then
|
||||
-- record builds
|
||||
local fac_builds = iocontrol.record_facility_builds(packet.data[1])
|
||||
@ -561,31 +555,31 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
|
||||
if fac_builds and unit_builds then
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.INITIAL_BUILDS, {})
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.INITIAL_BUILDS, {})
|
||||
else
|
||||
log.debug("received invalid INITIAL_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("INITIAL_BUILDS packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_BUILDS then
|
||||
elseif packet.type == CRDN_TYPE.FAC_BUILDS then
|
||||
if packet.length == 1 then
|
||||
-- record facility builds
|
||||
if iocontrol.record_facility_builds(packet.data[1]) then
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_BUILDS, {})
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_BUILDS, {})
|
||||
else
|
||||
log.debug("received invalid FAC_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("FAC_BUILDS packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_STATUS then
|
||||
elseif packet.type == CRDN_TYPE.FAC_STATUS then
|
||||
-- update facility status
|
||||
if not iocontrol.update_facility_status(packet.data) then
|
||||
log.debug("received invalid FAC_STATUS packet")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_CMD then
|
||||
elseif packet.type == CRDN_TYPE.FAC_CMD then
|
||||
-- facility command acknowledgement
|
||||
if packet.length >= 2 then
|
||||
local cmd = packet.data[1]
|
||||
@ -613,24 +607,24 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
else
|
||||
log.debug("SCADA_CRDN facility command ack packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
||||
elseif packet.type == CRDN_TYPE.UNIT_BUILDS then
|
||||
-- record builds
|
||||
if packet.length == 1 then
|
||||
if iocontrol.record_unit_builds(packet.data[1]) then
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_BUILDS, {})
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.UNIT_BUILDS, {})
|
||||
else
|
||||
log.debug("received invalid UNIT_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("UNIT_BUILDS packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_STATUSES then
|
||||
elseif packet.type == CRDN_TYPE.UNIT_STATUSES then
|
||||
-- update statuses
|
||||
if not iocontrol.update_unit_statuses(packet.data) then
|
||||
log.debug("received invalid UNIT_STATUSES packet")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_CMD then
|
||||
elseif packet.type == CRDN_TYPE.UNIT_CMD then
|
||||
-- unit command acknowledgement
|
||||
if packet.length == 3 then
|
||||
local cmd = packet.data[1]
|
||||
@ -672,7 +666,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
if self.sv_linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 then
|
||||
local timestamp = packet.data[1]
|
||||
@ -690,7 +684,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
else
|
||||
log.debug("SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
sv_watchdog.cancel()
|
||||
self.sv_addr = comms.BROADCAST
|
||||
@ -701,7 +695,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
else
|
||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type)
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- connection with supervisor established
|
||||
if packet.length == 2 then
|
||||
local est_ack = packet.data[1]
|
||||
|
@ -8,8 +8,8 @@ local iocontrol = require("coordinator.iocontrol")
|
||||
local pocket = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
-- local CAPI_TYPE = comms.CAPI_TYPE
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
-- local CRDN_TYPE = comms.CRDN_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
-- retry time constants in ms
|
||||
-- local INITIAL_WAIT = 1500
|
||||
@ -72,22 +72,22 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
iocontrol.fp_pkt_disconnected(id)
|
||||
end
|
||||
|
||||
-- send a CAPI packet
|
||||
-----@param msg_type CAPI_TYPE
|
||||
-- send a CRDN packet
|
||||
-----@param msg_type CRDN_TYPE
|
||||
-----@param msg table
|
||||
-- local function _send(msg_type, msg)
|
||||
-- local s_pkt = comms.scada_packet()
|
||||
-- local c_pkt = comms.capi_packet()
|
||||
-- local c_pkt = comms.crdn_packet()
|
||||
|
||||
-- c_pkt.make(msg_type, msg)
|
||||
-- s_pkt.make(self.seq_num, PROTOCOL.COORD_API, c_pkt.raw_sendable())
|
||||
-- s_pkt.make(self.seq_num, PROTOCOL.SCADA_CRDN, c_pkt.raw_sendable())
|
||||
|
||||
-- out_queue.push_packet(s_pkt)
|
||||
-- self.seq_num = self.seq_num + 1
|
||||
-- end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -101,7 +101,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
---@param pkt mgmt_frame|capi_frame
|
||||
---@param pkt mgmt_frame|crdn_frame
|
||||
local function _handle_packet(pkt)
|
||||
-- check sequence number
|
||||
if self.r_seq_num == nil then
|
||||
@ -117,17 +117,17 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
self.conn_watchdog.feed()
|
||||
|
||||
-- process packet
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.COORD_API then
|
||||
---@cast pkt capi_frame
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||
---@cast pkt crdn_frame
|
||||
|
||||
-- handle packet by type
|
||||
if pkt.type == nil then
|
||||
else
|
||||
log.debug(log_header .. "handler received unsupported CAPI packet type " .. pkt.type)
|
||||
log.debug(log_header .. "handler received unsupported CRDN packet type " .. pkt.type)
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -146,7 +146,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
else
|
||||
@ -174,7 +174,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
|
||||
@ -229,7 +229,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -22,7 +22,7 @@ local sounder = require("coordinator.sounder")
|
||||
|
||||
local apisessions = require("coordinator.session.apisessions")
|
||||
|
||||
local COORDINATOR_VERSION = "v1.0.9"
|
||||
local COORDINATOR_VERSION = "v1.0.10"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -7,7 +7,7 @@ local iocontrol = require("pocket.iocontrol")
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
local LINK_STATE = iocontrol.LINK_STATE
|
||||
|
||||
@ -51,7 +51,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
nic.open(pkt_channel)
|
||||
|
||||
-- send a management packet to the supervisor
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_sv(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -65,7 +65,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
end
|
||||
|
||||
-- send a management packet to the coordinator
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_crd(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -80,24 +80,24 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
|
||||
-- attempt supervisor connection establishment
|
||||
local function _send_sv_establish()
|
||||
_send_sv(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
_send_sv(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
end
|
||||
|
||||
-- attempt coordinator API connection establishment
|
||||
local function _send_api_establish()
|
||||
_send_crd(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
_send_crd(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
end
|
||||
|
||||
-- keep alive ack to supervisor
|
||||
---@param srv_time integer
|
||||
local function _send_sv_keep_alive_ack(srv_time)
|
||||
_send_sv(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_sv(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- keep alive ack to coordinator
|
||||
---@param srv_time integer
|
||||
local function _send_api_keep_alive_ack(srv_time)
|
||||
_send_crd(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_crd(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -111,7 +111,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
self.sv.linked = false
|
||||
self.sv.r_seq_num = nil
|
||||
self.sv.addr = comms.BROADCAST
|
||||
_send_sv(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_sv(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- close connection to coordinator API server
|
||||
@ -120,7 +120,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
self.api.linked = false
|
||||
self.api.r_seq_num = nil
|
||||
self.api.addr = comms.BROADCAST
|
||||
_send_crd(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_crd(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- close the connections to the servers
|
||||
@ -157,21 +157,21 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
|
||||
-- supervisor get active alarm tones
|
||||
function public.diag__get_alarm_tones()
|
||||
if self.sv.linked then _send_sv(SCADA_MGMT_TYPE.DIAG_TONE_GET, {}) end
|
||||
if self.sv.linked then _send_sv(MGMT_TYPE.DIAG_TONE_GET, {}) end
|
||||
end
|
||||
|
||||
-- supervisor test alarm tones by tone
|
||||
---@param id TONE|0 tone ID, or 0 to stop all
|
||||
---@param state boolean tone state
|
||||
function public.diag__set_alarm_tone(id, state)
|
||||
if self.sv.linked then _send_sv(SCADA_MGMT_TYPE.DIAG_TONE_SET, { id, state }) end
|
||||
if self.sv.linked then _send_sv(MGMT_TYPE.DIAG_TONE_SET, { id, state }) end
|
||||
end
|
||||
|
||||
-- supervisor test alarm tones by alarm
|
||||
---@param id ALARM|0 alarm ID, 0 to stop all
|
||||
---@param state boolean alarm state
|
||||
function public.diag__set_alarm(id, state)
|
||||
if self.sv.linked then _send_sv(SCADA_MGMT_TYPE.DIAG_ALARM_SET, { id, state }) end
|
||||
if self.sv.linked then _send_sv(MGMT_TYPE.DIAG_ALARM_SET, { id, state }) end
|
||||
end
|
||||
|
||||
-- parse a packet
|
||||
@ -180,7 +180,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
---@param reply_to integer
|
||||
---@param message any
|
||||
---@param distance integer
|
||||
---@return mgmt_frame|capi_frame|nil packet
|
||||
---@return mgmt_frame|crdn_frame|nil packet
|
||||
function public.parse_packet(side, sender, reply_to, message, distance)
|
||||
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
||||
local pkt = nil
|
||||
@ -192,11 +192,11 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
if mgmt_pkt.decode(s_pkt) then
|
||||
pkt = mgmt_pkt.get()
|
||||
end
|
||||
-- get as coordinator API packet
|
||||
elseif s_pkt.protocol() == PROTOCOL.COORD_API then
|
||||
local capi_pkt = comms.capi_packet()
|
||||
if capi_pkt.decode(s_pkt) then
|
||||
pkt = capi_pkt.get()
|
||||
-- get as coordinator packet
|
||||
elseif s_pkt.protocol() == PROTOCOL.SCADA_CRDN then
|
||||
local crdn_pkt = comms.crdn_packet()
|
||||
if crdn_pkt.decode(s_pkt) then
|
||||
pkt = crdn_pkt.get()
|
||||
end
|
||||
else
|
||||
log.debug("attempted parse of illegal packet type " .. s_pkt.protocol(), true)
|
||||
@ -207,7 +207,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
---@param packet mgmt_frame|capi_frame|nil
|
||||
---@param packet mgmt_frame|crdn_frame|nil
|
||||
function public.handle_packet(packet)
|
||||
local diag = iocontrol.get_db().diag
|
||||
|
||||
@ -240,7 +240,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
if protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
if self.api.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 then
|
||||
local timestamp = packet.data[1]
|
||||
@ -256,7 +256,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("coordinator SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
api_watchdog.cancel()
|
||||
self.api.linked = false
|
||||
@ -266,7 +266,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from coordinator")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- connection with coordinator established
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
@ -330,7 +330,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
if protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
if self.sv.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 then
|
||||
local timestamp = packet.data[1]
|
||||
@ -346,14 +346,14 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("supervisor SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
sv_watchdog.cancel()
|
||||
self.sv.linked = false
|
||||
self.sv.r_seq_num = nil
|
||||
self.sv.addr = comms.BROADCAST
|
||||
log.info("supervisor server connection closed by remote host")
|
||||
elseif packet.type == SCADA_MGMT_TYPE.DIAG_TONE_GET then
|
||||
elseif packet.type == MGMT_TYPE.DIAG_TONE_GET then
|
||||
if packet.length == 8 then
|
||||
for i = 1, #packet.data do
|
||||
diag.tone_test.tone_indicators[i].update(packet.data[i] == true)
|
||||
@ -361,7 +361,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("supervisor SCADA diag alarm states packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.DIAG_TONE_SET then
|
||||
elseif packet.type == MGMT_TYPE.DIAG_TONE_SET then
|
||||
if packet.length == 1 and packet.data[1] == false then
|
||||
diag.tone_test.ready_warn.set_value("testing denied")
|
||||
log.debug("supervisor SCADA diag tone set failed")
|
||||
@ -380,7 +380,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("supervisor SCADA diag tone set packet length/type mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.DIAG_ALARM_SET then
|
||||
elseif packet.type == MGMT_TYPE.DIAG_ALARM_SET then
|
||||
if packet.length == 1 and packet.data[1] == false then
|
||||
diag.tone_test.ready_warn.set_value("testing denied")
|
||||
log.debug("supervisor SCADA diag alarm set failed")
|
||||
@ -401,7 +401,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from supervisor")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- connection with supervisor established
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
|
@ -18,7 +18,7 @@ local iocontrol = require("pocket.iocontrol")
|
||||
local pocket = require("pocket.pocket")
|
||||
local renderer = require("pocket.renderer")
|
||||
|
||||
local POCKET_VERSION = "v0.6.0-alpha"
|
||||
local POCKET_VERSION = "v0.6.1-alpha"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -16,7 +16,7 @@ local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local RPLC_TYPE = comms.RPLC_TYPE
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local AUTO_ACK = comms.PLC_AUTO_ACK
|
||||
|
||||
local RPS_LIMITS = const.RPS_LIMITS
|
||||
@ -489,7 +489,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -600,7 +600,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
-- keep alive ack
|
||||
---@param srv_time integer
|
||||
local function _send_keep_alive_ack(srv_time)
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- general ack
|
||||
@ -668,12 +668,12 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
function public.close()
|
||||
conn_watchdog.cancel()
|
||||
public.unlink()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- attempt to establish link with supervisor
|
||||
function public.send_link_req()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PLC, id })
|
||||
_send_mgmt(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PLC, id })
|
||||
end
|
||||
|
||||
-- send live status information
|
||||
@ -929,7 +929,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
---@cast packet mgmt_frame
|
||||
-- if linked, only accept packets from configured supervisor
|
||||
if self.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||
local timestamp = packet.data[1]
|
||||
@ -945,7 +945,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
else
|
||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
conn_watchdog.cancel()
|
||||
public.unlink()
|
||||
@ -954,7 +954,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
else
|
||||
log.debug("received unsupported SCADA_MGMT packet type " .. packet.type)
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- link request confirmation
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
|
@ -19,7 +19,7 @@ local plc = require("reactor-plc.plc")
|
||||
local renderer = require("reactor-plc.renderer")
|
||||
local threads = require("reactor-plc.threads")
|
||||
|
||||
local R_PLC_VERSION = "v1.5.7"
|
||||
local R_PLC_VERSION = "v1.5.8"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
24
rtu/rtu.lua
24
rtu/rtu.lua
@ -14,7 +14,7 @@ local rtu = {}
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
|
||||
-- create a new RTU unit
|
||||
@ -227,7 +227,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
nic.open(rtu_channel)
|
||||
|
||||
-- send a scada management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -243,7 +243,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
-- keep alive ack
|
||||
---@param srv_time integer
|
||||
local function _send_keep_alive_ack(srv_time)
|
||||
_send(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- generate device advertisement table
|
||||
@ -298,25 +298,25 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
function public.close(rtu_state)
|
||||
conn_watchdog.cancel()
|
||||
public.unlink(rtu_state)
|
||||
_send(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- send establish request (includes advertisement)
|
||||
---@param units table
|
||||
function public.send_establish(units)
|
||||
_send(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.RTU, _generate_advertisement(units) })
|
||||
_send(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.RTU, _generate_advertisement(units) })
|
||||
end
|
||||
|
||||
-- send capability advertisement
|
||||
---@param units table
|
||||
function public.send_advertisement(units)
|
||||
_send(SCADA_MGMT_TYPE.RTU_ADVERT, _generate_advertisement(units))
|
||||
_send(MGMT_TYPE.RTU_ADVERT, _generate_advertisement(units))
|
||||
end
|
||||
|
||||
-- notify that a peripheral was remounted
|
||||
---@param unit_index integer RTU unit ID
|
||||
function public.send_remounted(unit_index)
|
||||
_send(SCADA_MGMT_TYPE.RTU_DEV_REMOUNT, { unit_index })
|
||||
_send(MGMT_TYPE.RTU_DEV_REMOUNT, { unit_index })
|
||||
end
|
||||
|
||||
-- parse a MODBUS/SCADA packet
|
||||
@ -433,7 +433,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
---@cast packet mgmt_frame
|
||||
-- SCADA management packet
|
||||
if rtu_state.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||
local timestamp = packet.data[1]
|
||||
@ -449,16 +449,16 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
else
|
||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- close connection
|
||||
conn_watchdog.cancel()
|
||||
public.unlink(rtu_state)
|
||||
println_ts("server connection closed by remote host")
|
||||
log.warning("server connection closed by remote host")
|
||||
elseif packet.type == SCADA_MGMT_TYPE.RTU_ADVERT then
|
||||
elseif packet.type == MGMT_TYPE.RTU_ADVERT then
|
||||
-- request for capabilities again
|
||||
public.send_advertisement(units)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.RTU_TONE_ALARM then
|
||||
elseif packet.type == MGMT_TYPE.RTU_TONE_ALARM then
|
||||
-- alarm tone update from supervisor
|
||||
if (packet.length == 1) and type(packet.data[1] == "table") and (#packet.data[1] == 8) then
|
||||
local states = packet.data[1]
|
||||
@ -474,7 +474,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
-- not supported
|
||||
log.debug("received unsupported SCADA_MGMT message type " .. packet.type)
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
|
||||
|
@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
|
||||
local sps_rtu = require("rtu.dev.sps_rtu")
|
||||
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
|
||||
|
||||
local RTU_VERSION = "v1.6.2"
|
||||
local RTU_VERSION = "v1.6.3"
|
||||
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
||||
|
@ -6,23 +6,25 @@ local log = require("scada-common.log")
|
||||
|
||||
local insert = table.insert
|
||||
|
||||
---@type integer computer ID
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local COMPUTER_ID = os.getComputerID() ---@type integer computer ID
|
||||
local COMPUTER_ID = os.getComputerID()
|
||||
|
||||
local max_distance = nil ---@type number|nil maximum acceptable transmission distance
|
||||
---@type number|nil maximum acceptable transmission distance
|
||||
local max_distance = nil
|
||||
|
||||
---@class comms
|
||||
local comms = {}
|
||||
|
||||
comms.version = "2.2.1"
|
||||
-- protocol version (non-protocol changes tracked by util.lua version)
|
||||
comms.version = "2.3.0"
|
||||
|
||||
---@enum PROTOCOL
|
||||
local PROTOCOL = {
|
||||
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
||||
RPLC = 1, -- reactor PLC protocol
|
||||
SCADA_MGMT = 2, -- SCADA supervisor management, device advertisements, etc
|
||||
SCADA_CRDN = 3, -- data/control packets for coordinators to/from supervisory controllers
|
||||
COORD_API = 4 -- data/control packets for pocket computers to/from coordinators
|
||||
SCADA_CRDN = 3 -- data/control packets for coordinators to/from supervisory controllers
|
||||
}
|
||||
|
||||
---@enum RPLC_TYPE
|
||||
@ -40,8 +42,8 @@ local RPLC_TYPE = {
|
||||
AUTO_BURN_RATE = 10 -- set an automatic burn rate, PLC will respond with status, enable toggle speed limited
|
||||
}
|
||||
|
||||
---@enum SCADA_MGMT_TYPE
|
||||
local SCADA_MGMT_TYPE = {
|
||||
---@enum MGMT_TYPE
|
||||
local MGMT_TYPE = {
|
||||
ESTABLISH = 0, -- establish new connection
|
||||
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
||||
CLOSE = 2, -- close a connection
|
||||
@ -53,8 +55,8 @@ local SCADA_MGMT_TYPE = {
|
||||
DIAG_ALARM_SET = 8 -- diagnostic: set alarm to simulate audio for
|
||||
}
|
||||
|
||||
---@enum SCADA_CRDN_TYPE
|
||||
local SCADA_CRDN_TYPE = {
|
||||
---@enum CRDN_TYPE
|
||||
local CRDN_TYPE = {
|
||||
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
||||
FAC_BUILDS = 1, -- facility RTU builds
|
||||
FAC_STATUS = 2, -- state of facility and facility devices
|
||||
@ -64,10 +66,6 @@ local SCADA_CRDN_TYPE = {
|
||||
UNIT_CMD = 6 -- command a reactor unit
|
||||
}
|
||||
|
||||
---@enum CAPI_TYPE
|
||||
local CAPI_TYPE = {
|
||||
}
|
||||
|
||||
---@enum ESTABLISH_ACK
|
||||
local ESTABLISH_ACK = {
|
||||
ALLOW = 0, -- link approved
|
||||
@ -119,9 +117,8 @@ local UNIT_COMMAND = {
|
||||
comms.PROTOCOL = PROTOCOL
|
||||
|
||||
comms.RPLC_TYPE = RPLC_TYPE
|
||||
comms.SCADA_MGMT_TYPE = SCADA_MGMT_TYPE
|
||||
comms.SCADA_CRDN_TYPE = SCADA_CRDN_TYPE
|
||||
comms.CAPI_TYPE = CAPI_TYPE
|
||||
comms.MGMT_TYPE = MGMT_TYPE
|
||||
comms.CRDN_TYPE = CRDN_TYPE
|
||||
|
||||
comms.ESTABLISH_ACK = ESTABLISH_ACK
|
||||
comms.DEVICE_TYPE = DEVICE_TYPE
|
||||
@ -134,8 +131,8 @@ comms.FAC_COMMAND = FAC_COMMAND
|
||||
-- destination broadcast address (to all devices)
|
||||
comms.BROADCAST = -1
|
||||
|
||||
---@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 packet scada_packet|modbus_packet|rplc_packet|mgmt_packet|crdn_packet
|
||||
---@alias frame modbus_frame|rplc_frame|mgmt_frame|crdn_frame
|
||||
|
||||
-- configure the maximum allowable message receive distance<br>
|
||||
-- packets received with distances greater than this will be silently discarded
|
||||
@ -144,7 +141,7 @@ function comms.set_trusted_range(distance)
|
||||
if distance == 0 then max_distance = nil else max_distance = distance end
|
||||
end
|
||||
|
||||
-- generic SCADA packet object
|
||||
-- generic SCADA packet
|
||||
---@nodiscard
|
||||
function comms.scada_packet()
|
||||
local self = {
|
||||
@ -199,9 +196,9 @@ function comms.scada_packet()
|
||||
self.valid = false
|
||||
self.raw = self.modem_msg_in.msg
|
||||
|
||||
if (type(max_distance) == "number") and (distance > max_distance) then
|
||||
if (type(max_distance) == "number") and (type(distance) == "number") and (distance > max_distance) then
|
||||
-- outside of maximum allowable transmission distance
|
||||
-- log.debug("comms.scada_packet.receive(): discarding packet with distance " .. distance .. " outside of trusted range")
|
||||
-- log.debug("comms.scada_packet.receive(): discarding packet with distance " .. distance .. " (outside trusted range)")
|
||||
else
|
||||
if type(self.raw) == "table" then
|
||||
if #self.raw == 5 then
|
||||
@ -227,12 +224,8 @@ function comms.scada_packet()
|
||||
-- check if this packet is destined for this device
|
||||
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
||||
|
||||
self.valid = is_destination and
|
||||
type(self.src_addr) == "number" and
|
||||
type(self.dest_addr) == "number" and
|
||||
type(self.seq_num) == "number" and
|
||||
type(self.protocol) == "number" and
|
||||
type(self.payload) == "table"
|
||||
self.valid = is_destination and type(self.src_addr) == "number" and type(self.dest_addr) == "number" and
|
||||
type(self.seq_num) == "number" and type(self.protocol) == "number" and type(self.payload) == "table"
|
||||
end
|
||||
end
|
||||
|
||||
@ -275,7 +268,7 @@ function comms.scada_packet()
|
||||
return public
|
||||
end
|
||||
|
||||
-- authenticated SCADA packet object
|
||||
-- authenticated SCADA packet
|
||||
---@nodiscard
|
||||
function comms.authd_packet()
|
||||
local self = {
|
||||
@ -325,7 +318,7 @@ function comms.authd_packet()
|
||||
|
||||
if (type(max_distance) == "number") and (type(distance) == "number") and (distance > max_distance) then
|
||||
-- outside of maximum allowable transmission distance
|
||||
-- log.debug("comms.authd_packet.receive(): discarding packet with distance " .. distance .. " outside of trusted range")
|
||||
-- log.debug("comms.authd_packet.receive(): discarding packet with distance " .. distance .. " (outside trusted range)")
|
||||
else
|
||||
if type(self.raw) == "table" then
|
||||
if #self.raw == 4 then
|
||||
@ -343,11 +336,8 @@ function comms.authd_packet()
|
||||
-- check if this packet is destined for this device
|
||||
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
||||
|
||||
self.valid = is_destination and
|
||||
type(self.src_addr) == "number" and
|
||||
type(self.dest_addr) == "number" and
|
||||
type(self.mac) == "string" and
|
||||
type(self.payload) == "string"
|
||||
self.valid = is_destination and type(self.src_addr) == "number" and type(self.dest_addr) == "number" and
|
||||
type(self.mac) == "string" and type(self.payload) == "string"
|
||||
end
|
||||
end
|
||||
|
||||
@ -381,8 +371,7 @@ function comms.authd_packet()
|
||||
return public
|
||||
end
|
||||
|
||||
-- MODBUS packet<br>
|
||||
-- modeled after MODBUS TCP packet
|
||||
-- MODBUS packet, modeled after MODBUS TCP
|
||||
---@nodiscard
|
||||
function comms.modbus_packet()
|
||||
local self = {
|
||||
@ -436,9 +425,7 @@ function comms.modbus_packet()
|
||||
public.make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
|
||||
end
|
||||
|
||||
local valid = type(self.txn_id) == "number" and
|
||||
type(self.unit_id) == "number" and
|
||||
type(self.func_code) == "number"
|
||||
local valid = type(self.txn_id) == "number" and type(self.unit_id) == "number" and type(self.func_code) == "number"
|
||||
|
||||
return size_ok and valid
|
||||
else
|
||||
@ -489,21 +476,6 @@ function comms.rplc_packet()
|
||||
---@class rplc_packet
|
||||
local public = {}
|
||||
|
||||
-- check that type is known
|
||||
local function _rplc_type_valid()
|
||||
return self.type == RPLC_TYPE.STATUS or
|
||||
self.type == RPLC_TYPE.MEK_STRUCT or
|
||||
self.type == RPLC_TYPE.MEK_BURN_RATE or
|
||||
self.type == RPLC_TYPE.RPS_ENABLE or
|
||||
self.type == RPLC_TYPE.RPS_SCRAM or
|
||||
self.type == RPLC_TYPE.RPS_ASCRAM or
|
||||
self.type == RPLC_TYPE.RPS_STATUS or
|
||||
self.type == RPLC_TYPE.RPS_ALARM or
|
||||
self.type == RPLC_TYPE.RPS_RESET or
|
||||
self.type == RPLC_TYPE.RPS_AUTO_RESET or
|
||||
self.type == RPLC_TYPE.AUTO_BURN_RATE
|
||||
end
|
||||
|
||||
-- make an RPLC packet
|
||||
---@param id integer
|
||||
---@param packet_type RPLC_TYPE
|
||||
@ -539,7 +511,6 @@ function comms.rplc_packet()
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], data[2], { table.unpack(data, 3, #data) })
|
||||
ok = _rplc_type_valid()
|
||||
end
|
||||
|
||||
ok = ok and type(self.id) == "number"
|
||||
@ -583,7 +554,7 @@ function comms.mgmt_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
raw = {},
|
||||
type = 0, ---@type SCADA_MGMT_TYPE
|
||||
type = 0, ---@type MGMT_TYPE
|
||||
length = 0,
|
||||
data = {}
|
||||
}
|
||||
@ -591,22 +562,8 @@ function comms.mgmt_packet()
|
||||
---@class mgmt_packet
|
||||
local public = {}
|
||||
|
||||
-- check that type is known
|
||||
local function _scada_type_valid()
|
||||
return self.type == SCADA_MGMT_TYPE.ESTABLISH or
|
||||
self.type == SCADA_MGMT_TYPE.KEEP_ALIVE or
|
||||
self.type == SCADA_MGMT_TYPE.CLOSE or
|
||||
self.type == SCADA_MGMT_TYPE.REMOTE_LINKED or
|
||||
self.type == SCADA_MGMT_TYPE.RTU_ADVERT or
|
||||
self.type == SCADA_MGMT_TYPE.RTU_DEV_REMOUNT or
|
||||
self.type == SCADA_MGMT_TYPE.RTU_TONE_ALARM or
|
||||
self.type == SCADA_MGMT_TYPE.DIAG_TONE_GET or
|
||||
self.type == SCADA_MGMT_TYPE.DIAG_TONE_SET or
|
||||
self.type == SCADA_MGMT_TYPE.DIAG_ALARM_SET
|
||||
end
|
||||
|
||||
-- make a SCADA management packet
|
||||
---@param packet_type SCADA_MGMT_TYPE
|
||||
---@param packet_type MGMT_TYPE
|
||||
---@param data table
|
||||
function public.make(packet_type, data)
|
||||
if type(data) == "table" then
|
||||
@ -638,7 +595,6 @@ function comms.mgmt_packet()
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||
ok = _scada_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
@ -679,7 +635,7 @@ function comms.crdn_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
raw = {},
|
||||
type = 0, ---@type SCADA_CRDN_TYPE
|
||||
type = 0, ---@type CRDN_TYPE
|
||||
length = 0,
|
||||
data = {}
|
||||
}
|
||||
@ -687,20 +643,8 @@ function comms.crdn_packet()
|
||||
---@class crdn_packet
|
||||
local public = {}
|
||||
|
||||
-- check that type is known
|
||||
---@nodiscard
|
||||
local function _crdn_type_valid()
|
||||
return self.type == SCADA_CRDN_TYPE.INITIAL_BUILDS or
|
||||
self.type == SCADA_CRDN_TYPE.FAC_BUILDS or
|
||||
self.type == SCADA_CRDN_TYPE.FAC_STATUS or
|
||||
self.type == SCADA_CRDN_TYPE.FAC_CMD or
|
||||
self.type == SCADA_CRDN_TYPE.UNIT_BUILDS or
|
||||
self.type == SCADA_CRDN_TYPE.UNIT_STATUSES or
|
||||
self.type == SCADA_CRDN_TYPE.UNIT_CMD
|
||||
end
|
||||
|
||||
-- make a coordinator packet
|
||||
---@param packet_type SCADA_CRDN_TYPE
|
||||
---@param packet_type CRDN_TYPE
|
||||
---@param data table
|
||||
function public.make(packet_type, data)
|
||||
if type(data) == "table" then
|
||||
@ -732,7 +676,6 @@ function comms.crdn_packet()
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||
ok = _crdn_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
@ -767,92 +710,4 @@ function comms.crdn_packet()
|
||||
return public
|
||||
end
|
||||
|
||||
-- coordinator API (CAPI) packet
|
||||
---@todo implement for pocket access, set enum type for self.type
|
||||
---@nodiscard
|
||||
function comms.capi_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
raw = {},
|
||||
type = 0,
|
||||
length = 0,
|
||||
data = {}
|
||||
}
|
||||
|
||||
---@class capi_packet
|
||||
local public = {}
|
||||
|
||||
local function _capi_type_valid()
|
||||
---@todo
|
||||
return false
|
||||
end
|
||||
|
||||
-- make a coordinator API packet
|
||||
---@param packet_type CAPI_TYPE
|
||||
---@param data table
|
||||
function public.make(packet_type, data)
|
||||
if type(data) == "table" then
|
||||
-- packet accessor properties
|
||||
self.type = packet_type
|
||||
self.length = #data
|
||||
self.data = data
|
||||
|
||||
-- populate raw array
|
||||
self.raw = { self.type }
|
||||
for i = 1, #data do
|
||||
insert(self.raw, data[i])
|
||||
end
|
||||
else
|
||||
log.error("comms.capi_packet.make(): data not table")
|
||||
end
|
||||
end
|
||||
|
||||
-- decode a coordinator API packet from a SCADA frame
|
||||
---@param frame scada_packet
|
||||
---@return boolean success
|
||||
function public.decode(frame)
|
||||
if frame then
|
||||
self.frame = frame
|
||||
|
||||
if frame.protocol() == PROTOCOL.COORD_API then
|
||||
local ok = frame.length() >= 1
|
||||
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||
ok = _capi_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
else
|
||||
log.debug("attempted COORD_API parse of incorrect protocol " .. frame.protocol(), true)
|
||||
return false
|
||||
end
|
||||
else
|
||||
log.debug("nil frame encountered", true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- get raw to send
|
||||
---@nodiscard
|
||||
function public.raw_sendable() return self.raw end
|
||||
|
||||
-- get this packet as a frame with an immutable relation to this object
|
||||
---@nodiscard
|
||||
function public.get()
|
||||
---@class capi_frame
|
||||
local frame = {
|
||||
scada_frame = self.frame,
|
||||
type = self.type,
|
||||
length = self.length,
|
||||
data = self.data
|
||||
}
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
return comms
|
||||
|
@ -8,7 +8,7 @@ local cc_strings = require("cc.strings")
|
||||
local util = {}
|
||||
|
||||
-- scada-common version
|
||||
util.version = "1.0.2"
|
||||
util.version = "1.1.0"
|
||||
|
||||
-- ENVIRONMENT CONSTANTS --
|
||||
|
||||
|
@ -10,8 +10,8 @@ local svqtypes = require("supervisor.session.svqtypes")
|
||||
local coordinator = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local CRDN_TYPE = comms.CRDN_TYPE
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
local FAC_COMMAND = comms.FAC_COMMAND
|
||||
|
||||
@ -94,7 +94,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
|
||||
-- send a CRDN packet
|
||||
---@param msg_type SCADA_CRDN_TYPE
|
||||
---@param msg_type CRDN_TYPE
|
||||
---@param msg table
|
||||
local function _send(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -108,7 +108,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -130,12 +130,12 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
unit_builds[unit.get_id()] = unit.get_build()
|
||||
end
|
||||
|
||||
_send(SCADA_CRDN_TYPE.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
||||
_send(CRDN_TYPE.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
||||
end
|
||||
|
||||
-- send facility builds
|
||||
local function _send_fac_builds()
|
||||
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build() })
|
||||
_send(CRDN_TYPE.FAC_BUILDS, { facility.get_build() })
|
||||
end
|
||||
|
||||
-- send unit builds
|
||||
@ -147,7 +147,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
builds[unit.get_id()] = unit.get_build()
|
||||
end
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
end
|
||||
|
||||
-- send facility status
|
||||
@ -158,7 +158,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
facility.get_alarm_tones()
|
||||
}
|
||||
|
||||
_send(SCADA_CRDN_TYPE.FAC_STATUS, status)
|
||||
_send(CRDN_TYPE.FAC_STATUS, status)
|
||||
end
|
||||
|
||||
-- send unit statuses
|
||||
@ -178,7 +178,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
}
|
||||
end
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_STATUSES, status)
|
||||
_send(CRDN_TYPE.UNIT_STATUSES, status)
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
@ -200,7 +200,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
-- process packet
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -219,7 +219,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
else
|
||||
@ -227,22 +227,22 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||
---@cast pkt crdn_frame
|
||||
if pkt.type == SCADA_CRDN_TYPE.INITIAL_BUILDS then
|
||||
if pkt.type == CRDN_TYPE.INITIAL_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.FAC_BUILDS then
|
||||
elseif pkt.type == CRDN_TYPE.FAC_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.fac_builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.FAC_CMD then
|
||||
elseif pkt.type == CRDN_TYPE.FAC_CMD then
|
||||
if pkt.length >= 1 then
|
||||
local cmd = pkt.data[1]
|
||||
|
||||
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||
facility.scram_all()
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
elseif cmd == FAC_COMMAND.STOP then
|
||||
facility.auto_stop()
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
elseif cmd == FAC_COMMAND.START then
|
||||
if pkt.length == 6 then
|
||||
---@type coord_auto_config
|
||||
@ -254,22 +254,22 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
limits = pkt.data[6]
|
||||
}
|
||||
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, table.unpack(facility.auto_start(config)) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, table.unpack(facility.auto_start(config)) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN auto start (with configuration) packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||
facility.ack_all()
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||
if pkt.length == 2 then
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, facility.set_waste_product(pkt.data[2]) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_waste_product(pkt.data[2]) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN set waste mode packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||
if pkt.length == 2 then
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2]) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2]) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN set pu fallback packet length mismatch")
|
||||
end
|
||||
@ -279,10 +279,10 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
else
|
||||
log.debug(log_header .. "CRDN facility command packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
||||
elseif pkt.type == CRDN_TYPE.UNIT_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.unit_builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.UNIT_CMD then
|
||||
elseif pkt.type == CRDN_TYPE.UNIT_CMD then
|
||||
if pkt.length >= 2 then
|
||||
-- get command and unit id
|
||||
local cmd = pkt.data[1]
|
||||
@ -315,7 +315,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||
unit.ack_all()
|
||||
_send(SCADA_CRDN_TYPE.UNIT_CMD, { cmd, uid, true })
|
||||
_send(CRDN_TYPE.UNIT_CMD, { cmd, uid, true })
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
||||
if pkt.length == 3 then
|
||||
unit.ack_alarm(pkt.data[3])
|
||||
@ -331,7 +331,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
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
|
||||
facility.set_group(unit.get_id(), pkt.data[3])
|
||||
_send(SCADA_CRDN_TYPE.UNIT_CMD, { cmd, uid, pkt.data[3] })
|
||||
_send(CRDN_TYPE.UNIT_CMD, { cmd, uid, pkt.data[3] })
|
||||
else
|
||||
log.debug(log_header .. "CRDN unit command set group missing group id")
|
||||
end
|
||||
@ -374,7 +374,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println("connection to coordinator " .. id .. " closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -406,7 +406,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
|
||||
if cmd.key == CRD_S_DATA.CMD_ACK then
|
||||
local ack = cmd.val ---@type coord_ack
|
||||
_send(SCADA_CRDN_TYPE.UNIT_CMD, { ack.cmd, ack.unit, ack.ack })
|
||||
_send(CRDN_TYPE.UNIT_CMD, { ack.cmd, ack.unit, ack.ack })
|
||||
elseif cmd.key == CRD_S_DATA.RESEND_PLC_BUILD then
|
||||
-- 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
|
||||
@ -419,7 +419,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
local unit = self.units[unit_id] ---@type reactor_unit
|
||||
builds[unit_id] = unit.get_build(-1)
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
elseif cmd.key == CRD_S_DATA.RESEND_RTU_BUILD then
|
||||
local unit_id = cmd.val.unit
|
||||
if unit_id > 0 then
|
||||
@ -433,14 +433,14 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
local unit = self.units[unit_id] ---@type reactor_unit
|
||||
builds[unit_id] = unit.get_build(cmd.val.type)
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
else
|
||||
-- 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
|
||||
self.retry_times.f_builds_packet = util.time() + PARTIAL_RETRY_PERIOD
|
||||
self.acks.fac_builds = false
|
||||
|
||||
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type) })
|
||||
_send(CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type) })
|
||||
end
|
||||
else
|
||||
log.error(log_header .. "unsupported data command received in in_queue (this is a bug)", true)
|
||||
@ -474,7 +474,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -12,7 +12,7 @@ local plc = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local RPLC_TYPE = comms.RPLC_TYPE
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local PLC_AUTO_ACK = comms.PLC_AUTO_ACK
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
|
||||
@ -258,7 +258,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -482,7 +482,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -501,7 +501,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
else
|
||||
@ -595,7 +595,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println("connection to reactor " .. reactor_id .. " PLC closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -726,7 +726,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -7,7 +7,7 @@ local databus = require("supervisor.databus")
|
||||
local pocket = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
-- retry time constants in ms
|
||||
-- local INITIAL_WAIT = 1500
|
||||
@ -76,7 +76,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -108,7 +108,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
-- process packet
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -127,13 +127,13 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_TONE_GET then
|
||||
elseif pkt.type == MGMT_TYPE.DIAG_TONE_GET then
|
||||
-- get the state of alarm tones
|
||||
_send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_GET, facility.get_alarm_tones())
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_TONE_SET then
|
||||
_send_mgmt(MGMT_TYPE.DIAG_TONE_GET, facility.get_alarm_tones())
|
||||
elseif pkt.type == MGMT_TYPE.DIAG_TONE_SET then
|
||||
local valid = false
|
||||
|
||||
-- attempt to set a tone state
|
||||
@ -144,7 +144,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
|
||||
-- try to set tone states, then send back if testing is allowed
|
||||
local allow_testing, test_tone_states = facility.diag_set_test_tone(pkt.data[1], pkt.data[2])
|
||||
_send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_SET, { allow_testing, test_tone_states })
|
||||
_send_mgmt(MGMT_TYPE.DIAG_TONE_SET, { allow_testing, test_tone_states })
|
||||
else
|
||||
log.debug(log_header .. "SCADA diag tone set packet data type mismatch")
|
||||
end
|
||||
@ -155,8 +155,8 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
log.debug(log_header .. "DIAG_TONE_SET is blocked without HMAC for security")
|
||||
end
|
||||
|
||||
if not valid then _send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_SET, { false }) end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_ALARM_SET then
|
||||
if not valid then _send_mgmt(MGMT_TYPE.DIAG_TONE_SET, { false }) end
|
||||
elseif pkt.type == MGMT_TYPE.DIAG_ALARM_SET then
|
||||
local valid = false
|
||||
|
||||
-- attempt to set an alarm state
|
||||
@ -167,7 +167,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
|
||||
-- try to set alarm states, then send back if testing is allowed
|
||||
local allow_testing, test_alarm_states = facility.diag_set_test_alarm(pkt.data[1], pkt.data[2])
|
||||
_send_mgmt(SCADA_MGMT_TYPE.DIAG_ALARM_SET, { allow_testing, test_alarm_states })
|
||||
_send_mgmt(MGMT_TYPE.DIAG_ALARM_SET, { allow_testing, test_alarm_states })
|
||||
else
|
||||
log.debug(log_header .. "SCADA diag alarm set packet data type mismatch")
|
||||
end
|
||||
@ -178,7 +178,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
log.debug(log_header .. "DIAG_ALARM_SET is blocked without HMAC for security")
|
||||
end
|
||||
|
||||
if not valid then _send_mgmt(SCADA_MGMT_TYPE.DIAG_ALARM_SET, { false }) end
|
||||
if not valid then _send_mgmt(MGMT_TYPE.DIAG_ALARM_SET, { false }) end
|
||||
else
|
||||
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
||||
end
|
||||
@ -204,7 +204,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println("connection to pocket diag session " .. id .. " closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -261,7 +261,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -22,7 +22,7 @@ local svrs_turbinev = require("supervisor.session.rtu.turbinev")
|
||||
local rtu = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
|
||||
local PERIODICS = {
|
||||
@ -223,7 +223,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -262,7 +262,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
-- handle management packet
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -281,17 +281,17 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.RTU_ADVERT then
|
||||
elseif pkt.type == MGMT_TYPE.RTU_ADVERT then
|
||||
-- RTU unit advertisement
|
||||
log.debug(log_header .. "received updated advertisement")
|
||||
self.advert = pkt.data
|
||||
|
||||
-- handle advertisement; this will re-create all unit sub-sessions
|
||||
_handle_advertisement()
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.RTU_DEV_REMOUNT then
|
||||
elseif pkt.type == MGMT_TYPE.RTU_DEV_REMOUNT then
|
||||
if pkt.length == 1 then
|
||||
local unit_id = pkt.data[1]
|
||||
if self.units[unit_id] ~= nil then
|
||||
@ -322,7 +322,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println(log_header .. "connection to RTU closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -387,7 +387,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
@ -395,7 +395,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
|
||||
periodics.alarm_tones = periodics.alarm_tones + elapsed
|
||||
if periodics.alarm_tones >= PERIODICS.ALARM_TONES then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.RTU_TONE_ALARM, { facility.get_alarm_tones() })
|
||||
_send_mgmt(MGMT_TYPE.RTU_TONE_ALARM, { facility.get_alarm_tones() })
|
||||
periodics.alarm_tones = 0
|
||||
end
|
||||
|
||||
|
@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local svsessions = require("supervisor.session.svsessions")
|
||||
|
||||
local SUPERVISOR_VERSION = "v1.0.2"
|
||||
local SUPERVISOR_VERSION = "v1.0.3"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -11,7 +11,7 @@ local supervisor = {}
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
-- supervisory controller communications
|
||||
---@nodiscard
|
||||
@ -58,7 +58,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
local s_pkt = comms.scada_packet()
|
||||
local m_pkt = comms.mgmt_packet()
|
||||
|
||||
m_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, { ack, data })
|
||||
m_pkt.make(MGMT_TYPE.ESTABLISH, { ack, data })
|
||||
s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||
|
||||
nic.transmit(packet.remote_channel(), svr_channel, s_pkt)
|
||||
@ -147,7 +147,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
@ -221,7 +221,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
@ -275,7 +275,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
@ -342,7 +342,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user