#130 facility data object, some code cleanup, comms protocol changed from 1.0.1 to 1.1.0
This commit is contained in:
@@ -10,7 +10,7 @@ local coordinator = {}
|
||||
local PROTOCOLS = comms.PROTOCOLS
|
||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
||||
local SCADA_CRDN_TYPES = comms.SCADA_CRDN_TYPES
|
||||
local CRDN_COMMANDS = comms.CRDN_COMMANDS
|
||||
local UNIT_COMMANDS = comms.UNIT_COMMANDS
|
||||
|
||||
local SV_Q_CMDS = svqtypes.SV_Q_CMDS
|
||||
local SV_Q_DATA = svqtypes.SV_Q_DATA
|
||||
@@ -44,15 +44,14 @@ local PERIODICS = {
|
||||
---@param id integer
|
||||
---@param in_queue mqueue
|
||||
---@param out_queue mqueue
|
||||
---@param facility_units table
|
||||
function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
---@param facility facility
|
||||
---@param units table
|
||||
function coordinator.new_session(id, in_queue, out_queue, facility, units)
|
||||
local log_header = "crdn_session(" .. id .. "): "
|
||||
|
||||
local self = {
|
||||
id = id,
|
||||
in_q = in_queue,
|
||||
out_q = out_queue,
|
||||
units = facility_units,
|
||||
-- connection properties
|
||||
seq_num = 0,
|
||||
r_seq_num = nil,
|
||||
@@ -67,11 +66,13 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
},
|
||||
-- when to next retry one of these messages
|
||||
retry_times = {
|
||||
builds_packet = 0
|
||||
f_builds_packet = 0,
|
||||
u_builds_packet = 0
|
||||
},
|
||||
-- message acknowledgements
|
||||
acks = {
|
||||
builds = false
|
||||
fac_builds = false,
|
||||
unit_builds = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,26 +110,41 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
self.seq_num = self.seq_num + 1
|
||||
end
|
||||
|
||||
-- send facility builds
|
||||
local function _send_fac_builds()
|
||||
self.acks.fac_builds = false
|
||||
_send(SCADA_CRDN_TYPES.FAC_BUILDS, facility.get_build())
|
||||
end
|
||||
|
||||
-- send unit builds
|
||||
local function _send_builds()
|
||||
self.acks.builds = false
|
||||
local function _send_unit_builds()
|
||||
self.acks.unit_builds = false
|
||||
|
||||
local builds = {}
|
||||
|
||||
for i = 1, #self.units do
|
||||
local unit = self.units[i] ---@type reactor_unit
|
||||
for i = 1, #units do
|
||||
local unit = units[i] ---@type reactor_unit
|
||||
builds[unit.get_id()] = unit.get_build()
|
||||
end
|
||||
|
||||
_send(SCADA_CRDN_TYPES.STRUCT_BUILDS, builds)
|
||||
_send(SCADA_CRDN_TYPES.UNIT_BUILDS, builds)
|
||||
end
|
||||
|
||||
-- send facility status
|
||||
local function _send_fac_status()
|
||||
local status = {
|
||||
facility.get_rtu_statuses()
|
||||
}
|
||||
|
||||
_send(SCADA_CRDN_TYPES.FAC_STATUS, status)
|
||||
end
|
||||
|
||||
-- send unit statuses
|
||||
local function _send_status()
|
||||
local function _send_unit_statuses()
|
||||
local status = {}
|
||||
|
||||
for i = 1, #self.units do
|
||||
local unit = self.units[i] ---@type reactor_unit
|
||||
for i = 1, #units do
|
||||
local unit = units[i] ---@type reactor_unit
|
||||
status[unit.get_id()] = {
|
||||
unit.get_reactor_status(),
|
||||
unit.get_rtu_statuses(),
|
||||
@@ -183,10 +199,13 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOLS.SCADA_CRDN then
|
||||
if pkt.type == SCADA_CRDN_TYPES.STRUCT_BUILDS then
|
||||
if pkt.type == SCADA_CRDN_TYPES.FAC_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPES.COMMAND_UNIT then
|
||||
self.acks.fac_builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPES.UNIT_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.unit_builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPES.UNIT_CMD then
|
||||
if pkt.length >= 2 then
|
||||
-- get command and unit id
|
||||
local cmd = pkt.data[1]
|
||||
@@ -196,37 +215,37 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
local data = { uid, pkt.data[3] }
|
||||
|
||||
-- continue if valid unit id
|
||||
if util.is_int(uid) and uid > 0 and uid <= #self.units then
|
||||
local unit = self.units[uid] ---@type reactor_unit
|
||||
if util.is_int(uid) and uid > 0 and uid <= #units then
|
||||
local unit = units[uid] ---@type reactor_unit
|
||||
|
||||
if cmd == CRDN_COMMANDS.START then
|
||||
if cmd == UNIT_COMMANDS.START then
|
||||
self.out_q.push_data(SV_Q_DATA.START, data)
|
||||
elseif cmd == CRDN_COMMANDS.SCRAM then
|
||||
elseif cmd == UNIT_COMMANDS.SCRAM then
|
||||
self.out_q.push_data(SV_Q_DATA.SCRAM, data)
|
||||
elseif cmd == CRDN_COMMANDS.RESET_RPS then
|
||||
elseif cmd == UNIT_COMMANDS.RESET_RPS then
|
||||
self.out_q.push_data(SV_Q_DATA.RESET_RPS, data)
|
||||
elseif cmd == CRDN_COMMANDS.SET_BURN then
|
||||
elseif cmd == UNIT_COMMANDS.SET_BURN then
|
||||
if pkt.length == 3 then
|
||||
self.out_q.push_data(SV_Q_DATA.SET_BURN, data)
|
||||
else
|
||||
log.debug(log_header .. "CRDN command unit burn rate missing option")
|
||||
end
|
||||
elseif cmd == CRDN_COMMANDS.SET_WASTE then
|
||||
elseif cmd == UNIT_COMMANDS.SET_WASTE then
|
||||
if pkt.length == 3 then
|
||||
unit.set_waste(pkt.data[3])
|
||||
else
|
||||
log.debug(log_header .. "CRDN command unit set waste missing option")
|
||||
end
|
||||
elseif cmd == CRDN_COMMANDS.ACK_ALL_ALARMS then
|
||||
elseif cmd == UNIT_COMMANDS.ACK_ALL_ALARMS then
|
||||
unit.ack_all()
|
||||
_send(SCADA_CRDN_TYPES.COMMAND_UNIT, { cmd, uid, true })
|
||||
elseif cmd == CRDN_COMMANDS.ACK_ALARM then
|
||||
_send(SCADA_CRDN_TYPES.UNIT_CMD, { cmd, uid, true })
|
||||
elseif cmd == UNIT_COMMANDS.ACK_ALARM then
|
||||
if pkt.length == 3 then
|
||||
unit.ack_alarm(pkt.data[3])
|
||||
else
|
||||
log.debug(log_header .. "CRDN command unit ack alarm missing id")
|
||||
end
|
||||
elseif cmd == CRDN_COMMANDS.RESET_ALARM then
|
||||
elseif cmd == UNIT_COMMANDS.RESET_ALARM then
|
||||
if pkt.length == 3 then
|
||||
unit.reset_alarm(pkt.data[3])
|
||||
else
|
||||
@@ -251,7 +270,7 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
local public = {}
|
||||
|
||||
-- get the session ID
|
||||
function public.get_id() return self.id end
|
||||
function public.get_id() return id end
|
||||
|
||||
-- check if a timer matches this session's watchdog
|
||||
function public.check_wd(timer)
|
||||
@@ -262,7 +281,7 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPES.CLOSE, {})
|
||||
println("connection to coordinator " .. self.id .. " closed by server")
|
||||
println("connection to coordinator " .. id .. " closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
|
||||
@@ -289,9 +308,9 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
local cmd = message.message
|
||||
if cmd == CRD_S_CMDS.RESEND_BUILDS then
|
||||
-- re-send builds
|
||||
self.acks.builds = false
|
||||
self.retry_times.builds_packet = util.time() + RETRY_PERIOD
|
||||
_send_builds()
|
||||
_send_fac_builds()
|
||||
_send_unit_builds()
|
||||
end
|
||||
elseif message.qtype == mqueue.TYPE.DATA then
|
||||
-- instruction with body
|
||||
@@ -299,7 +318,7 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
|
||||
if cmd.key == CRD_S_DATA.CMD_ACK then
|
||||
local ack = cmd.val ---@type coord_ack
|
||||
_send(SCADA_CRDN_TYPES.COMMAND_UNIT, { ack.cmd, ack.unit, ack.ack })
|
||||
_send(SCADA_CRDN_TYPES.UNIT_CMD, { ack.cmd, ack.unit, ack.ack })
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -313,7 +332,7 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
|
||||
-- exit if connection was closed
|
||||
if not self.connected then
|
||||
println("connection to coordinator " .. self.id .. " closed by remote host")
|
||||
println("connection to coordinator " .. id .. " closed by remote host")
|
||||
log.info(log_header .. "session closed by remote host")
|
||||
return self.connected
|
||||
end
|
||||
@@ -334,11 +353,12 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
-- unit statuses to coordinator
|
||||
-- statuses to coordinator
|
||||
|
||||
periodics.status_packet = periodics.status_packet + elapsed
|
||||
if periodics.status_packet >= PERIODICS.STATUS then
|
||||
_send_status()
|
||||
_send_fac_status()
|
||||
_send_unit_statuses()
|
||||
periodics.status_packet = 0
|
||||
end
|
||||
|
||||
@@ -350,12 +370,19 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
|
||||
local rtimes = self.retry_times
|
||||
|
||||
-- builds packet retry
|
||||
-- builds packet retries
|
||||
|
||||
if not self.acks.builds then
|
||||
if rtimes.builds_packet - util.time() <= 0 then
|
||||
_send_builds()
|
||||
rtimes.builds_packet = util.time() + RETRY_PERIOD
|
||||
if not self.acks.fac_builds then
|
||||
if rtimes.f_builds_packet - util.time() <= 0 then
|
||||
_send_fac_builds()
|
||||
rtimes.f_builds_packet = util.time() + RETRY_PERIOD
|
||||
end
|
||||
end
|
||||
|
||||
if not self.acks.unit_builds then
|
||||
if rtimes.u_builds_packet - util.time() <= 0 then
|
||||
_send_unit_builds()
|
||||
rtimes.u_builds_packet = util.time() + RETRY_PERIOD
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
100
supervisor/session/facility.lua
Normal file
100
supervisor/session/facility.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
local log = require("scada-common.log")
|
||||
local rsio = require("scada-common.rsio")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local rsctl = require("supervisor.session.rsctl")
|
||||
|
||||
---@class facility_management
|
||||
local facility = {}
|
||||
|
||||
-- create a new facility management object
|
||||
function facility.new()
|
||||
local self = {
|
||||
induction = {},
|
||||
redstone = {}
|
||||
}
|
||||
|
||||
-- init redstone RTU I/O controller
|
||||
local rs_rtu_io_ctl = rsctl.new(self.redstone)
|
||||
|
||||
-- unlink disconnected units
|
||||
---@param sessions table
|
||||
local function _unlink_disconnected_units(sessions)
|
||||
util.filter_table(sessions, function (u) return u.is_connected() end)
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
---@class facility
|
||||
local public = {}
|
||||
|
||||
-- ADD/LINK DEVICES --
|
||||
|
||||
-- link a redstone RTU session
|
||||
---@param rs_unit unit_session
|
||||
function public.add_redstone(rs_unit)
|
||||
table.insert(self.redstone, rs_unit)
|
||||
end
|
||||
|
||||
-- link an imatrix RTU session
|
||||
---@param imatrix unit_session
|
||||
function public.add_imatrix(imatrix)
|
||||
table.insert(self.induction, imatrix)
|
||||
end
|
||||
|
||||
-- purge devices associated with the given RTU session ID
|
||||
---@param session integer RTU session ID
|
||||
function public.purge_rtu_devices(session)
|
||||
util.filter_table(self.redstone, function (s) return s.get_session_id() ~= session end)
|
||||
util.filter_table(self.induction, function (s) return s.get_session_id() ~= session end)
|
||||
end
|
||||
|
||||
-- UPDATE --
|
||||
|
||||
-- update (iterate) the facility management
|
||||
function public.update()
|
||||
-- unlink RTU unit sessions if they are closed
|
||||
_unlink_disconnected_units(self.induction)
|
||||
_unlink_disconnected_units(self.redstone)
|
||||
end
|
||||
|
||||
-- READ STATES/PROPERTIES --
|
||||
|
||||
-- get build properties of all machines
|
||||
function public.get_build()
|
||||
local build = {}
|
||||
|
||||
build.induction = {}
|
||||
for i = 1, #self.induction do
|
||||
local matrix = self.induction[i] ---@type unit_session
|
||||
build.induction[matrix.get_device_idx()] = { matrix.get_db().formed, matrix.get_db().build }
|
||||
end
|
||||
|
||||
return build
|
||||
end
|
||||
|
||||
-- get RTU statuses
|
||||
function public.get_rtu_statuses()
|
||||
local status = {}
|
||||
|
||||
-- status of induction matricies (including tanks)
|
||||
status.induction = {}
|
||||
for i = 1, #self.induction do
|
||||
local matrix = self.induction[i] ---@type unit_session
|
||||
status.induction[matrix.get_device_idx()] = {
|
||||
matrix.is_faulted(),
|
||||
matrix.get_db().formed,
|
||||
matrix.get_db().state,
|
||||
matrix.get_db().tanks
|
||||
}
|
||||
end
|
||||
|
||||
---@todo other RTU statuses
|
||||
|
||||
return status
|
||||
end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
return facility
|
||||
@@ -11,7 +11,7 @@ local PROTOCOLS = comms.PROTOCOLS
|
||||
local RPLC_TYPES = comms.RPLC_TYPES
|
||||
local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
|
||||
|
||||
local CRDN_COMMANDS = comms.CRDN_COMMANDS
|
||||
local UNIT_COMMANDS = comms.UNIT_COMMANDS
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
@@ -352,7 +352,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- send acknowledgement to coordinator
|
||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||
unit = self.for_reactor,
|
||||
cmd = CRDN_COMMANDS.SET_BURN,
|
||||
cmd = UNIT_COMMANDS.SET_BURN,
|
||||
ack = ack
|
||||
})
|
||||
elseif pkt.type == RPLC_TYPES.RPS_ENABLE then
|
||||
@@ -367,7 +367,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- send acknowledgement to coordinator
|
||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||
unit = self.for_reactor,
|
||||
cmd = CRDN_COMMANDS.START,
|
||||
cmd = UNIT_COMMANDS.START,
|
||||
ack = ack
|
||||
})
|
||||
elseif pkt.type == RPLC_TYPES.RPS_SCRAM then
|
||||
@@ -383,7 +383,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- send acknowledgement to coordinator
|
||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||
unit = self.for_reactor,
|
||||
cmd = CRDN_COMMANDS.SCRAM,
|
||||
cmd = UNIT_COMMANDS.SCRAM,
|
||||
ack = ack
|
||||
})
|
||||
elseif pkt.type == RPLC_TYPES.RPS_ASCRAM then
|
||||
@@ -435,7 +435,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
|
||||
-- send acknowledgement to coordinator
|
||||
self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
|
||||
unit = self.for_reactor,
|
||||
cmd = CRDN_COMMANDS.RESET_RPS,
|
||||
cmd = UNIT_COMMANDS.RESET_RPS,
|
||||
ack = ack
|
||||
})
|
||||
else
|
||||
|
||||
39
supervisor/session/rsctl.lua
Normal file
39
supervisor/session/rsctl.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
--
|
||||
-- Redstone RTU Session I/O Controller
|
||||
--
|
||||
|
||||
local rsctl = {}
|
||||
|
||||
-- create a new redstone RTU I/O controller
|
||||
---@param redstone_rtus table redstone RTU sessions
|
||||
function rsctl.new(redstone_rtus)
|
||||
---@class rs_controller
|
||||
local public = {}
|
||||
|
||||
-- write to a digital redstone port (applies to all RTUs)
|
||||
---@param port IO_PORT
|
||||
---@param value boolean
|
||||
function public.digital_write(port, value)
|
||||
for i = 1, #redstone_rtus do
|
||||
local db = redstone_rtus[i].get_db() ---@type redstone_session_db
|
||||
local io = db.io[port] ---@type rs_db_dig_io|nil
|
||||
if io ~= nil then io.write(value) end
|
||||
end
|
||||
end
|
||||
|
||||
-- read a digital redstone port<br>
|
||||
-- this will read from the first one encountered if there are multiple, because there should not be multiple
|
||||
---@param port IO_PORT
|
||||
---@return boolean|nil
|
||||
function public.digital_read(port)
|
||||
for i = 1, #redstone_rtus do
|
||||
local db = redstone_rtus[i].get_db() ---@type redstone_session_db
|
||||
local io = db.io[port] ---@type rs_db_dig_io|nil
|
||||
if io ~= nil then return io.read() end
|
||||
end
|
||||
end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
return rsctl
|
||||
@@ -36,16 +36,15 @@ local PERIODICS = {
|
||||
---@param in_queue mqueue
|
||||
---@param out_queue mqueue
|
||||
---@param advertisement table
|
||||
---@param facility facility
|
||||
---@param facility_units table
|
||||
function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
function rtu.new_session(id, in_queue, out_queue, advertisement, facility, facility_units)
|
||||
local log_header = "rtu_session(" .. id .. "): "
|
||||
|
||||
local self = {
|
||||
id = id,
|
||||
in_q = in_queue,
|
||||
out_q = out_queue,
|
||||
modbus_q = mqueue.new(),
|
||||
f_units = facility_units,
|
||||
advert = advertisement,
|
||||
-- connection properties
|
||||
seq_num = 0,
|
||||
@@ -72,9 +71,10 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
local function _handle_advertisement()
|
||||
_reset_config()
|
||||
|
||||
for i = 1, #self.f_units do
|
||||
local unit = self.f_units[i] ---@type reactor_unit
|
||||
unit.purge_rtu_devices(self.id)
|
||||
for i = 1, #facility_units do
|
||||
local unit = facility_units[i] ---@type reactor_unit
|
||||
unit.purge_rtu_devices(id)
|
||||
facility.purge_rtu_devices(id)
|
||||
end
|
||||
|
||||
for i = 1, #self.advert do
|
||||
@@ -104,47 +104,61 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
|
||||
if advert_validator.valid() then
|
||||
advert_validator.assert_min(unit_advert.index, 1)
|
||||
advert_validator.assert_min(unit_advert.reactor, 1)
|
||||
advert_validator.assert_max(unit_advert.reactor, #self.f_units)
|
||||
advert_validator.assert_min(unit_advert.reactor, 0)
|
||||
advert_validator.assert_max(unit_advert.reactor, #facility_units)
|
||||
if not advert_validator.valid() then u_type = false end
|
||||
else
|
||||
u_type = false
|
||||
end
|
||||
|
||||
local type_string = util.strval(u_type)
|
||||
if type(u_type) == "number" then type_string = util.strval(comms.advert_type_to_rtu_t(u_type)) end
|
||||
|
||||
-- create unit by type
|
||||
|
||||
if u_type == false then
|
||||
-- validation fail
|
||||
log.debug(log_header .. "advertisement unit validation failure")
|
||||
else
|
||||
local target_unit = self.f_units[unit_advert.reactor] ---@type reactor_unit
|
||||
if unit_advert.reactor > 0 then
|
||||
local target_unit = facility_units[unit_advert.reactor] ---@type reactor_unit
|
||||
|
||||
if u_type == RTU_UNIT_TYPES.REDSTONE then
|
||||
-- redstone
|
||||
unit = svrs_redstone.new(self.id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_redstone(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPES.BOILER_VALVE then
|
||||
-- boiler (Mekanism 10.1+)
|
||||
unit = svrs_boilerv.new(self.id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_boiler(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPES.TURBINE_VALVE then
|
||||
-- turbine (Mekanism 10.1+)
|
||||
unit = svrs_turbinev.new(self.id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_turbine(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPES.IMATRIX then
|
||||
-- induction matrix
|
||||
unit = svrs_imatrix.new(self.id, i, unit_advert, self.modbus_q)
|
||||
elseif u_type == RTU_UNIT_TYPES.SPS then
|
||||
-- super-critical phase shifter
|
||||
unit = svrs_sps.new(self.id, i, unit_advert, self.modbus_q)
|
||||
elseif u_type == RTU_UNIT_TYPES.SNA then
|
||||
-- solar neutron activator
|
||||
unit = svrs_sna.new(self.id, i, unit_advert, self.modbus_q)
|
||||
elseif u_type == RTU_UNIT_TYPES.ENV_DETECTOR then
|
||||
-- environment detector
|
||||
unit = svrs_envd.new(self.id, i, unit_advert, self.modbus_q)
|
||||
if u_type == RTU_UNIT_TYPES.REDSTONE then
|
||||
-- redstone
|
||||
unit = svrs_redstone.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_redstone(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPES.BOILER_VALVE then
|
||||
-- boiler (Mekanism 10.1+)
|
||||
unit = svrs_boilerv.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_boiler(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPES.TURBINE_VALVE then
|
||||
-- turbine (Mekanism 10.1+)
|
||||
unit = svrs_turbinev.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then target_unit.add_turbine(unit) end
|
||||
else
|
||||
log.error(util.c(log_header, "bad advertisement: encountered unsupported reactor-specific RTU type ", type_string))
|
||||
end
|
||||
else
|
||||
log.error(log_header .. "bad advertisement: encountered unsupported RTU type")
|
||||
if u_type == RTU_UNIT_TYPES.REDSTONE then
|
||||
-- redstone
|
||||
unit = svrs_redstone.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then facility.add_redstone(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPES.IMATRIX then
|
||||
-- induction matrix
|
||||
unit = svrs_imatrix.new(id, i, unit_advert, self.modbus_q)
|
||||
if type(unit) ~= "nil" then facility.add_imatrix(unit) end
|
||||
elseif u_type == RTU_UNIT_TYPES.SPS then
|
||||
-- super-critical phase shifter
|
||||
unit = svrs_sps.new(id, i, unit_advert, self.modbus_q)
|
||||
elseif u_type == RTU_UNIT_TYPES.SNA then
|
||||
-- solar neutron activator
|
||||
unit = svrs_sna.new(id, i, unit_advert, self.modbus_q)
|
||||
elseif u_type == RTU_UNIT_TYPES.ENV_DETECTOR then
|
||||
-- environment detector
|
||||
unit = svrs_envd.new(id, i, unit_advert, self.modbus_q)
|
||||
else
|
||||
log.error(util.c(log_header, "bad advertisement: encountered unsupported reactor-independent RTU type ", type_string))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -152,10 +166,7 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
table.insert(self.units, unit)
|
||||
else
|
||||
_reset_config()
|
||||
if type(u_type) == "number" then
|
||||
local type_string = util.strval(comms.advert_type_to_rtu_t(u_type))
|
||||
log.error(log_header .. "bad advertisement: error occured while creating a unit (type is " .. type_string .. ")")
|
||||
end
|
||||
log.error(util.c(log_header, "bad advertisement: error occured while creating a unit (type is ", type_string, ")"))
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -271,7 +282,7 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
-- get the session ID
|
||||
function public.get_id() return self.id end
|
||||
function public.get_id() return id end
|
||||
|
||||
-- check if a timer matches this session's watchdog
|
||||
---@param timer number
|
||||
|
||||
@@ -2,6 +2,7 @@ local log = require("scada-common.log")
|
||||
local mqueue = require("scada-common.mqueue")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local facility = require("supervisor.session.facility")
|
||||
local svqtypes = require("supervisor.session.svqtypes")
|
||||
local unit = require("supervisor.session.unit")
|
||||
|
||||
@@ -32,7 +33,8 @@ svsessions.SESSION_TYPE = SESSION_TYPE
|
||||
local self = {
|
||||
modem = nil,
|
||||
num_reactors = 0,
|
||||
facility_units = {},
|
||||
facility = facility.new(),
|
||||
units = {},
|
||||
rtu_sessions = {},
|
||||
plc_sessions = {},
|
||||
coord_sessions = {},
|
||||
@@ -197,10 +199,10 @@ end
|
||||
function svsessions.init(modem, num_reactors, cooling_conf)
|
||||
self.modem = modem
|
||||
self.num_reactors = num_reactors
|
||||
self.facility_units = {}
|
||||
self.units = {}
|
||||
|
||||
for i = 1, self.num_reactors do
|
||||
table.insert(self.facility_units, unit.new(i, cooling_conf[i].BOILERS, cooling_conf[i].TURBINES))
|
||||
table.insert(self.units, unit.new(i, cooling_conf[i].BOILERS, cooling_conf[i].TURBINES))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -297,7 +299,7 @@ function svsessions.establish_plc_session(local_port, remote_port, for_reactor,
|
||||
plc_s.instance = plc.new_session(self.next_plc_id, for_reactor, plc_s.in_queue, plc_s.out_queue)
|
||||
table.insert(self.plc_sessions, plc_s)
|
||||
|
||||
self.facility_units[for_reactor].link_plc_session(plc_s)
|
||||
self.units[for_reactor].link_plc_session(plc_s)
|
||||
|
||||
log.debug("established new PLC session to " .. remote_port .. " with ID " .. self.next_plc_id)
|
||||
|
||||
@@ -330,7 +332,7 @@ function svsessions.establish_rtu_session(local_port, remote_port, advertisement
|
||||
instance = nil ---@type rtu_session
|
||||
}
|
||||
|
||||
rtu_s.instance = rtu.new_session(self.next_rtu_id, rtu_s.in_queue, rtu_s.out_queue, advertisement, self.facility_units)
|
||||
rtu_s.instance = rtu.new_session(self.next_rtu_id, rtu_s.in_queue, rtu_s.out_queue, advertisement, self.facility, self.units)
|
||||
table.insert(self.rtu_sessions, rtu_s)
|
||||
|
||||
log.debug("established new RTU session to " .. remote_port .. " with ID " .. self.next_rtu_id)
|
||||
@@ -360,7 +362,7 @@ function svsessions.establish_coord_session(local_port, remote_port, version)
|
||||
instance = nil ---@type coord_session
|
||||
}
|
||||
|
||||
coord_s.instance = coordinator.new_session(self.next_coord_id, coord_s.in_queue, coord_s.out_queue, self.facility_units)
|
||||
coord_s.instance = coordinator.new_session(self.next_coord_id, coord_s.in_queue, coord_s.out_queue, self.facility, self.units)
|
||||
table.insert(self.coord_sessions, coord_s)
|
||||
|
||||
log.debug("established new coordinator session to " .. remote_port .. " with ID " .. self.next_coord_id)
|
||||
@@ -399,9 +401,12 @@ function svsessions.iterate_all()
|
||||
-- iterate coordinator sessions
|
||||
_iterate(self.coord_sessions)
|
||||
|
||||
-- iterate facility
|
||||
self.facility.update()
|
||||
|
||||
-- iterate units
|
||||
for i = 1, #self.facility_units do
|
||||
local u = self.facility_units[i] ---@type reactor_unit
|
||||
for i = 1, #self.units do
|
||||
local u = self.units[i] ---@type reactor_unit
|
||||
u.update()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
local log = require("scada-common.log")
|
||||
local rsio = require("scada-common.rsio")
|
||||
local types = require("scada-common.types")
|
||||
local util = require("scada-common.util")
|
||||
local log = require("scada-common.log")
|
||||
local rsio = require("scada-common.rsio")
|
||||
local types = require("scada-common.types")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local qtypes = require("supervisor.session.rtu.qtypes")
|
||||
local rsctl = require("supervisor.session.rsctl")
|
||||
|
||||
---@class reactor_control_unit
|
||||
local unit = {}
|
||||
@@ -178,6 +178,9 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
}
|
||||
}
|
||||
|
||||
-- init redstone RTU I/O controller
|
||||
local rs_rtu_io_ctl = rsctl.new(self.redstone)
|
||||
|
||||
-- init boiler table fields
|
||||
for _ = 1, num_boilers do
|
||||
table.insert(self.db.annunciator.BoilerOnline, false)
|
||||
@@ -192,9 +195,6 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
table.insert(self.db.annunciator.TurbineTrip, false)
|
||||
end
|
||||
|
||||
---@class reactor_unit
|
||||
local public = {}
|
||||
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
--#region time derivative utility functions
|
||||
@@ -237,26 +237,8 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
|
||||
--#region redstone I/O
|
||||
|
||||
-- write to a redstone port
|
||||
local function __rs_w(port, value)
|
||||
for i = 1, #self.redstone do
|
||||
local db = self.redstone[i].get_db() ---@type redstone_session_db
|
||||
local io = db.io[port] ---@type rs_db_dig_io|nil
|
||||
if io ~= nil then io.write(value) end
|
||||
end
|
||||
end
|
||||
|
||||
-- read a redstone port<br>
|
||||
-- this will read from the first one encountered if there are multiple, because there should not be multiple
|
||||
---@param port IO_PORT
|
||||
---@return boolean|nil
|
||||
local function __rs_r(port)
|
||||
for i = 1, #self.redstone do
|
||||
local db = self.redstone[i].get_db() ---@type redstone_session_db
|
||||
local io = db.io[port] ---@type rs_db_dig_io|nil
|
||||
if io ~= nil then return io.read() end
|
||||
end
|
||||
end
|
||||
local __rs_w = rs_rtu_io_ctl.digital_write
|
||||
local __rs_r = rs_rtu_io_ctl.digital_read
|
||||
|
||||
-- waste valves
|
||||
local waste_pu = { open = function () __rs_w(IO.WASTE_PU, true) end, close = function () __rs_w(IO.WASTE_PU, false) end }
|
||||
@@ -702,6 +684,9 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
---@class reactor_unit
|
||||
local public = {}
|
||||
|
||||
-- ADD/LINK DEVICES --
|
||||
|
||||
-- link the PLC
|
||||
@@ -722,7 +707,6 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
-- link a redstone RTU session
|
||||
---@param rs_unit unit_session
|
||||
function public.add_redstone(rs_unit)
|
||||
-- insert into list
|
||||
table.insert(self.redstone, rs_unit)
|
||||
end
|
||||
|
||||
@@ -781,6 +765,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
-- unlink RTU unit sessions if they are closed
|
||||
_unlink_disconnected_units(self.boilers)
|
||||
_unlink_disconnected_units(self.turbines)
|
||||
_unlink_disconnected_units(self.redstone)
|
||||
|
||||
-- update annunciator logic
|
||||
_update_annunciator()
|
||||
|
||||
@@ -14,7 +14,7 @@ local svsessions = require("supervisor.session.svsessions")
|
||||
local config = require("supervisor.config")
|
||||
local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local SUPERVISOR_VERSION = "beta-v0.8.5"
|
||||
local SUPERVISOR_VERSION = "beta-v0.9.0"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
|
||||
Reference in New Issue
Block a user