code cleanup, type hints, bugfixes, and #98 removal of support for mek 10.0 RTU peripherals
This commit is contained in:
@@ -8,6 +8,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 print = util.print
|
||||
local println = util.println
|
||||
@@ -163,6 +164,24 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
|
||||
if pkt.type == SCADA_CRDN_TYPES.STRUCT_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPES.COMMAND_UNIT then
|
||||
if pkt.length > 2 then
|
||||
-- get command and unit id
|
||||
local cmd = pkt.data[1]
|
||||
local uid = pkt.data[2]
|
||||
|
||||
-- continue if valid unit id
|
||||
if util.is_int(uid) and uid > 0 and uid <= #self.units then
|
||||
local unit = self.units[pkt.data[2]] ---@type reactor_unit
|
||||
if cmd == CRDN_COMMANDS.SCRAM then
|
||||
unit.scram()
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "CRDN command unit invalid")
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "CRDN command unit packet length mismatch")
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "handler received unexpected SCADA_CRDN packet type " .. pkt.type)
|
||||
end
|
||||
|
||||
@@ -5,15 +5,12 @@ local rsio = require("scada-common.rsio")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
-- supervisor rtu sessions (svrs)
|
||||
local svrs_boiler = require("supervisor.session.rtu.boiler")
|
||||
local svrs_boilerv = require("supervisor.session.rtu.boilerv")
|
||||
local svrs_emachine = require("supervisor.session.rtu.emachine")
|
||||
local svrs_envd = require("supervisor.session.rtu.envd")
|
||||
local svrs_imatrix = require("supervisor.session.rtu.imatrix")
|
||||
local svrs_redstone = require("supervisor.session.rtu.redstone")
|
||||
local svrs_sna = require("supervisor.session.rtu.sna")
|
||||
local svrs_sps = require("supervisor.session.rtu.sps")
|
||||
local svrs_turbine = require("supervisor.session.rtu.turbine")
|
||||
local svrs_turbinev = require("supervisor.session.rtu.turbinev")
|
||||
|
||||
local rtu = {}
|
||||
@@ -76,7 +73,6 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
},
|
||||
rs_io_q = {},
|
||||
turbine_cmd_q = {},
|
||||
turbine_cmd_capable = false,
|
||||
units = {}
|
||||
}
|
||||
|
||||
@@ -87,7 +83,6 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
self.units = {}
|
||||
self.rs_io_q = {}
|
||||
self.turbine_cmd_q = {}
|
||||
self.turbine_cmd_capable = false
|
||||
end
|
||||
|
||||
-- parse the recorded advertisement and create unit sub-sessions
|
||||
@@ -110,7 +105,7 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
|
||||
local target_unit = self.f_units[unit_advert.reactor] ---@type reactor_unit
|
||||
|
||||
local u_type = unit_advert.type
|
||||
local u_type = unit_advert.type ---@type integer|boolean
|
||||
|
||||
-- validate unit advertisement
|
||||
|
||||
@@ -137,26 +132,14 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
elseif u_type == RTU_UNIT_TYPES.REDSTONE then
|
||||
-- redstone
|
||||
unit, rs_in_q = svrs_redstone.new(self.id, i, unit_advert, self.modbus_q)
|
||||
elseif u_type == RTU_UNIT_TYPES.BOILER then
|
||||
-- boiler
|
||||
unit = svrs_boiler.new(self.id, i, unit_advert, self.modbus_q)
|
||||
target_unit.add_boiler(unit)
|
||||
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)
|
||||
target_unit.add_boiler(unit)
|
||||
elseif u_type == RTU_UNIT_TYPES.TURBINE then
|
||||
-- turbine
|
||||
unit = svrs_turbine.new(self.id, i, unit_advert, self.modbus_q)
|
||||
target_unit.add_turbine(unit)
|
||||
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, tbv_in_q = svrs_turbinev.new(self.id, i, unit_advert, self.modbus_q)
|
||||
target_unit.add_turbine(unit)
|
||||
self.turbine_cmd_capable = true
|
||||
elseif u_type == RTU_UNIT_TYPES.EMACHINE then
|
||||
-- mekanism [energy] machine
|
||||
unit = svrs_emachine.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)
|
||||
@@ -202,8 +185,10 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
end
|
||||
else
|
||||
_reset_config()
|
||||
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 .. ")")
|
||||
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
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -265,6 +250,7 @@ function rtu.new_session(id, in_queue, out_queue, advertisement, facility_units)
|
||||
if pkt.scada_frame.protocol() == PROTOCOLS.MODBUS_TCP then
|
||||
if self.units[pkt.unit_id] ~= nil then
|
||||
local unit = self.units[pkt.unit_id] ---@type unit_session
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
unit.handle_packet(pkt)
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOLS.SCADA_MGMT then
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
local comms = require("scada-common.comms")
|
||||
local log = require("scada-common.log")
|
||||
local types = require("scada-common.types")
|
||||
|
||||
local unit_session = require("supervisor.session.rtu.unit_session")
|
||||
|
||||
local boiler = {}
|
||||
|
||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||
|
||||
local TXN_TYPES = {
|
||||
BUILD = 1,
|
||||
STATE = 2,
|
||||
TANKS = 3
|
||||
}
|
||||
|
||||
local TXN_TAGS = {
|
||||
"boiler.build",
|
||||
"boiler.state",
|
||||
"boiler.tanks"
|
||||
}
|
||||
|
||||
local PERIODICS = {
|
||||
BUILD = 1000,
|
||||
STATE = 500,
|
||||
TANKS = 1000
|
||||
}
|
||||
|
||||
-- create a new boiler rtu session runner
|
||||
---@param session_id integer
|
||||
---@param unit_id integer
|
||||
---@param advert rtu_advertisement
|
||||
---@param out_queue mqueue
|
||||
function boiler.new(session_id, unit_id, advert, out_queue)
|
||||
-- type check
|
||||
if advert.type ~= RTU_UNIT_TYPES.BOILER then
|
||||
log.error("attempt to instantiate boiler RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local log_tag = "session.rtu(" .. session_id .. ").boiler(" .. advert.index .. "): "
|
||||
|
||||
local self = {
|
||||
session = unit_session.new(unit_id, advert, out_queue, log_tag, TXN_TAGS),
|
||||
has_build = false,
|
||||
periodics = {
|
||||
next_build_req = 0,
|
||||
next_state_req = 0,
|
||||
next_tanks_req = 0
|
||||
},
|
||||
---@class boiler_session_db
|
||||
db = {
|
||||
build = {
|
||||
boil_cap = 0.0,
|
||||
steam_cap = 0,
|
||||
water_cap = 0,
|
||||
hcoolant_cap = 0,
|
||||
ccoolant_cap = 0,
|
||||
superheaters = 0,
|
||||
max_boil_rate = 0.0
|
||||
},
|
||||
state = {
|
||||
temperature = 0.0,
|
||||
boil_rate = 0.0
|
||||
},
|
||||
tanks = {
|
||||
steam = 0,
|
||||
steam_need = 0,
|
||||
steam_fill = 0.0,
|
||||
water = 0,
|
||||
water_need = 0,
|
||||
water_fill = 0.0,
|
||||
hcool = {}, ---@type tank_fluid
|
||||
hcool_need = 0,
|
||||
hcool_fill = 0.0,
|
||||
ccool = {}, ---@type tank_fluid
|
||||
ccool_need = 0,
|
||||
ccool_fill = 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local public = self.session.get()
|
||||
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
-- read input registers 1 through 7 (start = 1, count = 7)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 7 })
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
-- read input registers 8 through 9 (start = 8, count = 2)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 8, 2 })
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
-- read input registers 10 through 21 (start = 10, count = 12)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 10, 12 })
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
-- handle a packet
|
||||
---@param m_pkt modbus_frame
|
||||
function public.handle_packet(m_pkt)
|
||||
local txn_type = self.session.try_resolve(m_pkt)
|
||||
if txn_type == false then
|
||||
-- nothing to do
|
||||
elseif txn_type == TXN_TYPES.BUILD then
|
||||
-- build response
|
||||
-- load in data if correct length
|
||||
if m_pkt.length == 7 then
|
||||
self.db.build.boil_cap = m_pkt.data[1]
|
||||
self.db.build.steam_cap = m_pkt.data[2]
|
||||
self.db.build.water_cap = m_pkt.data[3]
|
||||
self.db.build.hcoolant_cap = m_pkt.data[4]
|
||||
self.db.build.ccoolant_cap = m_pkt.data[5]
|
||||
self.db.build.superheaters = m_pkt.data[6]
|
||||
self.db.build.max_boil_rate = m_pkt.data[7]
|
||||
self.has_build = true
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == TXN_TYPES.STATE then
|
||||
-- state response
|
||||
-- load in data if correct length
|
||||
if m_pkt.length == 2 then
|
||||
self.db.state.temperature = m_pkt.data[1]
|
||||
self.db.state.boil_rate = m_pkt.data[2]
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == TXN_TYPES.TANKS then
|
||||
-- tanks response
|
||||
-- load in data if correct length
|
||||
if m_pkt.length == 12 then
|
||||
self.db.tanks.steam = m_pkt.data[1]
|
||||
self.db.tanks.steam_need = m_pkt.data[2]
|
||||
self.db.tanks.steam_fill = m_pkt.data[3]
|
||||
self.db.tanks.water = m_pkt.data[4]
|
||||
self.db.tanks.water_need = m_pkt.data[5]
|
||||
self.db.tanks.water_fill = m_pkt.data[6]
|
||||
self.db.tanks.hcool = m_pkt.data[7]
|
||||
self.db.tanks.hcool_need = m_pkt.data[8]
|
||||
self.db.tanks.hcool_fill = m_pkt.data[9]
|
||||
self.db.tanks.ccool = m_pkt.data[10]
|
||||
self.db.tanks.ccool_need = m_pkt.data[11]
|
||||
self.db.tanks.ccool_fill = m_pkt.data[12]
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == nil then
|
||||
log.error(log_tag .. "unknown transaction reply")
|
||||
else
|
||||
log.error(log_tag .. "unknown transaction type " .. txn_type)
|
||||
end
|
||||
end
|
||||
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
end
|
||||
|
||||
-- get the unit session database
|
||||
function public.get_db() return self.db end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
return boiler
|
||||
@@ -1,7 +1,6 @@
|
||||
local comms = require("scada-common.comms")
|
||||
local log = require("scada-common.log")
|
||||
local types = require("scada-common.types")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local unit_session = require("supervisor.session.rtu.unit_session")
|
||||
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
local comms = require("scada-common.comms")
|
||||
local log = require("scada-common.log")
|
||||
local types = require("scada-common.types")
|
||||
|
||||
local unit_session = require("supervisor.session.rtu.unit_session")
|
||||
|
||||
local emachine = {}
|
||||
|
||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||
|
||||
local TXN_TYPES = {
|
||||
BUILD = 1,
|
||||
STORAGE = 2
|
||||
}
|
||||
|
||||
local TXN_TAGS = {
|
||||
"emachine.build",
|
||||
"emachine.storage"
|
||||
}
|
||||
|
||||
local PERIODICS = {
|
||||
BUILD = 1000,
|
||||
STORAGE = 500
|
||||
}
|
||||
|
||||
-- create a new energy machine rtu session runner
|
||||
---@param session_id integer
|
||||
---@param unit_id integer
|
||||
---@param advert rtu_advertisement
|
||||
---@param out_queue mqueue
|
||||
function emachine.new(session_id, unit_id, advert, out_queue)
|
||||
-- type check
|
||||
if advert.type ~= RTU_UNIT_TYPES.EMACHINE then
|
||||
log.error("attempt to instantiate emachine RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local log_tag = "session.rtu(" .. session_id .. ").emachine(" .. advert.index .. "): "
|
||||
|
||||
local self = {
|
||||
session = unit_session.new(unit_id, advert, out_queue, log_tag, TXN_TAGS),
|
||||
has_build = false,
|
||||
periodics = {
|
||||
next_build_req = 0,
|
||||
next_storage_req = 0
|
||||
},
|
||||
---@class emachine_session_db
|
||||
db = {
|
||||
build = {
|
||||
max_energy = 0
|
||||
},
|
||||
storage = {
|
||||
energy = 0,
|
||||
energy_need = 0,
|
||||
energy_fill = 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local public = self.session.get()
|
||||
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
-- read input register 1 (start = 1, count = 1)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 1 })
|
||||
end
|
||||
|
||||
-- query the state of the energy storage
|
||||
local function _request_storage()
|
||||
-- read input registers 2 through 4 (start = 2, count = 3)
|
||||
self.session.send_request(TXN_TYPES.STORAGE, MODBUS_FCODE.READ_INPUT_REGS, { 2, 3 })
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
-- handle a packet
|
||||
---@param m_pkt modbus_frame
|
||||
function public.handle_packet(m_pkt)
|
||||
local txn_type = self.session.try_resolve(m_pkt)
|
||||
if txn_type == false then
|
||||
-- nothing to do
|
||||
elseif txn_type == TXN_TYPES.BUILD then
|
||||
-- build response
|
||||
if m_pkt.length == 1 then
|
||||
self.db.build.max_energy = m_pkt.data[1]
|
||||
self.has_build = true
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == TXN_TYPES.STORAGE then
|
||||
-- storage response
|
||||
if m_pkt.length == 3 then
|
||||
self.db.storage.energy = m_pkt.data[1]
|
||||
self.db.storage.energy_need = m_pkt.data[2]
|
||||
self.db.storage.energy_fill = m_pkt.data[3]
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == nil then
|
||||
log.error(log_tag .. "unknown transaction reply")
|
||||
else
|
||||
log.error(log_tag .. "unknown transaction type " .. txn_type)
|
||||
end
|
||||
end
|
||||
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_storage_req <= time_now then
|
||||
_request_storage()
|
||||
self.periodics.next_storage_req = time_now + PERIODICS.STORAGE
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
end
|
||||
|
||||
-- get the unit session database
|
||||
function public.get_db() return self.db end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
return emachine
|
||||
@@ -1,179 +0,0 @@
|
||||
local comms = require("scada-common.comms")
|
||||
local log = require("scada-common.log")
|
||||
local types = require("scada-common.types")
|
||||
|
||||
local unit_session = require("supervisor.session.rtu.unit_session")
|
||||
|
||||
local turbine = {}
|
||||
|
||||
local RTU_UNIT_TYPES = comms.RTU_UNIT_TYPES
|
||||
local DUMPING_MODE = types.DUMPING_MODE
|
||||
local MODBUS_FCODE = types.MODBUS_FCODE
|
||||
|
||||
local TXN_TYPES = {
|
||||
BUILD = 1,
|
||||
STATE = 2,
|
||||
TANKS = 3
|
||||
}
|
||||
|
||||
local TXN_TAGS = {
|
||||
"turbine.build",
|
||||
"turbine.state",
|
||||
"turbine.tanks"
|
||||
}
|
||||
|
||||
local PERIODICS = {
|
||||
BUILD = 1000,
|
||||
STATE = 500,
|
||||
TANKS = 1000
|
||||
}
|
||||
|
||||
-- create a new turbine rtu session runner
|
||||
---@param session_id integer
|
||||
---@param unit_id integer
|
||||
---@param advert rtu_advertisement
|
||||
---@param out_queue mqueue
|
||||
function turbine.new(session_id, unit_id, advert, out_queue)
|
||||
-- type check
|
||||
if advert.type ~= RTU_UNIT_TYPES.TURBINE then
|
||||
log.error("attempt to instantiate turbine RTU for type '" .. advert.type .. "'. this is a bug.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local log_tag = "session.rtu(" .. session_id .. ").turbine(" .. advert.index .. "): "
|
||||
|
||||
local self = {
|
||||
session = unit_session.new(unit_id, advert, out_queue, log_tag, TXN_TAGS),
|
||||
has_build = false,
|
||||
periodics = {
|
||||
next_build_req = 0,
|
||||
next_state_req = 0,
|
||||
next_tanks_req = 0
|
||||
},
|
||||
---@class turbine_session_db
|
||||
db = {
|
||||
build = {
|
||||
blades = 0,
|
||||
coils = 0,
|
||||
vents = 0,
|
||||
dispersers = 0,
|
||||
condensers = 0,
|
||||
steam_cap = 0,
|
||||
max_flow_rate = 0,
|
||||
max_production = 0,
|
||||
max_water_output = 0
|
||||
},
|
||||
state = {
|
||||
flow_rate = 0,
|
||||
prod_rate = 0,
|
||||
steam_input_rate = 0,
|
||||
dumping_mode = DUMPING_MODE.IDLE ---@type DUMPING_MODE
|
||||
},
|
||||
tanks = {
|
||||
steam = 0,
|
||||
steam_need = 0,
|
||||
steam_fill = 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local public = self.session.get()
|
||||
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
-- read input registers 1 through 9 (start = 1, count = 9)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 9 })
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
-- read input registers 10 through 13 (start = 10, count = 4)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 10, 4 })
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
-- read input registers 14 through 16 (start = 14, count = 3)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 14, 3 })
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
-- handle a packet
|
||||
---@param m_pkt modbus_frame
|
||||
function public.handle_packet(m_pkt)
|
||||
local txn_type = self.session.try_resolve(m_pkt)
|
||||
if txn_type == false then
|
||||
-- nothing to do
|
||||
elseif txn_type == TXN_TYPES.BUILD then
|
||||
-- build response
|
||||
if m_pkt.length == 9 then
|
||||
self.db.build.blades = m_pkt.data[1]
|
||||
self.db.build.coils = m_pkt.data[2]
|
||||
self.db.build.vents = m_pkt.data[3]
|
||||
self.db.build.dispersers = m_pkt.data[4]
|
||||
self.db.build.condensers = m_pkt.data[5]
|
||||
self.db.build.steam_cap = m_pkt.data[6]
|
||||
self.db.build.max_flow_rate = m_pkt.data[7]
|
||||
self.db.build.max_production = m_pkt.data[8]
|
||||
self.db.build.max_water_output = m_pkt.data[9]
|
||||
self.has_build = true
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == TXN_TYPES.STATE then
|
||||
-- state response
|
||||
if m_pkt.length == 4 then
|
||||
self.db.state.flow_rate = m_pkt.data[1]
|
||||
self.db.state.prod_rate = m_pkt.data[2]
|
||||
self.db.state.steam_input_rate = m_pkt.data[3]
|
||||
self.db.state.dumping_mode = m_pkt.data[4]
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == TXN_TYPES.TANKS then
|
||||
-- tanks response
|
||||
if m_pkt.length == 3 then
|
||||
self.db.tanks.steam = m_pkt.data[1]
|
||||
self.db.tanks.steam_need = m_pkt.data[2]
|
||||
self.db.tanks.steam_fill = m_pkt.data[3]
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
elseif txn_type == nil then
|
||||
log.error(log_tag .. "unknown transaction reply")
|
||||
else
|
||||
log.error(log_tag .. "unknown transaction type " .. txn_type)
|
||||
end
|
||||
end
|
||||
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
end
|
||||
|
||||
-- get the unit session database
|
||||
function public.get_db() return self.db end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
return turbine
|
||||
@@ -147,6 +147,7 @@ end
|
||||
---@return rtu_session_struct|nil
|
||||
function svsessions.find_rtu_session(remote_port)
|
||||
-- check RTU sessions
|
||||
---@diagnostic disable-next-line: return-type-mismatch
|
||||
return _find_session(self.rtu_sessions, remote_port)
|
||||
end
|
||||
|
||||
@@ -155,6 +156,7 @@ end
|
||||
---@return plc_session_struct|nil
|
||||
function svsessions.find_plc_session(remote_port)
|
||||
-- check PLC sessions
|
||||
---@diagnostic disable-next-line: return-type-mismatch
|
||||
return _find_session(self.plc_sessions, remote_port)
|
||||
end
|
||||
|
||||
@@ -176,6 +178,7 @@ end
|
||||
---@return nil
|
||||
function svsessions.find_coord_session(remote_port)
|
||||
-- check coordinator sessions
|
||||
---@diagnostic disable-next-line: return-type-mismatch
|
||||
return _find_session(self.coord_sessions, remote_port)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
local types = require "scada-common.types"
|
||||
local util = require "scada-common.util"
|
||||
local log = require "scada-common.log"
|
||||
local types = require("scada-common.types")
|
||||
local util = require("scada-common.util")
|
||||
local log = require("scada-common.log")
|
||||
|
||||
local unit = {}
|
||||
|
||||
@@ -204,7 +204,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
-- go through boilers for stats and online
|
||||
for i = 1, #self.boilers do
|
||||
local session = self.boilers[i] ---@type unit_session
|
||||
local boiler = session.get_db() ---@type boiler_session_db
|
||||
local boiler = session.get_db() ---@type boilerv_session_db
|
||||
|
||||
total_boil_rate = total_boil_rate + boiler.state.boil_rate
|
||||
boiler_steam_dt_sum = _get_dt(DT_KEYS.BoilerSteam .. self.boilers[i].get_device_idx())
|
||||
@@ -221,7 +221,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
for i = 1, #self.boilers do
|
||||
local boiler = self.boilers[i] ---@type unit_session
|
||||
local idx = boiler.get_device_idx()
|
||||
local db = boiler.get_db() ---@type boiler_session_db
|
||||
local db = boiler.get_db() ---@type boilerv_session_db
|
||||
|
||||
if r_db.mek_status.status then
|
||||
self.db.annunciator.HeatingRateLow[idx] = db.state.boil_rate == 0
|
||||
@@ -240,7 +240,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
for i = 1, #self.boilers do
|
||||
local boiler = self.boilers[i] ---@type unit_session
|
||||
local idx = boiler.get_device_idx()
|
||||
local db = boiler.get_db() ---@type boiler_session_db
|
||||
local db = boiler.get_db() ---@type boilerv_session_db
|
||||
|
||||
local gaining_hc = _get_dt(DT_KEYS.BoilerHCool .. idx) > 0 or db.tanks.hcool_fill == 1
|
||||
|
||||
@@ -267,7 +267,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
-- go through turbines for stats and online
|
||||
for i = 1, #self.turbines do
|
||||
local session = self.turbines[i] ---@type unit_session
|
||||
local turbine = session.get_db() ---@type turbine_session_db
|
||||
local turbine = session.get_db() ---@type turbinev_session_db
|
||||
|
||||
total_flow_rate = total_flow_rate + turbine.state.flow_rate
|
||||
total_input_rate = total_input_rate + turbine.state.steam_input_rate
|
||||
@@ -285,7 +285,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
-- check if steam dumps are open
|
||||
for i = 1, #self.turbines do
|
||||
local turbine = self.turbines[i] ---@type unit_session
|
||||
local db = turbine.get_db() ---@type turbine_session_db
|
||||
local db = turbine.get_db() ---@type turbinev_session_db
|
||||
local idx = turbine.get_device_idx()
|
||||
|
||||
if db.state.dumping_mode == DUMPING_MODE.IDLE then
|
||||
@@ -300,7 +300,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
-- check if turbines are at max speed but not keeping up
|
||||
for i = 1, #self.turbines do
|
||||
local turbine = self.turbines[i] ---@type unit_session
|
||||
local db = turbine.get_db() ---@type turbine_session_db
|
||||
local db = turbine.get_db() ---@type turbinev_session_db
|
||||
local idx = turbine.get_device_idx()
|
||||
|
||||
self.db.annunciator.TurbineOverSpeed[idx] = (db.state.flow_rate == db.build.max_flow_rate) and (_get_dt(DT_KEYS.TurbineSteam .. idx) > 0)
|
||||
@@ -316,7 +316,7 @@ function unit.new(for_reactor, num_boilers, num_turbines)
|
||||
]]--
|
||||
for i = 1, #self.turbines do
|
||||
local turbine = self.turbines[i] ---@type unit_session
|
||||
local db = turbine.get_db() ---@type turbine_session_db
|
||||
local db = turbine.get_db() ---@type turbinev_session_db
|
||||
|
||||
local has_steam = db.state.steam_input_rate > 0 or db.tanks.steam_fill > 0.01
|
||||
self.db.annunciator.TurbineTrip[turbine.get_device_idx()] = has_steam and db.state.flow_rate == 0
|
||||
|
||||
Reference in New Issue
Block a user