diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 4e7cdb5..a233387 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -386,7 +386,7 @@ function plc.new_session(id, for_reactor, in_queue, out_queue) -- RPS reset acknowledgement local ack = _get_ack(pkt) if ack then - self.acks.rps_tripped = true + self.acks.rps_reset = true self.sDB.rps_tripped = false self.sDB.rps_trip_cause = "ok" elseif ack == false then diff --git a/supervisor/session/rtu/boilerv.lua b/supervisor/session/rtu/boilerv.lua index a7cea55..bd9aaad 100644 --- a/supervisor/session/rtu/boilerv.lua +++ b/supervisor/session/rtu/boilerv.lua @@ -1,6 +1,7 @@ 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") @@ -57,6 +58,7 @@ function boilerv.new(session_id, unit_id, advert, out_queue) db = { formed = false, build = { + last_update = 0, length = 0, width = 0, height = 0, @@ -72,10 +74,12 @@ function boilerv.new(session_id, unit_id, advert, out_queue) env_loss = 0.0 }, state = { + last_update = 0, temperature = 0.0, boil_rate = 0.0 }, tanks = { + last_update = 0, steam = { type = "mekanism:empty_gas", amount = 0 }, ---@type tank_fluid steam_need = 0, steam_fill = 0.0, @@ -140,6 +144,7 @@ function boilerv.new(session_id, unit_id, advert, out_queue) -- build response -- load in data if correct length if m_pkt.length == 13 then + self.db.build.last_update = util.time_ms() self.db.build.length = m_pkt.data[1] self.db.build.width = m_pkt.data[2] self.db.build.height = m_pkt.data[3] @@ -161,6 +166,7 @@ function boilerv.new(session_id, unit_id, advert, out_queue) -- state response -- load in data if correct length if m_pkt.length == 2 then + self.db.state.last_update = util.time_ms() self.db.state.temperature = m_pkt.data[1] self.db.state.boil_rate = m_pkt.data[2] else @@ -170,18 +176,19 @@ function boilerv.new(session_id, unit_id, advert, out_queue) -- 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] + self.db.tanks.last_update = util.time_ms() + 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 diff --git a/supervisor/session/rtu/envd.lua b/supervisor/session/rtu/envd.lua index 93968a9..3050835 100644 --- a/supervisor/session/rtu/envd.lua +++ b/supervisor/session/rtu/envd.lua @@ -1,6 +1,7 @@ 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") @@ -42,6 +43,7 @@ function envd.new(session_id, unit_id, advert, out_queue) }, ---@class envd_session_db db = { + last_update = 0, radiation = {}, radiation_raw = 0 } @@ -68,7 +70,8 @@ function envd.new(session_id, unit_id, advert, out_queue) elseif txn_type == TXN_TYPES.RAD then -- radiation status response if m_pkt.length == 2 then - self.db.radiation = m_pkt.data[1] + self.db.last_update = util.time_ms() + self.db.radiation = m_pkt.data[1] self.db.radiation_raw = m_pkt.data[2] else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") diff --git a/supervisor/session/rtu/imatrix.lua b/supervisor/session/rtu/imatrix.lua index d56be02..fc64b6d 100644 --- a/supervisor/session/rtu/imatrix.lua +++ b/supervisor/session/rtu/imatrix.lua @@ -1,6 +1,7 @@ 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") @@ -57,6 +58,7 @@ function imatrix.new(session_id, unit_id, advert, out_queue) db = { formed = false, build = { + last_update = 0, length = 0, width = 0, height = 0, @@ -68,10 +70,12 @@ function imatrix.new(session_id, unit_id, advert, out_queue) providers = 0 }, state = { + last_update = 0, last_input = 0, last_output = 0 }, tanks = { + last_update = 0, energy = 0, energy_need = 0, energy_fill = 0.0 @@ -127,6 +131,7 @@ function imatrix.new(session_id, unit_id, advert, out_queue) -- build response -- load in data if correct length if m_pkt.length == 9 then + self.db.build.last_update = util.time_ms() self.db.build.length = m_pkt.data[1] self.db.build.width = m_pkt.data[2] self.db.build.height = m_pkt.data[3] @@ -144,6 +149,7 @@ function imatrix.new(session_id, unit_id, advert, out_queue) -- state response -- load in data if correct length if m_pkt.length == 2 then + self.db.state.last_update = util.time_ms() self.db.state.last_input = m_pkt.data[1] self.db.state.last_output = m_pkt.data[2] else @@ -153,6 +159,7 @@ function imatrix.new(session_id, unit_id, advert, out_queue) -- tanks response -- load in data if correct length if m_pkt.length == 3 then + self.db.tanks.last_update = util.time_ms() self.db.tanks.energy = m_pkt.data[1] self.db.tanks.energy_need = m_pkt.data[2] self.db.tanks.energy_fill = m_pkt.data[3] diff --git a/supervisor/session/rtu/sna.lua b/supervisor/session/rtu/sna.lua index 2d7f885..68f38ae 100644 --- a/supervisor/session/rtu/sna.lua +++ b/supervisor/session/rtu/sna.lua @@ -1,6 +1,7 @@ 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") @@ -52,14 +53,17 @@ function sna.new(session_id, unit_id, advert, out_queue) ---@class sna_session_db db = { build = { + last_update = 0, input_cap = 0, output_cap = 0 }, state = { + last_update = 0, production_rate = 0.0, peak_production = 0.0 }, tanks = { + last_update = 0, input = {}, ---@type tank_fluid input_need = 0, input_fill = 0.0, @@ -104,8 +108,9 @@ function sna.new(session_id, unit_id, advert, out_queue) -- build response -- load in data if correct length if m_pkt.length == 2 then - self.db.build.input_cap = m_pkt.data[1] - self.db.build.output_cap = m_pkt.data[2] + self.db.build.last_update = util.time_ms() + self.db.build.input_cap = m_pkt.data[1] + self.db.build.output_cap = m_pkt.data[2] self.has_build = true else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") @@ -114,6 +119,7 @@ function sna.new(session_id, unit_id, advert, out_queue) -- state response -- load in data if correct length if m_pkt.length == 2 then + self.db.state.last_update = util.time_ms() self.db.state.production_rate = m_pkt.data[1] self.db.state.peak_production = m_pkt.data[2] else @@ -123,6 +129,7 @@ function sna.new(session_id, unit_id, advert, out_queue) -- tanks response -- load in data if correct length if m_pkt.length == 6 then + self.db.tanks.last_update = util.time_ms() self.db.tanks.input = m_pkt.data[1] self.db.tanks.input_need = m_pkt.data[2] self.db.tanks.input_fill = m_pkt.data[3] diff --git a/supervisor/session/rtu/sps.lua b/supervisor/session/rtu/sps.lua index e7a2a58..badad45 100644 --- a/supervisor/session/rtu/sps.lua +++ b/supervisor/session/rtu/sps.lua @@ -1,6 +1,7 @@ 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") @@ -57,6 +58,7 @@ function sps.new(session_id, unit_id, advert, out_queue) db = { formed = false, build = { + last_update = 0, length = 0, width = 0, height = 0, @@ -68,9 +70,11 @@ function sps.new(session_id, unit_id, advert, out_queue) max_energy = 0 }, state = { + last_update = 0, process_rate = 0.0 }, tanks = { + last_update = 0, input = {}, ---@type tank_fluid input_need = 0, input_fill = 0.0, @@ -132,15 +136,16 @@ function sps.new(session_id, unit_id, advert, out_queue) -- build response -- load in data if correct length if m_pkt.length == 9 then - self.db.build.length = m_pkt.data[1] - self.db.build.width = m_pkt.data[2] - self.db.build.height = m_pkt.data[3] - self.db.build.min_pos = m_pkt.data[4] - self.db.build.max_pos = m_pkt.data[5] - self.db.build.coils = m_pkt.data[6] - self.db.build.input_cap = m_pkt.data[7] - self.db.build.output_cap = m_pkt.data[8] - self.db.build.max_energy = m_pkt.data[9] + self.db.build.last_update = util.time_ms() + self.db.build.length = m_pkt.data[1] + self.db.build.width = m_pkt.data[2] + self.db.build.height = m_pkt.data[3] + self.db.build.min_pos = m_pkt.data[4] + self.db.build.max_pos = m_pkt.data[5] + self.db.build.coils = m_pkt.data[6] + self.db.build.input_cap = m_pkt.data[7] + self.db.build.output_cap = m_pkt.data[8] + self.db.build.max_energy = m_pkt.data[9] self.has_build = true else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") @@ -149,6 +154,7 @@ function sps.new(session_id, unit_id, advert, out_queue) -- state response -- load in data if correct length if m_pkt.length == 1 then + self.db.state.last_update = util.time_ms() self.db.state.process_rate = m_pkt.data[1] else log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")") @@ -157,6 +163,7 @@ function sps.new(session_id, unit_id, advert, out_queue) -- tanks response -- load in data if correct length if m_pkt.length == 9 then + self.db.tanks.last_update = util.time_ms() self.db.tanks.input = m_pkt.data[1] self.db.tanks.input_need = m_pkt.data[2] self.db.tanks.input_fill = m_pkt.data[3] diff --git a/supervisor/session/rtu/turbinev.lua b/supervisor/session/rtu/turbinev.lua index 56d43ef..d30733c 100644 --- a/supervisor/session/rtu/turbinev.lua +++ b/supervisor/session/rtu/turbinev.lua @@ -79,6 +79,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue) db = { formed = false, build = { + last_update = 0, length = 0, width = 0, height = 0, @@ -96,12 +97,14 @@ function turbinev.new(session_id, unit_id, advert, out_queue) max_water_output = 0 }, state = { + last_update = 0, flow_rate = 0, prod_rate = 0, steam_input_rate = 0, dumping_mode = DUMPING_MODE.IDLE ---@type DUMPING_MODE }, tanks = { + last_update = 0, steam = { type = "mekanism:empty_gas", amount = 0 }, ---@type tank_fluid steam_need = 0, steam_fill = 0.0, @@ -178,6 +181,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue) elseif txn_type == TXN_TYPES.BUILD then -- build response if m_pkt.length == 15 then + self.db.build.last_update = util.time_ms() self.db.build.length = m_pkt.data[1] self.db.build.width = m_pkt.data[2] self.db.build.height = m_pkt.data[3] @@ -200,6 +204,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue) elseif txn_type == TXN_TYPES.STATE then -- state response if m_pkt.length == 4 then + self.db.state.last_update = util.time_ms() 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] @@ -210,6 +215,7 @@ function turbinev.new(session_id, unit_id, advert, out_queue) elseif txn_type == TXN_TYPES.TANKS then -- tanks response if m_pkt.length == 6 then + self.db.tanks.last_update = util.time_ms() 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] diff --git a/supervisor/session/unit.lua b/supervisor/session/unit.lua index c51586e..b8dcc03 100644 --- a/supervisor/session/unit.lua +++ b/supervisor/session/unit.lua @@ -89,17 +89,20 @@ function unit.new(for_reactor, num_boilers, num_turbines) -- compute a change with respect to time of the given value ---@param key string value key ---@param value number value - local function _compute_dt(key, value) + ---@param time number timestamp for value + local function _compute_dt(key, value, time) if self.deltas[key] then local data = self.deltas[key] - data.dt = (value - data.last_v) / (util.time_s() - data.last_t) + if time ~= data.last_t then + data.dt = (value - data.last_v) / (time - data.last_t) - data.last_v = value - data.last_t = util.time_s() + data.last_v = value + data.last_t = time + end else self.deltas[key] = { - last_t = util.time_s(), + last_t = time, last_v = value, dt = 0.0 } @@ -126,30 +129,36 @@ function unit.new(for_reactor, num_boilers, num_turbines) if self.plc_s ~= nil then local plc_db = self.plc_i.get_db() - _compute_dt(DT_KEYS.ReactorTemp, plc_db.mek_status.temp) - _compute_dt(DT_KEYS.ReactorFuel, plc_db.mek_status.fuel) - _compute_dt(DT_KEYS.ReactorWaste, plc_db.mek_status.waste) - _compute_dt(DT_KEYS.ReactorCCool, plc_db.mek_status.ccool_amnt) - _compute_dt(DT_KEYS.ReactorHCool, plc_db.mek_status.hcool_amnt) + local last_update_s = plc_db.last_status_update / 1000.0 + + _compute_dt(DT_KEYS.ReactorTemp, plc_db.mek_status.temp, last_update_s) + _compute_dt(DT_KEYS.ReactorFuel, plc_db.mek_status.fuel, last_update_s) + _compute_dt(DT_KEYS.ReactorWaste, plc_db.mek_status.waste, last_update_s) + _compute_dt(DT_KEYS.ReactorCCool, plc_db.mek_status.ccool_amnt, last_update_s) + _compute_dt(DT_KEYS.ReactorHCool, plc_db.mek_status.hcool_amnt, last_update_s) end for i = 1, #self.boilers do local boiler = self.boilers[i] ---@type unit_session local db = boiler.get_db() ---@type boilerv_session_db - _compute_dt(DT_KEYS.BoilerWater .. boiler.get_device_idx(), db.tanks.water.amount) - _compute_dt(DT_KEYS.BoilerSteam .. boiler.get_device_idx(), db.tanks.steam.amount) - _compute_dt(DT_KEYS.BoilerCCool .. boiler.get_device_idx(), db.tanks.ccool.amount) - _compute_dt(DT_KEYS.BoilerHCool .. boiler.get_device_idx(), db.tanks.hcool.amount) + local last_update_s = db.tanks.last_update / 1000.0 + + _compute_dt(DT_KEYS.BoilerWater .. boiler.get_device_idx(), db.tanks.water.amount, last_update_s) + _compute_dt(DT_KEYS.BoilerSteam .. boiler.get_device_idx(), db.tanks.steam.amount, last_update_s) + _compute_dt(DT_KEYS.BoilerCCool .. boiler.get_device_idx(), db.tanks.ccool.amount, last_update_s) + _compute_dt(DT_KEYS.BoilerHCool .. boiler.get_device_idx(), db.tanks.hcool.amount, last_update_s) end for i = 1, #self.turbines do local turbine = self.turbines[i] ---@type unit_session local db = turbine.get_db() ---@type turbinev_session_db - _compute_dt(DT_KEYS.TurbineSteam .. turbine.get_device_idx(), db.tanks.steam.amount) + local last_update_s = db.tanks.last_update / 1000.0 + + _compute_dt(DT_KEYS.TurbineSteam .. turbine.get_device_idx(), db.tanks.steam.amount, last_update_s) ---@todo unused currently? - _compute_dt(DT_KEYS.TurbinePower .. turbine.get_device_idx(), db.tanks.energy) + _compute_dt(DT_KEYS.TurbinePower .. turbine.get_device_idx(), db.tanks.energy, last_update_s) end end @@ -182,10 +191,9 @@ function unit.new(for_reactor, num_boilers, num_turbines) self.db.annunciator.ReactorTempHigh = plc_db.mek_status.temp > 1000 self.db.annunciator.ReactorHighDeltaT = _get_dt(DT_KEYS.ReactorTemp) > 100 self.db.annunciator.FuelInputRateLow = _get_dt(DT_KEYS.ReactorFuel) < 0.0 or plc_db.mek_status.fuel_fill <= 0.01 - ---@todo this is catagorized as not urgent, but the >= 0.99 is extremely urgent, revist this (RPS will kick in though) - self.db.annunciator.WasteLineOcclusion = _get_dt(DT_KEYS.ReactorWaste) > 0.0 or plc_db.mek_status.waste_fill >= 0.99 + self.db.annunciator.WasteLineOcclusion = _get_dt(DT_KEYS.ReactorWaste) > 0.0 or plc_db.mek_status.waste_fill >= 0.85 ---@todo this is dependent on setup, i.e. how much coolant is buffered and the turbine setup - self.db.annunciator.HighStartupRate = not plc_db.control_state and plc_db.mek_status.burn_rate > 40 + self.db.annunciator.HighStartupRate = not plc_db.mek_status.status and plc_db.mek_status.burn_rate > 40 end ------------- diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 69cb1fe..7d1fae1 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -13,7 +13,7 @@ local svsessions = require("supervisor.session.svsessions") local config = require("supervisor.config") local supervisor = require("supervisor.supervisor") -local SUPERVISOR_VERSION = "beta-v0.6.2" +local SUPERVISOR_VERSION = "beta-v0.6.3" local print = util.print local println = util.println