2022-08-28 16:12:30 +00:00
|
|
|
local log = require("scada-common.log")
|
|
|
|
local mqueue = require("scada-common.mqueue")
|
|
|
|
local util = require("scada-common.util")
|
|
|
|
|
2022-10-03 01:17:13 +00:00
|
|
|
local svqtypes = require("supervisor.session.svqtypes")
|
2022-08-28 16:12:30 +00:00
|
|
|
local unit = require("supervisor.session.unit")
|
2022-05-04 17:37:01 +00:00
|
|
|
|
2022-05-11 15:31:02 +00:00
|
|
|
local coordinator = require("supervisor.session.coordinator")
|
2022-05-31 19:36:17 +00:00
|
|
|
local plc = require("supervisor.session.plc")
|
|
|
|
local rtu = require("supervisor.session.rtu")
|
2022-04-22 15:07:59 +00:00
|
|
|
|
|
|
|
-- Supervisor Sessions Handler
|
|
|
|
|
2022-10-03 01:17:13 +00:00
|
|
|
local SV_Q_CMDS = svqtypes.SV_Q_CMDS
|
2022-10-06 17:54:52 +00:00
|
|
|
local SV_Q_DATA = svqtypes.SV_Q_DATA
|
|
|
|
|
|
|
|
local PLC_S_CMDS = plc.PLC_S_CMDS
|
|
|
|
local PLC_S_DATA = plc.PLC_S_DATA
|
2022-10-03 01:17:13 +00:00
|
|
|
local CRD_S_CMDS = coordinator.CRD_S_CMDS
|
|
|
|
|
2022-05-04 17:37:01 +00:00
|
|
|
local svsessions = {}
|
|
|
|
|
|
|
|
local SESSION_TYPE = {
|
2022-04-22 15:07:59 +00:00
|
|
|
RTU_SESSION = 0,
|
|
|
|
PLC_SESSION = 1,
|
|
|
|
COORD_SESSION = 2
|
|
|
|
}
|
|
|
|
|
2022-05-04 17:37:01 +00:00
|
|
|
svsessions.SESSION_TYPE = SESSION_TYPE
|
|
|
|
|
2022-04-22 15:07:59 +00:00
|
|
|
local self = {
|
2022-04-24 17:22:45 +00:00
|
|
|
modem = nil,
|
2022-04-22 15:07:59 +00:00
|
|
|
num_reactors = 0,
|
2022-08-28 16:12:30 +00:00
|
|
|
facility_units = {},
|
2022-04-22 15:07:59 +00:00
|
|
|
rtu_sessions = {},
|
|
|
|
plc_sessions = {},
|
|
|
|
coord_sessions = {},
|
|
|
|
next_rtu_id = 0,
|
|
|
|
next_plc_id = 0,
|
|
|
|
next_coord_id = 0
|
|
|
|
}
|
|
|
|
|
2022-05-04 17:37:01 +00:00
|
|
|
-- PRIVATE FUNCTIONS --
|
|
|
|
|
2022-10-06 17:54:52 +00:00
|
|
|
-- handle a session output queue
|
|
|
|
---@param session plc_session_struct|rtu_session_struct|coord_session_struct
|
|
|
|
local function _sv_handle_outq(session)
|
|
|
|
-- record handler start time
|
|
|
|
local handle_start = util.time()
|
|
|
|
|
|
|
|
-- process output queue
|
|
|
|
while session.out_queue.ready() do
|
|
|
|
-- get a new message to process
|
|
|
|
local msg = session.out_queue.pop()
|
|
|
|
|
|
|
|
if msg ~= nil then
|
|
|
|
if msg.qtype == mqueue.TYPE.PACKET then
|
|
|
|
-- handle a packet to be sent
|
|
|
|
self.modem.transmit(session.r_port, session.l_port, msg.message.raw_sendable())
|
|
|
|
elseif msg.qtype == mqueue.TYPE.COMMAND then
|
|
|
|
-- handle instruction/notification
|
|
|
|
local cmd = msg.message
|
|
|
|
if cmd == SV_Q_CMDS.BUILD_CHANGED then
|
|
|
|
-- notify coordinator(s) that a build has changed
|
|
|
|
for j = 1, #self.coord_sessions do
|
|
|
|
local s = self.coord_sessions[j] ---@type coord_session_struct
|
|
|
|
s.in_queue.push_command(CRD_S_CMDS.RESEND_BUILDS)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif msg.qtype == mqueue.TYPE.DATA then
|
|
|
|
-- instruction/notification with body
|
|
|
|
local cmd = msg.message ---@type queue_data
|
|
|
|
local plc_s = nil
|
|
|
|
|
|
|
|
if type(cmd.val) == "table" then
|
|
|
|
plc_s = svsessions.get_reactor_session(cmd.val[1])
|
|
|
|
elseif type(cmd.val) == "number" then
|
|
|
|
plc_s = svsessions.get_reactor_session(cmd.val)
|
|
|
|
end
|
|
|
|
|
|
|
|
if plc_s ~= nil then
|
|
|
|
if cmd.key == SV_Q_DATA.START then
|
|
|
|
plc_s.in_queue.push_command(PLC_S_CMDS.ENABLE)
|
|
|
|
elseif cmd.key == SV_Q_DATA.SCRAM then
|
|
|
|
plc_s.in_queue.push_command(PLC_S_CMDS.SCRAM)
|
|
|
|
elseif cmd.key == SV_Q_DATA.RESET_RPS then
|
|
|
|
plc_s.in_queue.push_command(PLC_S_CMDS.RPS_RESET)
|
|
|
|
elseif cmd.key == SV_Q_DATA.SET_BURN and type(cmd.val) == "table" and #cmd.val == 2 then
|
|
|
|
plc_s.in_queue.push_data(PLC_S_DATA.BURN_RATE, cmd.val[2])
|
|
|
|
elseif cmd.key == SV_Q_DATA.SET_WASTE and type(cmd.val) == "table" and #cmd.val == 2 then
|
|
|
|
---@todo set waste
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- max 100ms spent processing queue
|
|
|
|
if util.time() - handle_start > 100 then
|
|
|
|
log.warning("supervisor out queue handler exceeded 100ms queue process limit")
|
|
|
|
log.warning(util.c("offending session: port ", session.r_port, " type '", session.s_type, "'"))
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-05-04 17:37:01 +00:00
|
|
|
-- iterate all the given sessions
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param sessions table
|
2022-05-04 17:37:01 +00:00
|
|
|
local function _iterate(sessions)
|
|
|
|
for i = 1, #sessions do
|
2022-10-03 01:17:13 +00:00
|
|
|
local session = sessions[i] ---@type plc_session_struct|rtu_session_struct|coord_session_struct
|
2022-10-06 17:54:52 +00:00
|
|
|
|
2022-10-03 01:17:13 +00:00
|
|
|
if session.open and session.instance.iterate() then
|
2022-10-06 17:54:52 +00:00
|
|
|
_sv_handle_outq(session)
|
2022-10-03 01:17:13 +00:00
|
|
|
else
|
|
|
|
session.open = false
|
2022-05-04 17:37:01 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- cleanly close a session
|
2022-05-13 13:45:11 +00:00
|
|
|
---@param session plc_session_struct|rtu_session_struct
|
2022-05-04 17:37:01 +00:00
|
|
|
local function _shutdown(session)
|
|
|
|
session.open = false
|
|
|
|
session.instance.close()
|
|
|
|
|
|
|
|
-- send packets in out queue (namely the close packet)
|
|
|
|
while session.out_queue.ready() do
|
|
|
|
local msg = session.out_queue.pop()
|
2022-05-11 16:31:19 +00:00
|
|
|
if msg ~= nil and msg.qtype == mqueue.TYPE.PACKET then
|
2022-05-04 17:37:01 +00:00
|
|
|
self.modem.transmit(session.r_port, session.l_port, msg.message.raw_sendable())
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
log.debug("closed session " .. session.instance.get_id() .. " on remote port " .. session.r_port)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- close connections
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param sessions table
|
2022-05-04 17:37:01 +00:00
|
|
|
local function _close(sessions)
|
|
|
|
for i = 1, #sessions do
|
2022-05-11 16:31:19 +00:00
|
|
|
local session = sessions[i] ---@type plc_session_struct
|
2022-05-04 17:37:01 +00:00
|
|
|
if session.open then
|
|
|
|
_shutdown(session)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- check if a watchdog timer event matches that of one of the provided sessions
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param sessions table
|
|
|
|
---@param timer_event number
|
2022-05-04 17:37:01 +00:00
|
|
|
local function _check_watchdogs(sessions, timer_event)
|
|
|
|
for i = 1, #sessions do
|
2022-05-11 16:31:19 +00:00
|
|
|
local session = sessions[i] ---@type plc_session_struct
|
2022-05-04 17:37:01 +00:00
|
|
|
if session.open then
|
|
|
|
local triggered = session.instance.check_wd(timer_event)
|
|
|
|
if triggered then
|
|
|
|
log.debug("watchdog closing session " .. session.instance.get_id() .. " on remote port " .. session.r_port .. "...")
|
|
|
|
_shutdown(session)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- delete any closed sessions
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param sessions table
|
2022-05-04 17:37:01 +00:00
|
|
|
local function _free_closed(sessions)
|
2022-05-16 21:11:46 +00:00
|
|
|
local f = function (session) return session.open end
|
2022-10-03 01:17:13 +00:00
|
|
|
|
|
|
|
local on_delete = function (session)
|
|
|
|
log.debug("free'ing closed session " .. session.instance.get_id() .. " on remote port " .. session.r_port)
|
|
|
|
end
|
2022-05-16 21:11:46 +00:00
|
|
|
|
|
|
|
util.filter_table(sessions, f, on_delete)
|
2022-05-04 17:37:01 +00:00
|
|
|
end
|
|
|
|
|
2022-05-21 16:30:14 +00:00
|
|
|
-- find a session by remote port
|
|
|
|
---@param list table
|
|
|
|
---@param port integer
|
|
|
|
---@return plc_session_struct|rtu_session_struct|nil
|
|
|
|
local function _find_session(list, port)
|
|
|
|
for i = 1, #list do
|
|
|
|
if list[i].r_port == port then return list[i] end
|
|
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
2022-05-04 17:37:01 +00:00
|
|
|
-- PUBLIC FUNCTIONS --
|
|
|
|
|
2022-08-28 16:12:30 +00:00
|
|
|
-- initialize svsessions
|
|
|
|
---@param modem table
|
|
|
|
---@param num_reactors integer
|
|
|
|
---@param cooling_conf table
|
|
|
|
function svsessions.init(modem, num_reactors, cooling_conf)
|
|
|
|
self.modem = modem
|
|
|
|
self.num_reactors = num_reactors
|
|
|
|
self.facility_units = {}
|
|
|
|
|
|
|
|
for i = 1, self.num_reactors do
|
|
|
|
table.insert(self.facility_units, unit.new(i, cooling_conf[i].BOILERS, cooling_conf[i].TURBINES))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- re-link the modem
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param modem table
|
2022-08-28 16:12:30 +00:00
|
|
|
function svsessions.relink_modem(modem)
|
2022-04-23 16:12:33 +00:00
|
|
|
self.modem = modem
|
|
|
|
end
|
|
|
|
|
2022-05-13 15:38:56 +00:00
|
|
|
-- find an RTU session by the remote port
|
|
|
|
---@param remote_port integer
|
|
|
|
---@return rtu_session_struct|nil
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.find_rtu_session(remote_port)
|
2022-05-13 15:38:56 +00:00
|
|
|
-- check RTU sessions
|
2022-09-21 19:53:51 +00:00
|
|
|
---@diagnostic disable-next-line: return-type-mismatch
|
2022-05-21 16:30:14 +00:00
|
|
|
return _find_session(self.rtu_sessions, remote_port)
|
2022-05-13 15:38:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- find a PLC session by the remote port
|
|
|
|
---@param remote_port integer
|
|
|
|
---@return plc_session_struct|nil
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.find_plc_session(remote_port)
|
2022-05-13 15:38:56 +00:00
|
|
|
-- check PLC sessions
|
2022-09-21 19:53:51 +00:00
|
|
|
---@diagnostic disable-next-line: return-type-mismatch
|
2022-05-21 16:30:14 +00:00
|
|
|
return _find_session(self.plc_sessions, remote_port)
|
2022-05-13 15:38:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- find a PLC/RTU session by the remote port
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param remote_port integer
|
2022-05-13 13:45:11 +00:00
|
|
|
---@return plc_session_struct|rtu_session_struct|nil
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.find_device_session(remote_port)
|
2022-05-02 15:42:24 +00:00
|
|
|
-- check RTU sessions
|
2022-05-21 16:30:14 +00:00
|
|
|
local s = _find_session(self.rtu_sessions, remote_port)
|
2022-04-22 15:07:59 +00:00
|
|
|
|
2022-05-02 15:42:24 +00:00
|
|
|
-- check PLC sessions
|
2022-05-21 16:30:14 +00:00
|
|
|
if s == nil then s = _find_session(self.plc_sessions, remote_port) end
|
2022-05-02 15:42:24 +00:00
|
|
|
|
2022-05-21 16:30:14 +00:00
|
|
|
return s
|
2022-05-13 15:38:56 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- find a coordinator session by the remote port
|
|
|
|
---@param remote_port integer
|
|
|
|
---@return nil
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.find_coord_session(remote_port)
|
2022-05-02 15:42:24 +00:00
|
|
|
-- check coordinator sessions
|
2022-09-21 19:53:51 +00:00
|
|
|
---@diagnostic disable-next-line: return-type-mismatch
|
2022-05-21 16:30:14 +00:00
|
|
|
return _find_session(self.coord_sessions, remote_port)
|
2022-04-22 15:07:59 +00:00
|
|
|
end
|
|
|
|
|
2022-05-02 15:42:24 +00:00
|
|
|
-- get a session by reactor ID
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param reactor integer
|
2022-05-13 15:38:56 +00:00
|
|
|
---@return plc_session_struct|nil session
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.get_reactor_session(reactor)
|
2022-04-22 15:07:59 +00:00
|
|
|
local session = nil
|
|
|
|
|
|
|
|
for i = 1, #self.plc_sessions do
|
|
|
|
if self.plc_sessions[i].reactor == reactor then
|
|
|
|
session = self.plc_sessions[i]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return session
|
|
|
|
end
|
|
|
|
|
2022-05-02 15:42:24 +00:00
|
|
|
-- establish a new PLC session
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param local_port integer
|
|
|
|
---@param remote_port integer
|
|
|
|
---@param for_reactor integer
|
2022-05-19 14:21:04 +00:00
|
|
|
---@param version string
|
2022-05-11 16:31:19 +00:00
|
|
|
---@return integer|false session_id
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.establish_plc_session(local_port, remote_port, for_reactor, version)
|
2022-10-06 17:54:52 +00:00
|
|
|
if svsessions.get_reactor_session(for_reactor) == nil and for_reactor >= 1 and for_reactor <= self.num_reactors then
|
2022-05-11 16:31:19 +00:00
|
|
|
---@class plc_session_struct
|
2022-04-22 15:07:59 +00:00
|
|
|
local plc_s = {
|
2022-10-06 17:54:52 +00:00
|
|
|
s_type = "plc",
|
2022-04-22 15:07:59 +00:00
|
|
|
open = true,
|
|
|
|
reactor = for_reactor,
|
2022-05-19 14:21:04 +00:00
|
|
|
version = version,
|
2022-04-23 16:12:33 +00:00
|
|
|
l_port = local_port,
|
|
|
|
r_port = remote_port,
|
2022-04-22 15:07:59 +00:00
|
|
|
in_queue = mqueue.new(),
|
|
|
|
out_queue = mqueue.new(),
|
|
|
|
instance = nil
|
|
|
|
}
|
|
|
|
|
2022-04-26 01:00:50 +00:00
|
|
|
plc_s.instance = plc.new_session(self.next_plc_id, for_reactor, plc_s.in_queue, plc_s.out_queue)
|
2022-04-22 15:07:59 +00:00
|
|
|
table.insert(self.plc_sessions, plc_s)
|
2022-04-26 01:00:50 +00:00
|
|
|
|
2022-08-28 16:12:30 +00:00
|
|
|
self.facility_units[for_reactor].link_plc_session(plc_s)
|
|
|
|
|
2022-05-04 17:37:01 +00:00
|
|
|
log.debug("established new PLC session to " .. remote_port .. " with ID " .. self.next_plc_id)
|
2022-04-26 01:00:50 +00:00
|
|
|
|
|
|
|
self.next_plc_id = self.next_plc_id + 1
|
2022-04-22 15:07:59 +00:00
|
|
|
|
|
|
|
-- success
|
|
|
|
return plc_s.instance.get_id()
|
|
|
|
else
|
2022-10-06 17:54:52 +00:00
|
|
|
-- reactor already assigned to a PLC or ID out of range
|
2022-04-22 15:07:59 +00:00
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-05-13 13:45:11 +00:00
|
|
|
-- establish a new RTU session
|
|
|
|
---@param local_port integer
|
|
|
|
---@param remote_port integer
|
|
|
|
---@param advertisement table
|
|
|
|
---@return integer session_id
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.establish_rtu_session(local_port, remote_port, advertisement)
|
2022-05-19 14:21:04 +00:00
|
|
|
-- pull version from advertisement
|
|
|
|
local version = table.remove(advertisement, 1)
|
|
|
|
|
2022-05-13 13:45:11 +00:00
|
|
|
---@class rtu_session_struct
|
|
|
|
local rtu_s = {
|
2022-10-06 17:54:52 +00:00
|
|
|
s_type = "rtu",
|
2022-05-13 13:45:11 +00:00
|
|
|
open = true,
|
2022-05-19 14:21:04 +00:00
|
|
|
version = version,
|
2022-05-13 13:45:11 +00:00
|
|
|
l_port = local_port,
|
|
|
|
r_port = remote_port,
|
|
|
|
in_queue = mqueue.new(),
|
|
|
|
out_queue = mqueue.new(),
|
|
|
|
instance = nil
|
|
|
|
}
|
|
|
|
|
2022-08-28 16:12:30 +00:00
|
|
|
rtu_s.instance = rtu.new_session(self.next_rtu_id, rtu_s.in_queue, rtu_s.out_queue, advertisement, self.facility_units)
|
2022-05-13 13:45:11 +00:00
|
|
|
table.insert(self.rtu_sessions, rtu_s)
|
|
|
|
|
|
|
|
log.debug("established new RTU session to " .. remote_port .. " with ID " .. self.next_rtu_id)
|
|
|
|
|
|
|
|
self.next_rtu_id = self.next_rtu_id + 1
|
|
|
|
|
|
|
|
-- success
|
|
|
|
return rtu_s.instance.get_id()
|
|
|
|
end
|
|
|
|
|
2022-07-07 04:34:42 +00:00
|
|
|
-- establish a new coordinator session
|
|
|
|
---@param local_port integer
|
|
|
|
---@param remote_port integer
|
|
|
|
---@param version string
|
|
|
|
---@return integer|false session_id
|
|
|
|
function svsessions.establish_coord_session(local_port, remote_port, version)
|
|
|
|
---@class coord_session_struct
|
|
|
|
local coord_s = {
|
2022-10-06 17:54:52 +00:00
|
|
|
s_type = "crd",
|
2022-07-07 04:34:42 +00:00
|
|
|
open = true,
|
|
|
|
version = version,
|
|
|
|
l_port = local_port,
|
|
|
|
r_port = remote_port,
|
|
|
|
in_queue = mqueue.new(),
|
|
|
|
out_queue = mqueue.new(),
|
|
|
|
instance = nil
|
|
|
|
}
|
|
|
|
|
2022-08-28 16:12:30 +00:00
|
|
|
coord_s.instance = coordinator.new_session(self.next_coord_id, coord_s.in_queue, coord_s.out_queue, self.facility_units)
|
2022-07-07 04:34:42 +00:00
|
|
|
table.insert(self.coord_sessions, coord_s)
|
|
|
|
|
|
|
|
log.debug("established new coordinator session to " .. remote_port .. " with ID " .. self.next_coord_id)
|
|
|
|
|
|
|
|
self.next_coord_id = self.next_coord_id + 1
|
|
|
|
|
|
|
|
-- success
|
|
|
|
return coord_s.instance.get_id()
|
|
|
|
end
|
|
|
|
|
2022-05-02 15:42:24 +00:00
|
|
|
-- attempt to identify which session's watchdog timer fired
|
2022-05-11 16:31:19 +00:00
|
|
|
---@param timer_event number
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.check_all_watchdogs(timer_event)
|
2022-04-23 16:12:33 +00:00
|
|
|
-- check RTU session watchdogs
|
|
|
|
_check_watchdogs(self.rtu_sessions, timer_event)
|
|
|
|
|
|
|
|
-- check PLC session watchdogs
|
|
|
|
_check_watchdogs(self.plc_sessions, timer_event)
|
|
|
|
|
|
|
|
-- check coordinator session watchdogs
|
|
|
|
_check_watchdogs(self.coord_sessions, timer_event)
|
|
|
|
end
|
|
|
|
|
2022-05-02 15:42:24 +00:00
|
|
|
-- iterate all sessions
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.iterate_all()
|
2022-04-22 15:07:59 +00:00
|
|
|
-- iterate RTU sessions
|
|
|
|
_iterate(self.rtu_sessions)
|
|
|
|
|
|
|
|
-- iterate PLC sessions
|
|
|
|
_iterate(self.plc_sessions)
|
|
|
|
|
|
|
|
-- iterate coordinator sessions
|
|
|
|
_iterate(self.coord_sessions)
|
2022-08-28 16:12:30 +00:00
|
|
|
|
|
|
|
-- iterate units
|
|
|
|
for i = 1, #self.facility_units do
|
|
|
|
local u = self.facility_units[i] ---@type reactor_unit
|
|
|
|
u.update()
|
|
|
|
end
|
2022-04-22 15:07:59 +00:00
|
|
|
end
|
|
|
|
|
2022-05-02 15:42:24 +00:00
|
|
|
-- delete all closed sessions
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.free_all_closed()
|
2022-04-22 15:07:59 +00:00
|
|
|
-- free closed RTU sessions
|
|
|
|
_free_closed(self.rtu_sessions)
|
|
|
|
|
|
|
|
-- free closed PLC sessions
|
|
|
|
_free_closed(self.plc_sessions)
|
|
|
|
|
|
|
|
-- free closed coordinator sessions
|
|
|
|
_free_closed(self.coord_sessions)
|
|
|
|
end
|
2022-05-02 15:42:24 +00:00
|
|
|
|
|
|
|
-- close all open connections
|
2022-05-31 19:36:17 +00:00
|
|
|
function svsessions.close_all()
|
2022-05-02 15:42:24 +00:00
|
|
|
-- close sessions
|
|
|
|
_close(self.rtu_sessions)
|
|
|
|
_close(self.plc_sessions)
|
|
|
|
_close(self.coord_sessions)
|
|
|
|
|
|
|
|
-- free sessions
|
2022-05-04 17:37:01 +00:00
|
|
|
svsessions.free_all_closed()
|
2022-05-02 15:42:24 +00:00
|
|
|
end
|
2022-05-04 17:37:01 +00:00
|
|
|
|
|
|
|
return svsessions
|