diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua index 64adb88..f0f26c8 100644 --- a/reactor-plc/plc.lua +++ b/reactor-plc/plc.lua @@ -131,7 +131,8 @@ function iss_init(reactor) log._warning("ISS: reactor SCRAM") self.tripped = true self.trip_cause = status - if self.reactor.scram() == ppm.ACCESS_FAULT then + self.reactor.scram() + if self.reactor.__p_is_faulted() then log._error("ISS: failed reactor SCRAM") end end @@ -420,12 +421,14 @@ function comms_init(id, modem, local_port, server_port, reactor, iss) -- disable the reactor self.scrammed = true plc_state.scram = true - _send_ack(packet.type, self.reactor.scram() == ppm.ACCESS_OK) + self.reactor.scram() + _send_ack(packet.type, self.reactor.__p_is_ok()) elseif packet.type == RPLC_TYPES.MEK_ENABLE then -- enable the reactor self.scrammed = false plc_state.scram = false - _send_ack(packet.type, self.reactor.activate() == ppm.ACCESS_OK) + self.reactor.activate() + _send_ack(packet.type, self.reactor.__p_is_ok()) elseif packet.type == RPLC_TYPES.MEK_BURN_RATE then -- set the burn rate local success = false @@ -441,11 +444,12 @@ function comms_init(id, modem, local_port, server_port, reactor, iss) -- if we know our max burn rate, update current burn rate if in range if max_burn_rate ~= ppm.ACCESS_FAULT then if burn_rate > 0 and burn_rate <= max_burn_rate then - success = self.reactor.setBurnRate(burn_rate) + self.reactor.setBurnRate(burn_rate) + success = self.reactor.__p_is_ok() end end - _send_ack(packet.type, success == ppm.ACCESS_OK) + _send_ack(packet.type, success) elseif packet.type == RPLC_TYPES.ISS_CLEAR then -- clear the ISS status iss.reset() diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index 07bb078..7cef958 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -10,7 +10,7 @@ os.loadAPI("scada-common/comms.lua") os.loadAPI("config.lua") os.loadAPI("plc.lua") -local R_PLC_VERSION = "alpha-v0.2.5" +local R_PLC_VERSION = "alpha-v0.2.6" local print = util.print local println = util.println @@ -281,7 +281,8 @@ while true do log._warning("terminate requested, exiting...") if plc_state.init_ok then plc_state.scram = true - if reactor.scram() ~= ppm.ACCESS_FAULT then + reactor.scram() + if reactor.__p_is_ok() then println_ts("reactor disabled") else -- send an alarm: plc_comms.send_alarm(ALARMS.PLC_LOST_CONTROL) ? diff --git a/rtu/startup.lua b/rtu/startup.lua index 42779c6..4534f18 100644 --- a/rtu/startup.lua +++ b/rtu/startup.lua @@ -17,7 +17,7 @@ os.loadAPI("dev/boiler_rtu.lua") os.loadAPI("dev/imatrix_rtu.lua") os.loadAPI("dev/turbine_rtu.lua") -local RTU_VERSION = "alpha-v0.2.3" +local RTU_VERSION = "alpha-v0.2.4" local print = util.print local println = util.println diff --git a/scada-common/ppm.lua b/scada-common/ppm.lua index 66f26a7..f383bae 100644 --- a/scada-common/ppm.lua +++ b/scada-common/ppm.lua @@ -4,14 +4,13 @@ -- Protected Peripheral Manager -- -ACCESS_OK = true ACCESS_FAULT = nil ---------------------------- -- PRIVATE DATA/FUNCTIONS -- ---------------------------- -local self = { +local _ppm_sys = { mounts = {}, auto_cf = false, faulted = false, @@ -20,38 +19,66 @@ local self = { } -- wrap peripheral calls with lua protected call --- ex. reason: we don't want a disconnect to crash the program before a SCRAM -local peri_init = function (device) - for key, func in pairs(device) do - device[key] = function (...) +-- we don't want a disconnect to crash a program +-- also provides peripheral-specific fault checks (auto-clear fault defaults to true) +local peri_init = function (iface) + local self = { + faulted = false, + auto_cf = true, + type = peripheral.getType(iface), + device = peripheral.wrap(iface) + } + + -- initialization process (re-map) + + for key, func in pairs(self.device) do + self.device[key] = function (...) local status, result = pcall(func, ...) if status then -- auto fault clear if self.auto_cf then self.faulted = false end - - -- assume nil is only for functions with no return, so return status - if result == nil then - return ACCESS_OK - else - return result - end + if _ppm_sys.auto_cf then _ppm_sys.faulted = false end + return result else -- function failed self.faulted = true + _ppm_sys.faulted = true - if not mute then + if not _ppm_sys.mute then log._error("PPM: protected " .. key .. "() -> " .. result) end if result == "Terminated" then - self.terminate = true + _ppm_sys.terminate = true end return ACCESS_FAULT end end end + + -- fault management functions + + local clear_fault = function () self.faulted = false end + local is_faulted = function () return self.faulted end + local is_ok = function () return not self.faulted end + + local enable_afc = function () self.auto_cf = true end + local disable_afc = function () self.auto_cf = false end + + -- append to device functions + + self.device.__p_clear_fault = clear_fault + self.device.__p_is_faulted = is_faulted + self.device.__p_is_ok = is_ok + self.device.__p_enable_afc = enable_afc + self.device.__p_disable_afc = disable_afc + + return { + type = self.type, + dev = self.device + } end ---------------------- @@ -62,41 +89,41 @@ end -- silence error prints function disable_reporting() - self.mute = true + _ppm_sys.mute = true end -- allow error prints function enable_reporting() - self.mute = false + _ppm_sys.mute = false end -- FAULT MEMORY -- -- enable automatically clearing fault flag function enable_afc() - self.auto_cf = true + _ppm_sys.auto_cf = true end -- disable automatically clearing fault flag function disable_afc() - self.auto_cf = false + _ppm_sys.auto_cf = false end -- check fault flag function is_faulted() - return self.faulted + return _ppm_sys.faulted end -- clear fault flag function clear_fault() - self.faulted = false + _ppm_sys.faulted = false end -- TERMINATION -- -- if a caught error was a termination request function should_terminate() - return self.terminate + return _ppm_sys.terminate end -- MOUNTING -- @@ -105,18 +132,12 @@ end function mount_all() local ifaces = peripheral.getNames() - self.mounts = {} + _ppm_sys.mounts = {} for i = 1, #ifaces do - local pm_dev = peripheral.wrap(ifaces[i]) - peri_init(pm_dev) + _ppm_sys.mounts[ifaces[i]] = peri_init(ifaces[i]) - self.mounts[ifaces[i]] = { - type = peripheral.getType(ifaces[i]), - dev = pm_dev - } - - log._info("PPM: found a " .. self.mounts[ifaces[i]].type .. " (" .. ifaces[i] .. ")") + log._info("PPM: found a " .. _ppm_sys.mounts[ifaces[i]].type .. " (" .. ifaces[i] .. ")") end if #ifaces == 0 then @@ -128,31 +149,27 @@ end function mount(iface) local ifaces = peripheral.getNames() local pm_dev = nil - local type = nil + local pm_type = nil for i = 1, #ifaces do if iface == ifaces[i] then log._info("PPM: mount(" .. iface .. ") -> found a " .. peripheral.getType(iface)) - type = peripheral.getType(iface) - pm_dev = peripheral.wrap(iface) - peri_init(pm_dev) + _ppm_sys.mounts[iface] = peri_init(iface) - self.mounts[iface] = { - type = peripheral.getType(iface), - dev = pm_dev - } + pm_type = _ppm_sys.mounts[iface].type + pm_dev = _ppm_sys.mounts[iface].dev break end end - return type, pm_dev + return pm_type, pm_dev end -- handle peripheral_detach event function handle_unmount(iface) -- what got disconnected? - local lost_dev = self.mounts[iface] + local lost_dev = _ppm_sys.mounts[iface] if lost_dev then local type = lost_dev.type @@ -173,20 +190,20 @@ end -- list mounted peripherals function list_mounts() - return self.mounts + return _ppm_sys.mounts end -- get a mounted peripheral by side/interface function get_periph(iface) - if self.mounts[iface] then - return self.mounts[iface].dev + if _ppm_sys.mounts[iface] then + return _ppm_sys.mounts[iface].dev else return nil end end -- get a mounted peripheral type by side/interface function get_type(iface) - if self.mounts[iface] then - return self.mounts[iface].type + if _ppm_sys.mounts[iface] then + return _ppm_sys.mounts[iface].type else return nil end end @@ -194,7 +211,7 @@ end function get_all_devices(name) local devices = {} - for side, data in pairs(self.mounts) do + for side, data in pairs(_ppm_sys.mounts) do if data.type == name then table.insert(devices, data.dev) end @@ -207,7 +224,7 @@ end function get_device(name) local device = nil - for side, data in pairs(self.mounts) do + for side, data in pairs(_ppm_sys.mounts) do if data.type == name then device = data.dev break @@ -228,7 +245,7 @@ end function get_wireless_modem() local w_modem = nil - for side, device in pairs(self.mounts) do + for side, device in pairs(_ppm_sys.mounts) do if device.type == "modem" and device.dev.isWireless() then w_modem = device.dev break diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 9fbed9b..91fbacc 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -330,7 +330,7 @@ function new_session(id, for_reactor, in_queue, out_queue) -- handle queue -- ------------------ - if ~self.in_q.empty() then + if not self.in_q.empty() then -- get a new message to process local message = self.in_q.pop() diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 1ad31bb..3395b81 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -17,7 +17,7 @@ os.loadAPI("session/plc.lua") os.loadAPI("session/coordinator.lua") os.loadAPI("session/svsessions.lua") -local SUPERVISOR_VERSION = "alpha-v0.1.2" +local SUPERVISOR_VERSION = "alpha-v0.1.3" local print = util.print local println = util.println