#498 pocket facility scram and ack all alarms
This commit is contained in:
@@ -11,6 +11,7 @@ local pocket = {}
|
|||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local CRDN_TYPE = comms.CRDN_TYPE
|
local CRDN_TYPE = comms.CRDN_TYPE
|
||||||
local MGMT_TYPE = comms.MGMT_TYPE
|
local MGMT_TYPE = comms.MGMT_TYPE
|
||||||
|
local FAC_COMMAND = comms.FAC_COMMAND
|
||||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||||
|
|
||||||
-- retry time constants in ms
|
-- retry time constants in ms
|
||||||
@@ -39,7 +40,7 @@ local PERIODICS = {
|
|||||||
---@param out_queue mqueue out message queue
|
---@param out_queue mqueue out message queue
|
||||||
---@param timeout number communications timeout
|
---@param timeout number communications timeout
|
||||||
function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
||||||
local log_header = "pkt_session(" .. id .. "): "
|
local log_tag = "pkt_session(" .. id .. "): "
|
||||||
|
|
||||||
local self = {
|
local self = {
|
||||||
-- connection properties
|
-- connection properties
|
||||||
@@ -106,6 +107,10 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- link callback transmissions
|
-- link callback transmissions
|
||||||
|
|
||||||
|
self.proc_handle.fac_ack.on_scram = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.SCRAM, success }) end
|
||||||
|
self.proc_handle.fac_ack.on_ack_alarms = function (success) _send(CRDN_TYPE.FAC_CMD, { FAC_COMMAND.ACK_ALL_ALARMS, success }) end
|
||||||
|
|
||||||
for u = 1, iocontrol.get_db().facility.num_units do
|
for u = 1, iocontrol.get_db().facility.num_units do
|
||||||
self.proc_handle.unit_ack[u].on_start = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.START, u, success }) end
|
self.proc_handle.unit_ack[u].on_start = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.START, u, success }) end
|
||||||
self.proc_handle.unit_ack[u].on_scram = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.SCRAM, u, success }) end
|
self.proc_handle.unit_ack[u].on_scram = function (success) _send(CRDN_TYPE.UNIT_CMD, { UNIT_COMMAND.SCRAM, u, success }) end
|
||||||
@@ -118,7 +123,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
local function _handle_packet(pkt)
|
local function _handle_packet(pkt)
|
||||||
-- check sequence number
|
-- check sequence number
|
||||||
if self.r_seq_num ~= pkt.scada_frame.seq_num() then
|
if self.r_seq_num ~= pkt.scada_frame.seq_num() then
|
||||||
log.warning(log_header .. "sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num())
|
log.warning(log_tag .. "sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num())
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
self.r_seq_num = pkt.scada_frame.seq_num() + 1
|
self.r_seq_num = pkt.scada_frame.seq_num() + 1
|
||||||
@@ -134,7 +139,28 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
local db = iocontrol.get_db()
|
local db = iocontrol.get_db()
|
||||||
|
|
||||||
-- handle packet by type
|
-- handle packet by type
|
||||||
if pkt.type == CRDN_TYPE.UNIT_CMD then
|
if pkt.type == CRDN_TYPE.FAC_CMD then
|
||||||
|
if pkt.length >= 1 then
|
||||||
|
local cmd = pkt.data[1]
|
||||||
|
|
||||||
|
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||||
|
log.info(log_tag .. "FAC SCRAM ALL")
|
||||||
|
self.proc_handle.fac_scram()
|
||||||
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
|
elseif cmd == FAC_COMMAND.START then
|
||||||
|
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||||
|
log.info(log_tag .. "FAC ACK ALL ALARMS")
|
||||||
|
self.proc_handle.fac_ack_alarms()
|
||||||
|
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||||
|
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||||
|
elseif cmd == FAC_COMMAND.SET_SPS_LP then
|
||||||
|
else
|
||||||
|
log.debug(log_tag .. "CRDN facility command unknown")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
log.debug(log_tag .. "CRDN facility command packet length mismatch")
|
||||||
|
end
|
||||||
|
elseif pkt.type == CRDN_TYPE.UNIT_CMD then
|
||||||
if pkt.length >= 2 then
|
if pkt.length >= 2 then
|
||||||
-- get command and unit id
|
-- get command and unit id
|
||||||
local cmd = pkt.data[1]
|
local cmd = pkt.data[1]
|
||||||
@@ -143,56 +169,36 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
-- continue if valid unit id
|
-- continue if valid unit id
|
||||||
if util.is_int(uid) and uid > 0 and uid <= #db.units then
|
if util.is_int(uid) and uid > 0 and uid <= #db.units then
|
||||||
if cmd == UNIT_COMMAND.START then
|
if cmd == UNIT_COMMAND.START then
|
||||||
log.info(util.c(log_header, "UNIT[", uid, "] START"))
|
log.info(util.c(log_tag, "UNIT[", uid, "] START"))
|
||||||
self.proc_handle.start(uid)
|
self.proc_handle.start(uid)
|
||||||
elseif cmd == UNIT_COMMAND.SCRAM then
|
elseif cmd == UNIT_COMMAND.SCRAM then
|
||||||
log.info(util.c(log_header, "UNIT[", uid, "] SCRAM"))
|
log.info(util.c(log_tag, "UNIT[", uid, "] SCRAM"))
|
||||||
self.proc_handle.scram(uid)
|
self.proc_handle.scram(uid)
|
||||||
elseif cmd == UNIT_COMMAND.RESET_RPS then
|
elseif cmd == UNIT_COMMAND.RESET_RPS then
|
||||||
log.info(util.c(log_header, "UNIT[", uid, "] RESET RPS"))
|
log.info(util.c(log_tag, "UNIT[", uid, "] RESET RPS"))
|
||||||
self.proc_handle.reset_rps(uid)
|
self.proc_handle.reset_rps(uid)
|
||||||
elseif cmd == UNIT_COMMAND.SET_BURN then
|
elseif cmd == UNIT_COMMAND.SET_BURN then
|
||||||
if pkt.length == 3 then
|
if pkt.length == 3 then
|
||||||
log.info(util.c(log_header, "UNIT[", uid, "] SET BURN ", pkt.data[3]))
|
log.info(util.c(log_tag, "UNIT[", uid, "] SET BURN ", pkt.data[3]))
|
||||||
process.set_rate(uid, pkt.data[3])
|
process.set_rate(uid, pkt.data[3])
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command burn rate missing option")
|
log.debug(log_tag .. "CRDN unit command burn rate missing option")
|
||||||
end
|
end
|
||||||
elseif cmd == UNIT_COMMAND.SET_WASTE then
|
elseif cmd == UNIT_COMMAND.SET_WASTE then
|
||||||
-- if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] > 0) and (pkt.data[3] <= 4) then
|
|
||||||
-- process.set_unit_waste(uid, pkt.data[3])
|
|
||||||
-- else
|
|
||||||
-- log.debug(log_header .. "CRDN unit command set waste missing/invalid option")
|
|
||||||
-- end
|
|
||||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||||
log.info(util.c(log_header, "UNIT[", uid, "] ACK ALL ALARMS"))
|
log.info(util.c(log_tag, "UNIT[", uid, "] ACK ALL ALARMS"))
|
||||||
self.proc_handle.ack_all_alarms(uid)
|
self.proc_handle.ack_all_alarms(uid)
|
||||||
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
||||||
-- if pkt.length == 3 then
|
|
||||||
-- process.ack_alarm(uid, pkt.data[3])
|
|
||||||
-- else
|
|
||||||
-- log.debug(log_header .. "CRDN unit command ack alarm missing alarm id")
|
|
||||||
-- end
|
|
||||||
elseif cmd == UNIT_COMMAND.RESET_ALARM then
|
elseif cmd == UNIT_COMMAND.RESET_ALARM then
|
||||||
-- if pkt.length == 3 then
|
|
||||||
-- process.reset_alarm(uid, pkt.data[3])
|
|
||||||
-- else
|
|
||||||
-- log.debug(log_header .. "CRDN unit command reset alarm missing alarm id")
|
|
||||||
-- end
|
|
||||||
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
||||||
-- if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] >= 0) and (pkt.data[3] <= 4) then
|
|
||||||
-- process.set_group(uid, pkt.data[3])
|
|
||||||
-- else
|
|
||||||
-- log.debug(log_header .. "CRDN unit command set group missing group id")
|
|
||||||
-- end
|
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command unknown")
|
log.debug(log_tag .. "CRDN unit command unknown")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command invalid")
|
log.debug(log_tag .. "CRDN unit command invalid")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN unit command packet length mismatch")
|
log.debug(log_tag .. "CRDN unit command packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == CRDN_TYPE.API_GET_FAC then
|
elseif pkt.type == CRDN_TYPE.API_GET_FAC then
|
||||||
local fac = db.facility
|
local fac = db.facility
|
||||||
@@ -232,7 +238,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "handler received unsupported CRDN packet type " .. pkt.type)
|
log.debug(log_tag .. "handler received unsupported CRDN packet type " .. pkt.type)
|
||||||
end
|
end
|
||||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast pkt mgmt_frame
|
---@cast pkt mgmt_frame
|
||||||
@@ -245,7 +251,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
self.last_rtt = srv_now - srv_start
|
self.last_rtt = srv_now - srv_start
|
||||||
|
|
||||||
if self.last_rtt > 750 then
|
if self.last_rtt > 750 then
|
||||||
log.warning(log_header .. "PKT KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)")
|
log.warning(log_tag .. "PKT KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- log.debug(log_header .. "PKT RTT = " .. self.last_rtt .. "ms")
|
-- log.debug(log_header .. "PKT RTT = " .. self.last_rtt .. "ms")
|
||||||
@@ -253,7 +259,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
iocontrol.fp_pkt_rtt(id, self.last_rtt)
|
iocontrol.fp_pkt_rtt(id, self.last_rtt)
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_tag .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
@@ -261,9 +267,9 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
elseif pkt.type == MGMT_TYPE.ESTABLISH then
|
elseif pkt.type == MGMT_TYPE.ESTABLISH then
|
||||||
-- something is wrong, kill the session
|
-- something is wrong, kill the session
|
||||||
_close()
|
_close()
|
||||||
log.warning(log_header .. "terminated session due to an unexpected ESTABLISH packet")
|
log.warning(log_tag .. "terminated session due to an unexpected ESTABLISH packet")
|
||||||
else
|
else
|
||||||
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
log.debug(log_tag .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -288,7 +294,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_tag .. "session closed by server")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- iterate the session
|
-- iterate the session
|
||||||
@@ -319,14 +325,14 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
-- max 100ms spent processing queue
|
-- max 100ms spent processing queue
|
||||||
if util.time() - handle_start > 100 then
|
if util.time() - handle_start > 100 then
|
||||||
log.warning(log_header .. "exceeded 100ms queue process limit")
|
log.warning(log_tag .. "exceeded 100ms queue process limit")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- exit if connection was closed
|
-- exit if connection was closed
|
||||||
if not self.connected then
|
if not self.connected then
|
||||||
log.info(log_header .. "session closed by remote host")
|
log.info(log_tag .. "session closed by remote host")
|
||||||
return self.connected
|
return self.connected
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,11 @@ function iocontrol.init_fac(conf)
|
|||||||
|
|
||||||
radiation = types.new_zero_radiation_reading(),
|
radiation = types.new_zero_radiation_reading(),
|
||||||
|
|
||||||
|
start_ack = __generic_ack,
|
||||||
|
stop_ack = __generic_ack,
|
||||||
|
scram_ack = __generic_ack,
|
||||||
|
ack_alarms_ack = __generic_ack,
|
||||||
|
|
||||||
ps = psil.create(),
|
ps = psil.create(),
|
||||||
|
|
||||||
induction_ps_tbl = {},
|
induction_ps_tbl = {},
|
||||||
|
|||||||
@@ -654,7 +654,28 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
|||||||
if protocol == PROTOCOL.SCADA_CRDN then
|
if protocol == PROTOCOL.SCADA_CRDN then
|
||||||
---@cast packet crdn_frame
|
---@cast packet crdn_frame
|
||||||
if self.api.linked then
|
if self.api.linked then
|
||||||
if packet.type == CRDN_TYPE.UNIT_CMD then
|
if packet.type == CRDN_TYPE.FAC_CMD then
|
||||||
|
-- facility command acknowledgement
|
||||||
|
if packet.length >= 2 then
|
||||||
|
local cmd = packet.data[1]
|
||||||
|
local ack = packet.data[2] == true
|
||||||
|
|
||||||
|
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||||
|
iocontrol.get_db().facility.scram_ack(ack)
|
||||||
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
|
elseif cmd == FAC_COMMAND.START then
|
||||||
|
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||||
|
iocontrol.get_db().facility.ack_alarms_ack(ack)
|
||||||
|
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||||
|
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||||
|
elseif cmd == FAC_COMMAND.SET_SPS_LP then
|
||||||
|
else
|
||||||
|
log.debug(util.c("received facility command ack with unknown command ", cmd))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
log.debug("SCADA_CRDN facility command ack packet length mismatch")
|
||||||
|
end
|
||||||
|
elseif packet.type == CRDN_TYPE.UNIT_CMD then
|
||||||
-- unit command acknowledgement
|
-- unit command acknowledgement
|
||||||
if packet.length == 3 then
|
if packet.length == 3 then
|
||||||
local cmd = packet.data[1]
|
local cmd = packet.data[1]
|
||||||
@@ -670,16 +691,10 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav)
|
|||||||
unit.start_ack(ack)
|
unit.start_ack(ack)
|
||||||
elseif cmd == UNIT_COMMAND.RESET_RPS then
|
elseif cmd == UNIT_COMMAND.RESET_RPS then
|
||||||
unit.reset_rps_ack(ack)
|
unit.reset_rps_ack(ack)
|
||||||
elseif cmd == UNIT_COMMAND.SET_BURN then
|
|
||||||
-- this also doesn't exist
|
|
||||||
elseif cmd == UNIT_COMMAND.SET_WASTE then
|
|
||||||
-- updated by unit updates
|
|
||||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||||
unit.ack_alarms_ack(ack)
|
unit.ack_alarms_ack(ack)
|
||||||
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
|
||||||
-- updated by unit updates
|
|
||||||
else
|
else
|
||||||
log.debug(util.c("received unit command ack with unknown command ", cmd))
|
log.debug(util.c("received unsupported unit command ack for command ", cmd))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ local util = require("scada-common.util")
|
|||||||
|
|
||||||
local iocontrol = require("pocket.iocontrol")
|
local iocontrol = require("pocket.iocontrol")
|
||||||
local pocket = require("pocket.pocket")
|
local pocket = require("pocket.pocket")
|
||||||
|
local process = require("pocket.process")
|
||||||
|
|
||||||
local style = require("pocket.ui.style")
|
local style = require("pocket.ui.style")
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
|
|
||||||
local Div = require("graphics.elements.div")
|
local Div = require("graphics.elements.div")
|
||||||
local ListBox = require("graphics.elements.listbox")
|
|
||||||
local MultiPane = require("graphics.elements.multipane")
|
local MultiPane = require("graphics.elements.multipane")
|
||||||
local TextBox = require("graphics.elements.textbox")
|
local TextBox = require("graphics.elements.textbox")
|
||||||
|
|
||||||
@@ -77,6 +77,7 @@ local function new_view(root)
|
|||||||
local function set_sidebar()
|
local function set_sidebar()
|
||||||
local list = {
|
local list = {
|
||||||
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end },
|
{ label = " # ", tall = true, color = core.cpair(colors.black, colors.green), callback = function () db.nav.open_app(APP_ID.ROOT) end },
|
||||||
|
{ label = "FAC", color = core.cpair(colors.black, colors.orange), callback = function () app.switcher(db.facility.num_units + 1) end }
|
||||||
}
|
}
|
||||||
|
|
||||||
for i = 1, db.facility.num_units do
|
for i = 1, db.facility.num_units do
|
||||||
@@ -95,7 +96,7 @@ local function new_view(root)
|
|||||||
local active_unit = 1
|
local active_unit = 1
|
||||||
|
|
||||||
-- create all page divs
|
-- create all page divs
|
||||||
for _ = 1, db.facility.num_units do
|
for _ = 1, db.facility.num_units + 1 do
|
||||||
local div = Div{parent=page_div}
|
local div = Div{parent=page_div}
|
||||||
table.insert(panes, div)
|
table.insert(panes, div)
|
||||||
end
|
end
|
||||||
@@ -188,6 +189,21 @@ local function new_view(root)
|
|||||||
util.nop()
|
util.nop()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- facility controls
|
||||||
|
|
||||||
|
local f_pane = panes[db.facility.num_units + 1]
|
||||||
|
local f_div = Div{parent=f_pane,x=2,width=main.get_width()-2}
|
||||||
|
|
||||||
|
app.new_page(nil, db.facility.num_units + 1)
|
||||||
|
|
||||||
|
TextBox{parent=f_div,y=1,text="Facility Commands",alignment=ALIGN.CENTER}
|
||||||
|
|
||||||
|
local scram = HazardButton{parent=f_div,x=5,y=6,text="FAC SCRAM",accent=colors.yellow,dis_colors=dis_colors,callback=process.fac_scram,fg_bg=hzd_fg_bg}
|
||||||
|
local ack_a = HazardButton{parent=f_div,x=7,y=11,text="ACK \x13",accent=colors.orange,dis_colors=dis_colors,callback=process.fac_ack_alarms,fg_bg=hzd_fg_bg}
|
||||||
|
|
||||||
|
db.facility.scram_ack = scram.on_response
|
||||||
|
db.facility.ack_alarms_ack = ack_a.on_response
|
||||||
|
|
||||||
-- setup multipane
|
-- setup multipane
|
||||||
local u_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes}
|
local u_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes}
|
||||||
app.set_root_pane(u_pane)
|
app.set_root_pane(u_pane)
|
||||||
|
|||||||
Reference in New Issue
Block a user