#74 coordinator comms and work on database

This commit is contained in:
Mikayla Fischler 2022-06-25 13:39:47 -04:00
parent cf6f0e3153
commit e54d5b3d85
3 changed files with 114 additions and 69 deletions

View File

@ -0,0 +1,7 @@
local apisessions = {}
---@param packet capi_frame
function apisessions.handle_packet(packet)
end
return apisessions

View File

@ -2,12 +2,18 @@
local comms = require("scada-common.comms")
local log = require("scada-common.log")
local ppm = require("scada-common.ppm")
local psil = require("scada-common.psil")
local util = require("scada-common.util")
local apisessions = require("coordinator.apisessions")
local dialog = require("coordinator.util.dialog")
local coordinator = {}
---@class coord_db
local db = {}
local print = util.print
local println = util.println
local print_ts = util.print_ts
@ -142,12 +148,43 @@ function coordinator.configure_monitors(num_units)
return true, monitors
end
-- initialize the coordinator database
---@param num_units integer number of units expected
function coordinator.init_database(num_units)
db.facility = {
num_units = num_units,
ps = psil.create()
}
db.units = {}
for i = 1, num_units do
table.insert(db.units, {
uint_id = i,
initialized = false,
reactor_ps = psil.create(),
reactor_data = {},
boiler_ps_tbl = {},
boiler_data_tbl = {},
turbine_ps_tbl = {},
turbine_data_tbl = {}
})
end
end
-- coordinator communications
---@param conn_watchdog watchdog
function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_listen, api_listen, conn_watchdog)
---@param version string
---@param modem table
---@param sv_port integer
---@param sv_listen integer
---@param api_listen integer
---@param sv_watchdog watchdog
function coordinator.coord_comms(version, modem, sv_port, sv_listen, api_listen, sv_watchdog)
local self = {
seq_num = 0,
r_seq_num = nil,
sv_seq_num = 0,
sv_r_seq_num = nil,
modem = modem,
connected = false
}
@ -171,32 +208,26 @@ function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_liste
-- open at construct time
_open_channels()
-- send a coordinator packet
---@param msg_type COORD_TYPES
---@param msg string
local function _send(msg_type, msg)
-- send a packet to the supervisor
---@param msg_type SCADA_MGMT_TYPES|COORD_TYPES
---@param msg table
local function _send_sv(protocol, msg_type, msg)
local s_pkt = comms.scada_packet()
local c_pkt = comms.coord_packet()
local pkt = nil ---@type mgmt_packet|coord_packet
c_pkt.make(msg_type, msg)
s_pkt.make(self.seq_num, PROTOCOLS.COORD_DATA, c_pkt.raw_sendable())
self.modem.transmit(sv_port, sv_listen, s_pkt.raw_sendable())
self.seq_num = self.seq_num + 1
if protocol == PROTOCOLS.SCADA_MGMT then
pkt = comms.mgmt_packet()
elseif protocol == PROTOCOLS.COORD_DATA then
pkt = comms.coord_packet()
else
return
end
-- send a SCADA management packet
---@param msg_type SCADA_MGMT_TYPES
---@param msg string
local function _send_mgmt(msg_type, msg)
local s_pkt = comms.scada_packet()
local m_pkt = comms.mgmt_packet()
m_pkt.make(msg_type, msg)
s_pkt.make(self.seq_num, PROTOCOLS.SCADA_MGMT, m_pkt.raw_sendable())
pkt.make(msg_type, msg)
s_pkt.make(self.sv_seq_num, protocol, pkt.raw_sendable())
self.modem.transmit(sv_port, sv_listen, s_pkt.raw_sendable())
self.seq_num = self.seq_num + 1
self.sv_seq_num = self.sv_seq_num + 1
end
-- PUBLIC FUNCTIONS --
@ -254,20 +285,23 @@ function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_liste
---@param packet mgmt_frame|coord_frame|capi_frame
function public.handle_packet(packet)
if packet ~= nil then
local protocol = packet.scada_frame.protocol()
if protocol == PROTOCOLS.COORD_API then
apisessions.handle_packet(packet)
else
-- check sequence number
if self.r_seq_num == nil then
self.r_seq_num = packet.scada_frame.seq_num()
elseif self.connected and self.r_seq_num >= packet.scada_frame.seq_num() then
log.warning("sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. packet.scada_frame.seq_num())
if self.sv_r_seq_num == nil then
self.sv_r_seq_num = packet.scada_frame.seq_num()
elseif self.connected and self.sv_r_seq_num >= packet.scada_frame.seq_num() then
log.warning("sequence out-of-order: last = " .. self.sv_r_seq_num .. ", new = " .. packet.scada_frame.seq_num())
return
else
self.r_seq_num = packet.scada_frame.seq_num()
self.sv_r_seq_num = packet.scada_frame.seq_num()
end
-- feed watchdog on valid sequence number
conn_watchdog.feed()
local protocol = packet.scada_frame.protocol()
sv_watchdog.feed()
-- handle packet
if protocol == PROTOCOLS.COORD_DATA then
@ -277,15 +311,14 @@ function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_liste
elseif packet.type == COORD_TYPES.COMMAND_UNIT then
elseif packet.type == COORD_TYPES.ALARM then
else
log.warning("received unknown coordinator data packet type " .. packet.type)
log.warning("received unknown COORD_DATA packet type " .. packet.type)
end
elseif protocol == PROTOCOLS.COORD_API then
elseif protocol == PROTOCOLS.SCADA_MGMT then
if packet.type == SCADA_MGMT_TYPES.KEEP_ALIVE then
-- keep alive response received
elseif packet.type == SCADA_MGMT_TYPES.CLOSE then
-- handle session close
conn_watchdog.cancel()
sv_watchdog.cancel()
println_ts("server connection closed by remote host")
log.warning("server connection closed by remote host")
else
@ -297,6 +330,7 @@ function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_liste
end
end
end
end
return public
end

View File

@ -57,6 +57,11 @@ local COORD_TYPES = {
ALARM = 4 -- alarm signaling
}
---@alias CAPI_TYPES integer
local CAPI_TYPES = {
ESTABLISH = 0 -- initial greeting
}
---@alias RTU_UNIT_TYPES integer
local RTU_UNIT_TYPES = {
REDSTONE = 0, -- redstone I/O
@ -433,7 +438,6 @@ function comms.mgmt_packet()
end
-- SCADA coordinator packet
-- @todo
function comms.coord_packet()
local self = {
frame = nil,
@ -456,7 +460,7 @@ function comms.coord_packet()
end
-- make a coordinator packet
---@param packet_type any
---@param packet_type COORD_TYPES
---@param data table
function public.make(packet_type, data)
if type(data) == "table" then
@ -541,7 +545,7 @@ function comms.capi_packet()
end
-- make a coordinator API packet
---@param packet_type any
---@param packet_type CAPI_TYPES
---@param data table
function public.make(packet_type, data)
if type(data) == "table" then