mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#445 fixed PPM undefined field logic and improved RTU unit fault handling
This commit is contained in:
parent
d1e4ea586e
commit
79c93f1562
@ -7,7 +7,7 @@ local boilerv_rtu = {}
|
||||
---@param boiler table
|
||||
---@return rtu_device interface, boolean faulted
|
||||
function boilerv_rtu.new(boiler)
|
||||
local unit = rtu.init_unit()
|
||||
local unit = rtu.init_unit(boiler)
|
||||
|
||||
-- disable auto fault clearing
|
||||
boiler.__p_clear_fault()
|
||||
|
@ -7,7 +7,7 @@ local dynamicv_rtu = {}
|
||||
---@param dynamic_tank table
|
||||
---@return rtu_device interface, boolean faulted
|
||||
function dynamicv_rtu.new(dynamic_tank)
|
||||
local unit = rtu.init_unit()
|
||||
local unit = rtu.init_unit(dynamic_tank)
|
||||
|
||||
-- disable auto fault clearing
|
||||
dynamic_tank.__p_clear_fault()
|
||||
|
@ -7,7 +7,7 @@ local envd_rtu = {}
|
||||
---@param envd table
|
||||
---@return rtu_device interface, boolean faulted
|
||||
function envd_rtu.new(envd)
|
||||
local unit = rtu.init_unit()
|
||||
local unit = rtu.init_unit(envd)
|
||||
|
||||
-- disable auto fault clearing
|
||||
envd.__p_clear_fault()
|
||||
|
@ -7,7 +7,7 @@ local imatrix_rtu = {}
|
||||
---@param imatrix table
|
||||
---@return rtu_device interface, boolean faulted
|
||||
function imatrix_rtu.new(imatrix)
|
||||
local unit = rtu.init_unit()
|
||||
local unit = rtu.init_unit(imatrix)
|
||||
|
||||
-- disable auto fault clearing
|
||||
imatrix.__p_clear_fault()
|
||||
|
@ -7,7 +7,7 @@ local sna_rtu = {}
|
||||
---@param sna table
|
||||
---@return rtu_device interface, boolean faulted
|
||||
function sna_rtu.new(sna)
|
||||
local unit = rtu.init_unit()
|
||||
local unit = rtu.init_unit(sna)
|
||||
|
||||
-- disable auto fault clearing
|
||||
sna.__p_clear_fault()
|
||||
|
@ -7,7 +7,7 @@ local sps_rtu = {}
|
||||
---@param sps table
|
||||
---@return rtu_device interface, boolean faulted
|
||||
function sps_rtu.new(sps)
|
||||
local unit = rtu.init_unit()
|
||||
local unit = rtu.init_unit(sps)
|
||||
|
||||
-- disable auto fault clearing
|
||||
sps.__p_clear_fault()
|
||||
|
@ -7,7 +7,7 @@ local turbinev_rtu = {}
|
||||
---@param turbine table
|
||||
---@return rtu_device interface, boolean faulted
|
||||
function turbinev_rtu.new(turbine)
|
||||
local unit = rtu.init_unit()
|
||||
local unit = rtu.init_unit(turbine)
|
||||
|
||||
-- disable auto fault clearing
|
||||
turbine.__p_clear_fault()
|
||||
|
@ -37,12 +37,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = rtu_dev.read_coil(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
readings = MODBUS_EXCODE.SERVER_DEVICE_FAIL
|
||||
break
|
||||
end
|
||||
if access_fault then break end
|
||||
end
|
||||
end
|
||||
|
||||
@ -86,12 +81,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = rtu_dev.read_di(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
readings = MODBUS_EXCODE.SERVER_DEVICE_FAIL
|
||||
break
|
||||
end
|
||||
if access_fault then break end
|
||||
end
|
||||
end
|
||||
|
||||
@ -135,12 +125,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = rtu_dev.read_holding_reg(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
readings = MODBUS_EXCODE.SERVER_DEVICE_FAIL
|
||||
break
|
||||
end
|
||||
if access_fault then break end
|
||||
end
|
||||
end
|
||||
|
||||
@ -184,12 +169,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = rtu_dev.read_input_reg(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
readings = MODBUS_EXCODE.SERVER_DEVICE_FAIL
|
||||
break
|
||||
end
|
||||
if access_fault then break end
|
||||
end
|
||||
end
|
||||
|
||||
|
28
rtu/rtu.lua
28
rtu/rtu.lua
@ -67,9 +67,11 @@ function rtu.load_config()
|
||||
return cfv.valid()
|
||||
end
|
||||
|
||||
-- create a new RTU unit
|
||||
-- create a new RTU unit<br>
|
||||
-- if this is for a PPM peripheral, auto fault clearing MUST stay enabled once access begins
|
||||
---@nodiscard
|
||||
function rtu.init_unit()
|
||||
---@param device table|nil peripheral device, if applicable
|
||||
function rtu.init_unit(device)
|
||||
local self = {
|
||||
discrete_inputs = {},
|
||||
coils = {},
|
||||
@ -86,6 +88,10 @@ function rtu.init_unit()
|
||||
---@class rtu
|
||||
local protected = {}
|
||||
|
||||
-- function to check if the peripheral (if exists) is faulted
|
||||
local function _is_faulted() return false end
|
||||
if device then _is_faulted = device.__p_is_faulted end
|
||||
|
||||
-- refresh IO count
|
||||
local function _count_io()
|
||||
self.io_count_cache = { #self.discrete_inputs, #self.coils, #self.input_regs, #self.holding_regs }
|
||||
@ -112,9 +118,8 @@ function rtu.init_unit()
|
||||
---@param di_addr integer
|
||||
---@return any value, boolean access_fault
|
||||
function public.read_di(di_addr)
|
||||
ppm.clear_fault()
|
||||
local value = self.discrete_inputs[di_addr].read()
|
||||
return value, ppm.is_faulted()
|
||||
return value, _is_faulted()
|
||||
end
|
||||
|
||||
-- coils: single bit read-write
|
||||
@ -133,9 +138,8 @@ function rtu.init_unit()
|
||||
---@param coil_addr integer
|
||||
---@return any value, boolean access_fault
|
||||
function public.read_coil(coil_addr)
|
||||
ppm.clear_fault()
|
||||
local value = self.coils[coil_addr].read()
|
||||
return value, ppm.is_faulted()
|
||||
return value, _is_faulted()
|
||||
end
|
||||
|
||||
-- write coil
|
||||
@ -143,9 +147,8 @@ function rtu.init_unit()
|
||||
---@param value any
|
||||
---@return boolean access_fault
|
||||
function public.write_coil(coil_addr, value)
|
||||
ppm.clear_fault()
|
||||
self.coils[coil_addr].write(value)
|
||||
return ppm.is_faulted()
|
||||
return _is_faulted()
|
||||
end
|
||||
|
||||
-- input registers: multi-bit read-only
|
||||
@ -163,9 +166,8 @@ function rtu.init_unit()
|
||||
---@param reg_addr integer
|
||||
---@return any value, boolean access_fault
|
||||
function public.read_input_reg(reg_addr)
|
||||
ppm.clear_fault()
|
||||
local value = self.input_regs[reg_addr].read()
|
||||
return value, ppm.is_faulted()
|
||||
return value, _is_faulted()
|
||||
end
|
||||
|
||||
-- holding registers: multi-bit read-write
|
||||
@ -184,9 +186,8 @@ function rtu.init_unit()
|
||||
---@param reg_addr integer
|
||||
---@return any value, boolean access_fault
|
||||
function public.read_holding_reg(reg_addr)
|
||||
ppm.clear_fault()
|
||||
local value = self.holding_regs[reg_addr].read()
|
||||
return value, ppm.is_faulted()
|
||||
return value, _is_faulted()
|
||||
end
|
||||
|
||||
-- write holding register
|
||||
@ -194,9 +195,8 @@ function rtu.init_unit()
|
||||
---@param value any
|
||||
---@return boolean access_fault
|
||||
function public.write_holding_reg(reg_addr, value)
|
||||
ppm.clear_fault()
|
||||
self.holding_regs[reg_addr].write(value)
|
||||
return ppm.is_faulted()
|
||||
return _is_faulted()
|
||||
end
|
||||
|
||||
-- public RTU device access
|
||||
|
@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu")
|
||||
local sps_rtu = require("rtu.dev.sps_rtu")
|
||||
local turbinev_rtu = require("rtu.dev.turbinev_rtu")
|
||||
|
||||
local RTU_VERSION = "v1.7.14"
|
||||
local RTU_VERSION = "v1.7.15"
|
||||
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
||||
|
@ -131,31 +131,33 @@ local function peri_init(iface)
|
||||
|
||||
local mt = {
|
||||
__index = function (_, key)
|
||||
-- this will continuously be counting calls here as faults
|
||||
-- unlike other functions, faults here can't be cleared as it is just not defined
|
||||
if self.fault_counts[key] == nil then
|
||||
self.fault_counts[key] = 0
|
||||
end
|
||||
|
||||
-- function failed
|
||||
self.faulted = true
|
||||
self.last_fault = UNDEFINED_FIELD
|
||||
|
||||
ppm_sys.faulted = true
|
||||
ppm_sys.last_fault = UNDEFINED_FIELD
|
||||
|
||||
if not ppm_sys.mute and (self.fault_counts[key] % REPORT_FREQUENCY == 0) then
|
||||
local count_str = ""
|
||||
if self.fault_counts[key] > 0 then
|
||||
count_str = " [" .. self.fault_counts[key] .. " total calls]"
|
||||
return (function ()
|
||||
-- this will continuously be counting calls here as faults
|
||||
-- unlike other functions, faults here can't be cleared as it is just not defined
|
||||
if self.fault_counts[key] == nil then
|
||||
self.fault_counts[key] = 0
|
||||
end
|
||||
|
||||
log.error(util.c("PPM: caught undefined function ", key, "()", count_str))
|
||||
end
|
||||
-- function failed
|
||||
self.faulted = true
|
||||
self.last_fault = UNDEFINED_FIELD
|
||||
|
||||
self.fault_counts[key] = self.fault_counts[key] + 1
|
||||
ppm_sys.faulted = true
|
||||
ppm_sys.last_fault = UNDEFINED_FIELD
|
||||
|
||||
return (function () return UNDEFINED_FIELD end)
|
||||
if not ppm_sys.mute and (self.fault_counts[key] % REPORT_FREQUENCY == 0) then
|
||||
local count_str = ""
|
||||
if self.fault_counts[key] > 0 then
|
||||
count_str = " [" .. self.fault_counts[key] .. " total calls]"
|
||||
end
|
||||
|
||||
log.error(util.c("PPM: caught undefined function ", key, "()", count_str))
|
||||
end
|
||||
|
||||
self.fault_counts[key] = self.fault_counts[key] + 1
|
||||
|
||||
return UNDEFINED_FIELD
|
||||
end)
|
||||
end
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user