mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#74 coordinator comms and work on database
This commit is contained in:
7
coordinator/apisessions.lua
Normal file
7
coordinator/apisessions.lua
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
local apisessions = {}
|
||||||
|
|
||||||
|
---@param packet capi_frame
|
||||||
|
function apisessions.handle_packet(packet)
|
||||||
|
end
|
||||||
|
|
||||||
|
return apisessions
|
@ -1,13 +1,19 @@
|
|||||||
|
|
||||||
local comms = require("scada-common.comms")
|
local comms = require("scada-common.comms")
|
||||||
local log = require("scada-common.log")
|
local log = require("scada-common.log")
|
||||||
local ppm = require("scada-common.ppm")
|
local ppm = require("scada-common.ppm")
|
||||||
local util = require("scada-common.util")
|
local psil = require("scada-common.psil")
|
||||||
|
local util = require("scada-common.util")
|
||||||
|
|
||||||
|
local apisessions = require("coordinator.apisessions")
|
||||||
|
|
||||||
local dialog = require("coordinator.util.dialog")
|
local dialog = require("coordinator.util.dialog")
|
||||||
|
|
||||||
local coordinator = {}
|
local coordinator = {}
|
||||||
|
|
||||||
|
---@class coord_db
|
||||||
|
local db = {}
|
||||||
|
|
||||||
local print = util.print
|
local print = util.print
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local print_ts = util.print_ts
|
local print_ts = util.print_ts
|
||||||
@ -142,12 +148,43 @@ function coordinator.configure_monitors(num_units)
|
|||||||
return true, monitors
|
return true, monitors
|
||||||
end
|
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
|
-- coordinator communications
|
||||||
---@param conn_watchdog watchdog
|
---@param version string
|
||||||
function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_listen, api_listen, conn_watchdog)
|
---@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 = {
|
local self = {
|
||||||
seq_num = 0,
|
sv_seq_num = 0,
|
||||||
r_seq_num = nil,
|
sv_r_seq_num = nil,
|
||||||
modem = modem,
|
modem = modem,
|
||||||
connected = false
|
connected = false
|
||||||
}
|
}
|
||||||
@ -171,32 +208,26 @@ function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_liste
|
|||||||
-- open at construct time
|
-- open at construct time
|
||||||
_open_channels()
|
_open_channels()
|
||||||
|
|
||||||
-- send a coordinator packet
|
-- send a packet to the supervisor
|
||||||
---@param msg_type COORD_TYPES
|
---@param msg_type SCADA_MGMT_TYPES|COORD_TYPES
|
||||||
---@param msg string
|
---@param msg table
|
||||||
local function _send(msg_type, msg)
|
local function _send_sv(protocol, msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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)
|
if protocol == PROTOCOLS.SCADA_MGMT then
|
||||||
s_pkt.make(self.seq_num, PROTOCOLS.COORD_DATA, c_pkt.raw_sendable())
|
pkt = comms.mgmt_packet()
|
||||||
|
elseif protocol == PROTOCOLS.COORD_DATA then
|
||||||
|
pkt = comms.coord_packet()
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
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.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
|
|
||||||
|
|
||||||
-- 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())
|
|
||||||
|
|
||||||
self.modem.transmit(sv_port, sv_listen, s_pkt.raw_sendable())
|
|
||||||
self.seq_num = self.seq_num + 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- PUBLIC FUNCTIONS --
|
-- PUBLIC FUNCTIONS --
|
||||||
@ -254,46 +285,49 @@ function coordinator.coord_comms(version, num_reactors, modem, sv_port, sv_liste
|
|||||||
---@param packet mgmt_frame|coord_frame|capi_frame
|
---@param packet mgmt_frame|coord_frame|capi_frame
|
||||||
function public.handle_packet(packet)
|
function public.handle_packet(packet)
|
||||||
if packet ~= nil then
|
if packet ~= nil then
|
||||||
-- 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())
|
|
||||||
return
|
|
||||||
else
|
|
||||||
self.r_seq_num = packet.scada_frame.seq_num()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- feed watchdog on valid sequence number
|
|
||||||
conn_watchdog.feed()
|
|
||||||
|
|
||||||
local protocol = packet.scada_frame.protocol()
|
local protocol = packet.scada_frame.protocol()
|
||||||
|
|
||||||
-- handle packet
|
if protocol == PROTOCOLS.COORD_API then
|
||||||
if protocol == PROTOCOLS.COORD_DATA then
|
apisessions.handle_packet(packet)
|
||||||
if packet.type == COORD_TYPES.ESTABLISH then
|
|
||||||
elseif packet.type == COORD_TYPES.QUERY_UNIT then
|
|
||||||
elseif packet.type == COORD_TYPES.QUERY_FACILITY then
|
|
||||||
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)
|
|
||||||
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()
|
|
||||||
println_ts("server connection closed by remote host")
|
|
||||||
log.warning("server connection closed by remote host")
|
|
||||||
else
|
|
||||||
log.warning("received unknown SCADA_MGMT packet type " .. packet.type)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
-- should be unreachable assuming packet is from parse_packet()
|
-- check sequence number
|
||||||
log.error("illegal packet type " .. protocol, true)
|
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.sv_r_seq_num = packet.scada_frame.seq_num()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- feed watchdog on valid sequence number
|
||||||
|
sv_watchdog.feed()
|
||||||
|
|
||||||
|
-- handle packet
|
||||||
|
if protocol == PROTOCOLS.COORD_DATA then
|
||||||
|
if packet.type == COORD_TYPES.ESTABLISH then
|
||||||
|
elseif packet.type == COORD_TYPES.QUERY_UNIT then
|
||||||
|
elseif packet.type == COORD_TYPES.QUERY_FACILITY then
|
||||||
|
elseif packet.type == COORD_TYPES.COMMAND_UNIT then
|
||||||
|
elseif packet.type == COORD_TYPES.ALARM then
|
||||||
|
else
|
||||||
|
log.warning("received unknown COORD_DATA packet type " .. packet.type)
|
||||||
|
end
|
||||||
|
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
|
||||||
|
sv_watchdog.cancel()
|
||||||
|
println_ts("server connection closed by remote host")
|
||||||
|
log.warning("server connection closed by remote host")
|
||||||
|
else
|
||||||
|
log.warning("received unknown SCADA_MGMT packet type " .. packet.type)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- should be unreachable assuming packet is from parse_packet()
|
||||||
|
log.error("illegal packet type " .. protocol, true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,6 +57,11 @@ local COORD_TYPES = {
|
|||||||
ALARM = 4 -- alarm signaling
|
ALARM = 4 -- alarm signaling
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@alias CAPI_TYPES integer
|
||||||
|
local CAPI_TYPES = {
|
||||||
|
ESTABLISH = 0 -- initial greeting
|
||||||
|
}
|
||||||
|
|
||||||
---@alias RTU_UNIT_TYPES integer
|
---@alias RTU_UNIT_TYPES integer
|
||||||
local RTU_UNIT_TYPES = {
|
local RTU_UNIT_TYPES = {
|
||||||
REDSTONE = 0, -- redstone I/O
|
REDSTONE = 0, -- redstone I/O
|
||||||
@ -433,7 +438,6 @@ function comms.mgmt_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- SCADA coordinator packet
|
-- SCADA coordinator packet
|
||||||
-- @todo
|
|
||||||
function comms.coord_packet()
|
function comms.coord_packet()
|
||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
@ -456,7 +460,7 @@ function comms.coord_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- make a coordinator packet
|
-- make a coordinator packet
|
||||||
---@param packet_type any
|
---@param packet_type COORD_TYPES
|
||||||
---@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
|
||||||
@ -541,7 +545,7 @@ function comms.capi_packet()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- make a coordinator API packet
|
-- make a coordinator API packet
|
||||||
---@param packet_type any
|
---@param packet_type CAPI_TYPES
|
||||||
---@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
|
||||||
|
Reference in New Issue
Block a user