diff --git a/supervisor/facility.lua b/supervisor/facility.lua index 65c6b09..a205dfc 100644 --- a/supervisor/facility.lua +++ b/supervisor/facility.lua @@ -2,11 +2,11 @@ local log = require("scada-common.log") local types = require("scada-common.types") local util = require("scada-common.util") +local unit = require("supervisor.unit") local fac_update = require("supervisor.facility_update") -local unit = require("supervisor.unit") - local rsctl = require("supervisor.session.rsctl") +local svsessions = require("supervisor.session.svsessions") local PROCESS = types.PROCESS local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE @@ -35,9 +35,7 @@ local facility = {} -- create a new facility management object ---@nodiscard ---@param config svr_config supervisor configuration ----@param cooling_conf sv_cooling_conf cooling configurations of reactor units ----@param check_rtu_id function ID checking function for RTUs attempting to be linked -function facility.new(config, cooling_conf, check_rtu_id) +function facility.new(config) ---@class _facility_self local self = { units = {}, @@ -46,8 +44,13 @@ function facility.new(config, cooling_conf, check_rtu_id) all_sys_ok = false, allow_testing = false, -- facility tanks - tank_defs = cooling_conf.fac_tank_defs, - tank_list = {}, + ---@class sv_cooling_conf + cooling_conf = { + r_cool = config.CoolingConfig, + fac_tank_mode = config.FacilityTankMode, + fac_tank_defs = config.FacilityTankDefs, + fac_tank_list = {} + }, -- rtus rtu_conn_count = 0, rtu_list = {}, @@ -124,7 +127,8 @@ function facility.new(config, cooling_conf, check_rtu_id) -- create units for i = 1, config.UnitCount do - table.insert(self.units, unit.new(i, cooling_conf.r_cool[i].BoilerCount, cooling_conf.r_cool[i].TurbineCount, check_rtu_id, config.ExtChargeIdling)) + table.insert(self.units, + unit.new(i, self.cooling_conf.r_cool[i].BoilerCount, self.cooling_conf.r_cool[i].TurbineCount, config.ExtChargeIdling)) table.insert(self.group_map, 0) end @@ -143,26 +147,28 @@ function facility.new(config, cooling_conf, check_rtu_id) --#region decode tank configuration + local cool_conf = self.cooling_conf + -- determine tank information - if cooling_conf.fac_tank_mode == 0 then - self.tank_defs = {} + if cool_conf.fac_tank_mode == 0 then + cool_conf.tank_defs = {} -- on facility tank mode 0, setup tank defs to match unit tank option for i = 1, config.UnitCount do - self.tank_defs[i] = util.trinary(cooling_conf.r_cool[i].TankConnection, 1, 0) + cool_conf.tank_defs[i] = util.trinary(cool_conf.r_cool[i].TankConnection, 1, 0) end - self.tank_list = { table.unpack(self.tank_defs) } + cool_conf.tank_list = { table.unpack(cool_conf.tank_defs) } else -- decode the layout of tanks from the connections definitions - local tank_mode = cooling_conf.fac_tank_mode - local tank_defs = self.tank_defs + local tank_mode = cool_conf.fac_tank_mode + local tank_defs = cool_conf.fac_tank_defs local tank_list = { table.unpack(tank_defs) } local function calc_fdef(start_idx, end_idx) local first = 4 for i = start_idx, end_idx do - if self.tank_defs[i] == 2 then + if tank_defs[i] == 2 then if i < first then first = i end end end @@ -227,7 +233,7 @@ function facility.new(config, cooling_conf, check_rtu_id) end end - self.tank_list = tank_list + cool_conf.fac_tank_list = tank_list end --#endregion @@ -247,7 +253,7 @@ function facility.new(config, cooling_conf, check_rtu_id) ---@param imatrix unit_session ---@return boolean linked induction matrix accepted (max 1) function public.add_imatrix(imatrix) - local fail_code, fail_str = check_rtu_id(imatrix, self.induction, 1) + local fail_code, fail_str = svsessions.check_rtu_id(imatrix, self.induction, 1) if fail_code == 0 then table.insert(self.induction, imatrix) @@ -262,7 +268,7 @@ function facility.new(config, cooling_conf, check_rtu_id) ---@param sps unit_session ---@return boolean linked SPS accepted (max 1) function public.add_sps(sps) - local fail_code, fail_str = check_rtu_id(sps, self.sps, 1) + local fail_code, fail_str = svsessions.check_rtu_id(sps, self.sps, 1) if fail_code == 0 then table.insert(self.sps, sps) @@ -303,7 +309,7 @@ function facility.new(config, cooling_conf, check_rtu_id) f_update.redstone(public.ack_all) -- unit tasks - f_update.unit_mgmt(cooling_conf) + f_update.unit_mgmt() -- update alarm tones f_update.alarm_audio() @@ -631,6 +637,9 @@ function facility.new(config, cooling_conf, check_rtu_id) ---@param rtu_sessions table session list of all connected RTUs function public.report_rtus(rtu_sessions) self.rtu_conn_count = #rtu_sessions end + -- get the facility cooling configuration + function public.get_cooling_conf() return self.cooling_conf end + -- get the units in this facility ---@nodiscard function public.get_units() return self.units end diff --git a/supervisor/facility_update.lua b/supervisor/facility_update.lua index b26c722..2927023 100644 --- a/supervisor/facility_update.lua +++ b/supervisor/facility_update.lua @@ -766,8 +766,7 @@ function update.redstone(ack_all) end -- update unit tasks ----@param cooling_conf sv_cooling_conf cooling configuration -function update.unit_mgmt(cooling_conf) +function update.unit_mgmt() local insufficent_po_rate = false local need_emcool = false @@ -782,7 +781,7 @@ function update.unit_mgmt(cooling_conf) end -- check if unit activated emergency coolant & uses facility tanks - if (cooling_conf.fac_tank_mode > 0) and u.is_emer_cool_tripped() and (cooling_conf.fac_tank_defs[i] == 2) then + if (self.cooling_conf.fac_tank_mode > 0) and u.is_emer_cool_tripped() and (self.cooling_conf.fac_tank_defs[i] == 2) then need_emcool = true end end diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index 3368451..904a29a 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -3,7 +3,6 @@ local mqueue = require("scada-common.mqueue") local util = require("scada-common.util") local databus = require("supervisor.databus") -local facility = require("supervisor.facility") local pgi = require("supervisor.panel.pgi") @@ -45,7 +44,7 @@ local self = { ---@alias sv_session_structs plc_session_struct|rtu_session_struct|crd_session_struct|pdg_session_struct --- PRIVATE FUNCTIONS -- +--#region PRIVATE FUNCTIONS -- handle a session output queue ---@param session sv_session_structs @@ -208,13 +207,15 @@ local function _update_dev_dbg() end end --- SHARED FUNCTIONS -- +--#endregion + +--#region PUBLIC FUNCTIONS ---@param unit unit_session RTU session ---@param list table table of RTU sessions ---@param max integer max of this type of RTU ---@return 0|1|2|3 fail_code, string fail_str 0 = success, 1 = out-of-range, 2 = duplicate, 3 = exceeded table max -local function check_rtu_id(unit, list, max) +function svsessions.check_rtu_id(unit, list, max) local fail_code, fail_str = 0, "OK" if (unit.get_device_idx() < 1 and max ~= 1) or unit.get_device_idx() > max then @@ -254,18 +255,16 @@ local function check_rtu_id(unit, list, max) return fail_code, fail_str end --- PUBLIC FUNCTIONS -- - -- initialize svsessions ---@param nic nic network interface device ---@param fp_ok boolean front panel active ---@param config svr_config supervisor configuration ----@param cooling_conf sv_cooling_conf cooling configuration definition -function svsessions.init(nic, fp_ok, config, cooling_conf) +---@param facility facility +function svsessions.init(nic, fp_ok, config, facility) self.nic = nic self.fp_ok = fp_ok self.config = config - self.facility = facility.new(config, cooling_conf, check_rtu_id) + self.facility = facility -- initialize connection tracking table self.dev_dbg.connected = { imatrix = nil, sps = nil, tanks = {}, units = {} } @@ -554,4 +553,6 @@ function svsessions.close_all() svsessions.free_all_closed() end +--#endregion + return svsessions diff --git a/supervisor/startup.lua b/supervisor/startup.lua index a89a777..9a567ac 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -16,6 +16,7 @@ local core = require("graphics.core") local configure = require("supervisor.configure") local databus = require("supervisor.databus") +local facility = require("supervisor.facility") local renderer = require("supervisor.renderer") local supervisor = require("supervisor.supervisor") @@ -129,9 +130,12 @@ local function main() println_ts = function (_) end end + -- create facility and unit objects + local sv_facility = facility.new(config) + -- create network interface then setup comms local nic = network.nic(modem) - local superv_comms = supervisor.comms(SUPERVISOR_VERSION, nic, fp_ok) + local superv_comms = supervisor.comms(SUPERVISOR_VERSION, nic, fp_ok, sv_facility) -- base loop clock (6.67Hz, 3 ticks) local MAIN_CLOCK = 0.15 diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 69a98f5..8b06d49 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -102,14 +102,12 @@ end ---@param _version string supervisor version ---@param nic nic network interface device ---@param fp_ok boolean if the front panel UI is running +---@param facility facility facility instance ---@diagnostic disable-next-line: unused-local -function supervisor.comms(_version, nic, fp_ok) +function supervisor.comms(_version, nic, fp_ok, facility) -- print a log message to the terminal as long as the UI isn't running local function println(message) if not fp_ok then util.println_ts(message) end end - ---@class sv_cooling_conf - local cooling_conf = { r_cool = config.CoolingConfig, fac_tank_mode = config.FacilityTankMode, fac_tank_defs = config.FacilityTankDefs } - local self = { last_est_acks = {} } @@ -122,8 +120,8 @@ function supervisor.comms(_version, nic, fp_ok) nic.closeAll() nic.open(config.SVR_Channel) - -- pass modem, status, and config data to svsessions - svsessions.init(nic, fp_ok, config, cooling_conf) + -- pass system data and objects to svsessions + svsessions.init(nic, fp_ok, config, facility) -- send an establish request response ---@param packet scada_packet @@ -373,7 +371,7 @@ function supervisor.comms(_version, nic, fp_ok) println(util.c("CRD (", firmware_v, ") [@", src_addr, "] \xbb connected")) log.info(util.c("CRD_ESTABLISH: coordinator (", firmware_v, ") [@", src_addr, "] connected with session ID ", s_id)) - _send_establish(packet.scada_frame, ESTABLISH_ACK.ALLOW, { config.UnitCount, cooling_conf }) + _send_establish(packet.scada_frame, ESTABLISH_ACK.ALLOW, { config.UnitCount, facility.get_cooling_conf() }) else if last_ack ~= ESTABLISH_ACK.COLLISION then log.info("CRD_ESTABLISH: denied new coordinator [@" .. src_addr .. "] due to already being connected to another coordinator") diff --git a/supervisor/unit.lua b/supervisor/unit.lua index 6f39cb6..3578926 100644 --- a/supervisor/unit.lua +++ b/supervisor/unit.lua @@ -1,12 +1,13 @@ -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 logic = require("supervisor.unitlogic") +local logic = require("supervisor.unitlogic") -local plc = require("supervisor.session.plc") -local rsctl = require("supervisor.session.rsctl") +local plc = require("supervisor.session.plc") +local rsctl = require("supervisor.session.rsctl") +local svsessions = require("supervisor.session.svsessions") local WASTE_MODE = types.WASTE_MODE local WASTE = types.WASTE_PRODUCT @@ -63,9 +64,8 @@ local unit = {} ---@param reactor_id integer reactor unit number ---@param num_boilers integer number of boilers expected ---@param num_turbines integer number of turbines expected ----@param check_rtu_id function ID checking function for RTUs attempting to be linked ---@param ext_idle boolean extended idling mode -function unit.new(reactor_id, num_boilers, num_turbines, check_rtu_id, ext_idle) +function unit.new(reactor_id, num_boilers, num_turbines, ext_idle) -- time (ms) to idle for auto idling local IDLE_TIME = util.trinary(ext_idle, 60000, 10000) @@ -444,7 +444,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, check_rtu_id, ext_idle) ---@param turbine unit_session ---@return boolean linked turbine accepted to associated device slot function public.add_turbine(turbine) - local fail_code, fail_str = check_rtu_id(turbine, self.turbines, num_turbines) + local fail_code, fail_str = svsessions.check_rtu_id(turbine, self.turbines, num_turbines) if fail_code == 0 then table.insert(self.turbines, turbine) @@ -463,7 +463,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, check_rtu_id, ext_idle) ---@param boiler unit_session ---@return boolean linked boiler accepted to associated device slot function public.add_boiler(boiler) - local fail_code, fail_str = check_rtu_id(boiler, self.boilers, num_boilers) + local fail_code, fail_str = svsessions.check_rtu_id(boiler, self.boilers, num_boilers) if fail_code == 0 then table.insert(self.boilers, boiler) @@ -484,7 +484,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, check_rtu_id, ext_idle) ---@param dynamic_tank unit_session ---@return boolean linked dynamic tank accepted (max 1) function public.add_tank(dynamic_tank) - local fail_code, fail_str = check_rtu_id(dynamic_tank, self.tanks, 1) + local fail_code, fail_str = svsessions.check_rtu_id(dynamic_tank, self.tanks, 1) if fail_code == 0 then table.insert(self.tanks, dynamic_tank) @@ -503,7 +503,7 @@ function unit.new(reactor_id, num_boilers, num_turbines, check_rtu_id, ext_idle) ---@param envd unit_session ---@return boolean linked environment detector accepted (max 1) function public.add_envd(envd) - local fail_code, fail_str = check_rtu_id(envd, self.envd, 99) + local fail_code, fail_str = svsessions.check_rtu_id(envd, self.envd, 99) if fail_code == 0 then table.insert(self.envd, envd)