mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
Merge pull request #341 from MikaylaFischler/300-code-footprint-cleanup-tasks
300 code footprint cleanup tasks
This commit is contained in:
commit
b9073153b3
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -24,6 +24,7 @@
|
||||
},
|
||||
"Lua.hint.setType": true,
|
||||
"Lua.diagnostics.disable": [
|
||||
"duplicate-set-field"
|
||||
"duplicate-set-field",
|
||||
"inject-field"
|
||||
]
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ local println = util.println
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local CRDN_TYPE = comms.CRDN_TYPE
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
local FAC_COMMAND = comms.FAC_COMMAND
|
||||
|
||||
@ -279,7 +279,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
apisessions.init(nic)
|
||||
|
||||
-- send a packet to the supervisor
|
||||
---@param msg_type SCADA_MGMT_TYPE|SCADA_CRDN_TYPE
|
||||
---@param msg_type MGMT_TYPE|CRDN_TYPE
|
||||
---@param msg table
|
||||
local function _send_sv(protocol, msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -307,7 +307,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
local s_pkt = comms.scada_packet()
|
||||
local m_pkt = comms.mgmt_packet()
|
||||
|
||||
m_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, { ack })
|
||||
m_pkt.make(MGMT_TYPE.ESTABLISH, { ack })
|
||||
s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||
|
||||
nic.transmit(pkt_channel, crd_channel, s_pkt)
|
||||
@ -316,13 +316,13 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
|
||||
-- attempt connection establishment
|
||||
local function _send_establish()
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.CRDN })
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.CRD })
|
||||
end
|
||||
|
||||
-- keep alive ack
|
||||
---@param srv_time integer
|
||||
local function _send_keep_alive_ack(srv_time)
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -394,20 +394,20 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
self.sv_linked = false
|
||||
self.sv_r_seq_num = nil
|
||||
iocontrol.fp_link_state(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_sv(PROTOCOL.SCADA_MGMT, MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- send a facility command
|
||||
---@param cmd FAC_COMMAND command
|
||||
---@param option any? optional option options for the optional options (like waste mode)
|
||||
function public.send_fac_command(cmd, option)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, { cmd, option })
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_CMD, { cmd, option })
|
||||
end
|
||||
|
||||
-- send the auto process control configuration with a start command
|
||||
---@param config coord_auto_config configuration
|
||||
function public.send_auto_start(config)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_CMD, {
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_CMD, {
|
||||
FAC_COMMAND.START, config.mode, config.burn_target, config.charge_target, config.gen_target, config.limits
|
||||
})
|
||||
end
|
||||
@ -417,7 +417,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
---@param unit integer unit ID
|
||||
---@param option any? optional option options for the optional options (like burn rate)
|
||||
function public.send_unit_command(cmd, unit, option)
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_CMD, { cmd, unit, option })
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.UNIT_CMD, { cmd, unit, option })
|
||||
end
|
||||
|
||||
-- parse a packet
|
||||
@ -426,7 +426,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
---@param reply_to integer
|
||||
---@param message any
|
||||
---@param distance integer
|
||||
---@return mgmt_frame|crdn_frame|capi_frame|nil packet
|
||||
---@return mgmt_frame|crdn_frame|nil packet
|
||||
function public.parse_packet(side, sender, reply_to, message, distance)
|
||||
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
||||
local pkt = nil
|
||||
@ -444,12 +444,6 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
if crdn_pkt.decode(s_pkt) then
|
||||
pkt = crdn_pkt.get()
|
||||
end
|
||||
-- get as coordinator API packet
|
||||
elseif s_pkt.protocol() == PROTOCOL.COORD_API then
|
||||
local capi_pkt = comms.capi_packet()
|
||||
if capi_pkt.decode(s_pkt) then
|
||||
pkt = capi_pkt.get()
|
||||
end
|
||||
else
|
||||
log.debug("attempted parse of illegal packet type " .. s_pkt.protocol(), true)
|
||||
end
|
||||
@ -459,7 +453,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
---@param packet mgmt_frame|crdn_frame|capi_frame|nil
|
||||
---@param packet mgmt_frame|crdn_frame|nil
|
||||
---@return boolean close_ui
|
||||
function public.handle_packet(packet)
|
||||
local was_linked = self.sv_linked
|
||||
@ -475,18 +469,18 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
elseif r_chan == pkt_channel then
|
||||
if not self.sv_linked then
|
||||
log.debug("discarding pocket API packet before linked to supervisor")
|
||||
elseif protocol == PROTOCOL.COORD_API then
|
||||
---@cast packet capi_frame
|
||||
elseif protocol == PROTOCOL.SCADA_CRDN then
|
||||
---@cast packet crdn_frame
|
||||
-- look for an associated session
|
||||
local session = apisessions.find_session(src_addr)
|
||||
|
||||
-- API packet
|
||||
-- coordinator packet
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
else
|
||||
-- any other packet should be session related, discard it
|
||||
log.debug("discarding COORD_API packet without a known session")
|
||||
log.debug("discarding SCADA_CRDN packet without a known session")
|
||||
end
|
||||
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
@ -497,7 +491,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
-- validate packet and continue
|
||||
if packet.length == 3 and type(packet.data[1]) == "string" and type(packet.data[2]) == "string" then
|
||||
@ -553,7 +547,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
if protocol == PROTOCOL.SCADA_CRDN then
|
||||
---@cast packet crdn_frame
|
||||
if self.sv_linked then
|
||||
if packet.type == SCADA_CRDN_TYPE.INITIAL_BUILDS then
|
||||
if packet.type == CRDN_TYPE.INITIAL_BUILDS then
|
||||
if packet.length == 2 then
|
||||
-- record builds
|
||||
local fac_builds = iocontrol.record_facility_builds(packet.data[1])
|
||||
@ -561,31 +555,31 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
|
||||
if fac_builds and unit_builds then
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.INITIAL_BUILDS, {})
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.INITIAL_BUILDS, {})
|
||||
else
|
||||
log.debug("received invalid INITIAL_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("INITIAL_BUILDS packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_BUILDS then
|
||||
elseif packet.type == CRDN_TYPE.FAC_BUILDS then
|
||||
if packet.length == 1 then
|
||||
-- record facility builds
|
||||
if iocontrol.record_facility_builds(packet.data[1]) then
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_BUILDS, {})
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_BUILDS, {})
|
||||
else
|
||||
log.debug("received invalid FAC_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("FAC_BUILDS packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_STATUS then
|
||||
elseif packet.type == CRDN_TYPE.FAC_STATUS then
|
||||
-- update facility status
|
||||
if not iocontrol.update_facility_status(packet.data) then
|
||||
log.debug("received invalid FAC_STATUS packet")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_CMD then
|
||||
elseif packet.type == CRDN_TYPE.FAC_CMD then
|
||||
-- facility command acknowledgement
|
||||
if packet.length >= 2 then
|
||||
local cmd = packet.data[1]
|
||||
@ -613,24 +607,24 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
else
|
||||
log.debug("SCADA_CRDN facility command ack packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
||||
elseif packet.type == CRDN_TYPE.UNIT_BUILDS then
|
||||
-- record builds
|
||||
if packet.length == 1 then
|
||||
if iocontrol.record_unit_builds(packet.data[1]) then
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_BUILDS, {})
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.UNIT_BUILDS, {})
|
||||
else
|
||||
log.debug("received invalid UNIT_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("UNIT_BUILDS packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_STATUSES then
|
||||
elseif packet.type == CRDN_TYPE.UNIT_STATUSES then
|
||||
-- update statuses
|
||||
if not iocontrol.update_unit_statuses(packet.data) then
|
||||
log.debug("received invalid UNIT_STATUSES packet")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_CMD then
|
||||
elseif packet.type == CRDN_TYPE.UNIT_CMD then
|
||||
-- unit command acknowledgement
|
||||
if packet.length == 3 then
|
||||
local cmd = packet.data[1]
|
||||
@ -672,7 +666,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
if self.sv_linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 then
|
||||
local timestamp = packet.data[1]
|
||||
@ -690,7 +684,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
else
|
||||
log.debug("SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
sv_watchdog.cancel()
|
||||
self.sv_addr = comms.BROADCAST
|
||||
@ -701,7 +695,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
||||
else
|
||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type)
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- connection with supervisor established
|
||||
if packet.length == 2 then
|
||||
local est_ack = packet.data[1]
|
||||
|
@ -8,8 +8,8 @@ local iocontrol = require("coordinator.iocontrol")
|
||||
local pocket = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
-- local CAPI_TYPE = comms.CAPI_TYPE
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
-- local CRDN_TYPE = comms.CRDN_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
-- retry time constants in ms
|
||||
-- local INITIAL_WAIT = 1500
|
||||
@ -72,22 +72,22 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
iocontrol.fp_pkt_disconnected(id)
|
||||
end
|
||||
|
||||
-- send a CAPI packet
|
||||
-----@param msg_type CAPI_TYPE
|
||||
-- send a CRDN packet
|
||||
-----@param msg_type CRDN_TYPE
|
||||
-----@param msg table
|
||||
-- local function _send(msg_type, msg)
|
||||
-- local s_pkt = comms.scada_packet()
|
||||
-- local c_pkt = comms.capi_packet()
|
||||
-- local c_pkt = comms.crdn_packet()
|
||||
|
||||
-- c_pkt.make(msg_type, msg)
|
||||
-- s_pkt.make(self.seq_num, PROTOCOL.COORD_API, c_pkt.raw_sendable())
|
||||
-- s_pkt.make(self.seq_num, PROTOCOL.SCADA_CRDN, c_pkt.raw_sendable())
|
||||
|
||||
-- out_queue.push_packet(s_pkt)
|
||||
-- self.seq_num = self.seq_num + 1
|
||||
-- end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -101,7 +101,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
---@param pkt mgmt_frame|capi_frame
|
||||
---@param pkt mgmt_frame|crdn_frame
|
||||
local function _handle_packet(pkt)
|
||||
-- check sequence number
|
||||
if self.r_seq_num == nil then
|
||||
@ -117,17 +117,17 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
self.conn_watchdog.feed()
|
||||
|
||||
-- process packet
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.COORD_API then
|
||||
---@cast pkt capi_frame
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||
---@cast pkt crdn_frame
|
||||
|
||||
-- handle packet by type
|
||||
if pkt.type == nil then
|
||||
else
|
||||
log.debug(log_header .. "handler received unsupported CAPI packet type " .. pkt.type)
|
||||
log.debug(log_header .. "handler received unsupported CRDN packet type " .. pkt.type)
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -146,7 +146,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
else
|
||||
@ -174,7 +174,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
|
||||
@ -229,7 +229,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -22,7 +22,7 @@ local sounder = require("coordinator.sounder")
|
||||
|
||||
local apisessions = require("coordinator.session.apisessions")
|
||||
|
||||
local COORDINATOR_VERSION = "v1.0.9"
|
||||
local COORDINATOR_VERSION = "v1.0.10"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -12,20 +12,19 @@ local VerticalBar = require("graphics.elements.indicators.vbar")
|
||||
local cpair = core.cpair
|
||||
local border = core.border
|
||||
|
||||
local text_fg_bg = style.text_colors
|
||||
|
||||
-- new boiler view
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
---@param ps psil ps interface
|
||||
local function new_view(root, x, y, ps)
|
||||
local boiler = Rectangle{parent=root,border=border(1, colors.gray, true),width=31,height=7,x=x,y=y}
|
||||
|
||||
local text_fg_bg = cpair(colors.black, colors.lightGray)
|
||||
local lu_col = cpair(colors.gray, colors.gray)
|
||||
local boiler = Rectangle{parent=root,border=border(1,colors.gray,true),width=31,height=7,x=x,y=y}
|
||||
|
||||
local status = StateIndicator{parent=boiler,x=9,y=1,states=style.boiler.states,value=1,min_width=12}
|
||||
local temp = DataIndicator{parent=boiler,x=5,y=3,lu_colors=lu_col,label="Temp:",unit="K",format="%10.2f",value=0,width=22,fg_bg=text_fg_bg}
|
||||
local boil_r = DataIndicator{parent=boiler,x=5,y=4,lu_colors=lu_col,label="Boil:",unit="mB/t",format="%10.0f",value=0,commas=true,width=22,fg_bg=text_fg_bg}
|
||||
local temp = DataIndicator{parent=boiler,x=5,y=3,lu_colors=style.lu_col,label="Temp:",unit="K",format="%10.2f",value=0,width=22,fg_bg=text_fg_bg}
|
||||
local boil_r = DataIndicator{parent=boiler,x=5,y=4,lu_colors=style.lu_col,label="Boil:",unit="mB/t",format="%10.0f",value=0,commas=true,width=22,fg_bg=text_fg_bg}
|
||||
|
||||
status.register(ps, "computed_status", status.update)
|
||||
temp.register(ps, "temperature", temp.update)
|
||||
|
@ -18,6 +18,9 @@ local border = core.border
|
||||
|
||||
local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local text_fg_bg = style.text_colors
|
||||
local lu_col = style.lu_colors
|
||||
|
||||
-- new induction matrix view
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
@ -31,14 +34,12 @@ local function new_view(root, x, y, data, ps, id)
|
||||
|
||||
local matrix = Div{parent=root,fg_bg=style.root,width=33,height=24,x=x,y=y}
|
||||
|
||||
TextBox{parent=matrix,text=" ",width=33,height=1,x=1,y=1,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||
TextBox{parent=matrix,text=title,alignment=TEXT_ALIGN.CENTER,width=33,height=1,x=1,y=2,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||
TextBox{parent=matrix,text=" ",width=33,height=1,x=1,y=1,fg_bg=style.lg_gray}
|
||||
TextBox{parent=matrix,text=title,alignment=TEXT_ALIGN.CENTER,width=33,height=1,x=1,y=2,fg_bg=style.lg_gray}
|
||||
|
||||
local rect = Rectangle{parent=matrix,border=border(1,colors.gray,true),width=33,height=22,x=1,y=3}
|
||||
|
||||
local text_fg_bg = cpair(colors.black, colors.lightGray)
|
||||
local label_fg_bg = cpair(colors.gray, colors.lightGray)
|
||||
local lu_col = cpair(colors.gray, colors.gray)
|
||||
|
||||
local status = StateIndicator{parent=rect,x=10,y=1,states=style.imatrix.states,value=1,min_width=14}
|
||||
local energy = PowerIndicator{parent=rect,x=7,y=3,lu_colors=lu_col,label="Energy: ",format="%8.2f",value=0,width=26,fg_bg=text_fg_bg}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
|
||||
local style = require("coordinator.ui.style")
|
||||
|
||||
local core = require("graphics.core")
|
||||
|
||||
local Div = require("graphics.elements.div")
|
||||
@ -15,6 +17,9 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local cpair = core.cpair
|
||||
|
||||
local text_fg_bg = style.text_colors
|
||||
local lg_wh = style.lg_white
|
||||
|
||||
-- create a pocket list entry
|
||||
---@param parent graphics_element parent
|
||||
---@param id integer PKT session ID
|
||||
@ -23,22 +28,22 @@ local function init(parent, id)
|
||||
|
||||
-- root div
|
||||
local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true}
|
||||
local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=cpair(colors.black,colors.white)}
|
||||
local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=style.bw_fg_bg}
|
||||
|
||||
local ps_prefix = "pkt_" .. id .. "_"
|
||||
|
||||
TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
local pkt_addr = TextBox{parent=entry,x=1,y=2,text="@ C ??",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)}
|
||||
TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=text_fg_bg}
|
||||
local pkt_addr = TextBox{parent=entry,x=1,y=2,text="@ C ??",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=text_fg_bg,nav_active=cpair(colors.gray,colors.black)}
|
||||
TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=text_fg_bg}
|
||||
pkt_addr.register(ps, ps_prefix .. "addr", pkt_addr.set_value)
|
||||
|
||||
TextBox{parent=entry,x=10,y=2,text="FW:",width=3,height=1}
|
||||
local pkt_fw_v = TextBox{parent=entry,x=14,y=2,text=" ------- ",width=20,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local pkt_fw_v = TextBox{parent=entry,x=14,y=2,text=" ------- ",width=20,height=1,fg_bg=lg_wh}
|
||||
pkt_fw_v.register(ps, ps_prefix .. "fw", pkt_fw_v.set_value)
|
||||
|
||||
TextBox{parent=entry,x=35,y=2,text="RTT:",width=4,height=1}
|
||||
local pkt_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local pkt_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=lg_wh}
|
||||
TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=lg_wh}
|
||||
pkt_rtt.register(ps, ps_prefix .. "rtt", pkt_rtt.update)
|
||||
pkt_rtt.register(ps, ps_prefix .. "rtt_color", pkt_rtt.recolor)
|
||||
|
||||
|
@ -33,6 +33,8 @@ local lu_cpair = style.lu_colors
|
||||
local hzd_fg_bg = style.hzd_fg_bg
|
||||
local dis_colors = style.dis_colors
|
||||
|
||||
local gry_wht = style.gray_white
|
||||
|
||||
local ind_grn = style.ind_grn
|
||||
local ind_yel = style.ind_yel
|
||||
local ind_red = style.ind_red
|
||||
@ -47,6 +49,10 @@ local period = core.flasher.PERIOD
|
||||
local function new_view(root, x, y)
|
||||
assert(root.get_height() >= (y + 24), "main display not of sufficient vertical resolution (add an additional row of monitors)")
|
||||
|
||||
local black = cpair(colors.black, colors.black)
|
||||
local blk_brn = cpair(colors.black, colors.brown)
|
||||
local blk_pur = cpair(colors.black, colors.purple)
|
||||
|
||||
local facility = iocontrol.get_db().facility
|
||||
local units = iocontrol.get_db().units
|
||||
|
||||
@ -116,35 +122,35 @@ local function new_view(root, x, y)
|
||||
|
||||
local targets = Div{parent=proc,width=31,height=24,x=1,y=1}
|
||||
|
||||
local burn_tag = Div{parent=targets,x=1,y=1,width=8,height=4,fg_bg=cpair(colors.black,colors.purple)}
|
||||
local burn_tag = Div{parent=targets,x=1,y=1,width=8,height=4,fg_bg=blk_pur}
|
||||
TextBox{parent=burn_tag,x=2,y=2,text="Burn Target",width=7,height=2}
|
||||
|
||||
local burn_target = Div{parent=targets,x=9,y=1,width=23,height=3,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local b_target = SpinboxNumeric{parent=burn_target,x=11,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
||||
local burn_target = Div{parent=targets,x=9,y=1,width=23,height=3,fg_bg=gry_wht}
|
||||
local b_target = SpinboxNumeric{parent=burn_target,x=11,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=gry_wht,fg_bg=bw_fg_bg}
|
||||
TextBox{parent=burn_target,x=18,y=2,text="mB/t"}
|
||||
local burn_sum = DataIndicator{parent=targets,x=9,y=4,label="",format="%18.1f",value=0,unit="mB/t",commas=true,lu_colors=cpair(colors.black,colors.black),width=23,fg_bg=cpair(colors.black,colors.brown)}
|
||||
local burn_sum = DataIndicator{parent=targets,x=9,y=4,label="",format="%18.1f",value=0,unit="mB/t",commas=true,lu_colors=black,width=23,fg_bg=blk_brn}
|
||||
|
||||
b_target.register(facility.ps, "process_burn_target", b_target.set_value)
|
||||
burn_sum.register(facility.ps, "burn_sum", burn_sum.update)
|
||||
|
||||
local chg_tag = Div{parent=targets,x=1,y=6,width=8,height=4,fg_bg=cpair(colors.black,colors.purple)}
|
||||
local chg_tag = Div{parent=targets,x=1,y=6,width=8,height=4,fg_bg=blk_pur}
|
||||
TextBox{parent=chg_tag,x=2,y=2,text="Charge Target",width=7,height=2}
|
||||
|
||||
local chg_target = Div{parent=targets,x=9,y=6,width=23,height=3,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local c_target = SpinboxNumeric{parent=chg_target,x=2,y=1,whole_num_precision=15,fractional_precision=0,min=0,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
||||
local chg_target = Div{parent=targets,x=9,y=6,width=23,height=3,fg_bg=gry_wht}
|
||||
local c_target = SpinboxNumeric{parent=chg_target,x=2,y=1,whole_num_precision=15,fractional_precision=0,min=0,arrow_fg_bg=gry_wht,fg_bg=bw_fg_bg}
|
||||
TextBox{parent=chg_target,x=18,y=2,text="MFE"}
|
||||
local cur_charge = DataIndicator{parent=targets,x=9,y=9,label="",format="%19d",value=0,unit="MFE",commas=true,lu_colors=cpair(colors.black,colors.black),width=23,fg_bg=cpair(colors.black,colors.brown)}
|
||||
local cur_charge = DataIndicator{parent=targets,x=9,y=9,label="",format="%19d",value=0,unit="MFE",commas=true,lu_colors=black,width=23,fg_bg=blk_brn}
|
||||
|
||||
c_target.register(facility.ps, "process_charge_target", c_target.set_value)
|
||||
cur_charge.register(facility.induction_ps_tbl[1], "energy", function (j) cur_charge.update(util.joules_to_fe(j) / 1000000) end)
|
||||
|
||||
local gen_tag = Div{parent=targets,x=1,y=11,width=8,height=4,fg_bg=cpair(colors.black,colors.purple)}
|
||||
local gen_tag = Div{parent=targets,x=1,y=11,width=8,height=4,fg_bg=blk_pur}
|
||||
TextBox{parent=gen_tag,x=2,y=2,text="Gen. Target",width=7,height=2}
|
||||
|
||||
local gen_target = Div{parent=targets,x=9,y=11,width=23,height=3,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local g_target = SpinboxNumeric{parent=gen_target,x=8,y=1,whole_num_precision=9,fractional_precision=0,min=0,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
||||
local gen_target = Div{parent=targets,x=9,y=11,width=23,height=3,fg_bg=gry_wht}
|
||||
local g_target = SpinboxNumeric{parent=gen_target,x=8,y=1,whole_num_precision=9,fractional_precision=0,min=0,arrow_fg_bg=gry_wht,fg_bg=bw_fg_bg}
|
||||
TextBox{parent=gen_target,x=18,y=2,text="kFE/t"}
|
||||
local cur_gen = DataIndicator{parent=targets,x=9,y=14,label="",format="%17d",value=0,unit="kFE/t",commas=true,lu_colors=cpair(colors.black,colors.black),width=23,fg_bg=cpair(colors.black,colors.brown)}
|
||||
local cur_gen = DataIndicator{parent=targets,x=9,y=14,label="",format="%17d",value=0,unit="kFE/t",commas=true,lu_colors=black,width=23,fg_bg=blk_brn}
|
||||
|
||||
g_target.register(facility.ps, "process_gen_target", g_target.set_value)
|
||||
cur_gen.register(facility.induction_ps_tbl[1], "last_input", function (j) cur_gen.update(util.round(util.joules_to_fe(j) / 1000)) end)
|
||||
@ -159,10 +165,10 @@ local function new_view(root, x, y)
|
||||
|
||||
for i = 1, 4 do
|
||||
local unit
|
||||
local tag_fg_bg = cpair(colors.gray,colors.white)
|
||||
local lim_fg_bg = cpair(colors.lightGray,colors.white)
|
||||
local tag_fg_bg = gry_wht
|
||||
local lim_fg_bg = style.lg_white
|
||||
local ctl_fg = colors.lightGray
|
||||
local cur_fg_bg = cpair(colors.lightGray,colors.white)
|
||||
local cur_fg_bg = style.lg_white
|
||||
local cur_lu = colors.lightGray
|
||||
|
||||
if i <= facility.num_units then
|
||||
@ -170,7 +176,7 @@ local function new_view(root, x, y)
|
||||
tag_fg_bg = cpair(colors.black,colors.lightBlue)
|
||||
lim_fg_bg = bw_fg_bg
|
||||
ctl_fg = colors.gray
|
||||
cur_fg_bg = cpair(colors.black,colors.brown)
|
||||
cur_fg_bg = blk_brn
|
||||
cur_lu = colors.black
|
||||
end
|
||||
|
||||
@ -180,7 +186,7 @@ local function new_view(root, x, y)
|
||||
TextBox{parent=unit_tag,x=2,y=2,text="Unit "..i.." Limit",width=7,height=2}
|
||||
|
||||
local lim_ctl = Div{parent=limit_div,x=9,y=_y,width=14,height=3,fg_bg=cpair(ctl_fg,colors.white)}
|
||||
local lim = SpinboxNumeric{parent=lim_ctl,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=lim_fg_bg}
|
||||
local lim = SpinboxNumeric{parent=lim_ctl,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=gry_wht,fg_bg=lim_fg_bg}
|
||||
TextBox{parent=lim_ctl,x=9,y=2,text="mB/t",width=4,height=1}
|
||||
|
||||
local cur_burn = DataIndicator{parent=limit_div,x=9,y=_y+3,label="",format="%7.1f",value=0,unit="mB/t",commas=false,lu_colors=cpair(cur_lu,cur_lu),width=14,fg_bg=cur_fg_bg}
|
||||
@ -203,8 +209,8 @@ local function new_view(root, x, y)
|
||||
local stat_div = Div{parent=proc,width=22,height=24,x=57,y=6}
|
||||
|
||||
for i = 1, 4 do
|
||||
local tag_fg_bg = cpair(colors.gray, colors.white)
|
||||
local ind_fg_bg = cpair(colors.lightGray, colors.white)
|
||||
local tag_fg_bg = gry_wht
|
||||
local ind_fg_bg = style.lg_white
|
||||
local ind_off = colors.lightGray
|
||||
|
||||
if i <= facility.num_units then
|
||||
@ -241,12 +247,12 @@ local function new_view(root, x, y)
|
||||
|
||||
local u_stat = Rectangle{parent=proc,border=border(1,colors.gray,true),thin=true,width=31,height=4,x=1,y=16,fg_bg=bw_fg_bg}
|
||||
local stat_line_1 = TextBox{parent=u_stat,x=1,y=1,text="UNKNOWN",width=31,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=bw_fg_bg}
|
||||
local stat_line_2 = TextBox{parent=u_stat,x=1,y=2,text="awaiting data...",width=31,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=cpair(colors.gray, colors.white)}
|
||||
local stat_line_2 = TextBox{parent=u_stat,x=1,y=2,text="awaiting data...",width=31,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=gry_wht}
|
||||
|
||||
stat_line_1.register(facility.ps, "status_line_1", stat_line_1.set_value)
|
||||
stat_line_2.register(facility.ps, "status_line_2", stat_line_2.set_value)
|
||||
|
||||
local auto_controls = Div{parent=proc,x=1,y=20,width=31,height=5,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local auto_controls = Div{parent=proc,x=1,y=20,width=31,height=5,fg_bg=gry_wht}
|
||||
|
||||
-- save the automatic process control configuration without starting
|
||||
local function _save_cfg()
|
||||
@ -321,7 +327,7 @@ local function new_view(root, x, y)
|
||||
|
||||
local waste_sel = Div{parent=proc,width=21,height=24,x=81,y=1}
|
||||
|
||||
TextBox{parent=waste_sel,text=" ",width=21,height=1,x=1,y=1,fg_bg=cpair(colors.black,colors.brown)}
|
||||
TextBox{parent=waste_sel,text=" ",width=21,height=1,x=1,y=1,fg_bg=blk_brn}
|
||||
TextBox{parent=waste_sel,text="WASTE PRODUCTION",alignment=TEXT_ALIGN.CENTER,width=21,height=1,x=1,y=2,fg_bg=cpair(colors.lightGray,colors.brown)}
|
||||
|
||||
local rect = Rectangle{parent=waste_sel,border=border(1,colors.brown,true),width=21,height=22,x=1,y=3}
|
||||
|
@ -14,6 +14,9 @@ local StateIndicator = require("graphics.elements.indicators.state")
|
||||
local cpair = core.cpair
|
||||
local border = core.border
|
||||
|
||||
local text_fg_bg = style.text_colors
|
||||
local lu_col = style.lu_colors
|
||||
|
||||
-- create new reactor view
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
@ -22,9 +25,6 @@ local border = core.border
|
||||
local function new_view(root, x, y, ps)
|
||||
local reactor = Rectangle{parent=root,border=border(1, colors.gray, true),width=30,height=7,x=x,y=y}
|
||||
|
||||
local text_fg_bg = cpair(colors.black, colors.lightGray)
|
||||
local lu_col = cpair(colors.gray, colors.gray)
|
||||
|
||||
local status = StateIndicator{parent=reactor,x=6,y=1,states=style.reactor.states,value=1,min_width=16}
|
||||
local core_temp = DataIndicator{parent=reactor,x=2,y=3,lu_colors=lu_col,label="Core Temp:",unit="K",format="%10.2f",value=0,width=26,fg_bg=text_fg_bg}
|
||||
local burn_r = DataIndicator{parent=reactor,x=2,y=4,lu_colors=lu_col,label="Burn Rate:",unit="mB/t",format="%10.2f",value=0,width=26,fg_bg=text_fg_bg}
|
||||
|
@ -15,16 +15,16 @@ local VerticalBar = require("graphics.elements.indicators.vbar")
|
||||
local cpair = core.cpair
|
||||
local border = core.border
|
||||
|
||||
local text_fg_bg = style.text_colors
|
||||
local lu_col = style.lu_colors
|
||||
|
||||
-- new turbine view
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
---@param ps psil ps interface
|
||||
local function new_view(root, x, y, ps)
|
||||
local turbine = Rectangle{parent=root,border=border(1, colors.gray, true),width=23,height=7,x=x,y=y}
|
||||
|
||||
local text_fg_bg = cpair(colors.black, colors.lightGray)
|
||||
local lu_col = cpair(colors.gray, colors.gray)
|
||||
local turbine = Rectangle{parent=root,border=border(1,colors.gray,true),width=23,height=7,x=x,y=y}
|
||||
|
||||
local status = StateIndicator{parent=turbine,x=7,y=1,states=style.turbine.states,value=1,min_width=12}
|
||||
local prod_rate = PowerIndicator{parent=turbine,x=5,y=3,lu_colors=lu_col,label="",format="%10.2f",value=0,rate=true,width=16,fg_bg=text_fg_bg}
|
||||
|
@ -2,6 +2,8 @@
|
||||
-- Reactor Unit SCADA Coordinator GUI
|
||||
--
|
||||
|
||||
local types = require("scada-common.types")
|
||||
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
|
||||
local style = require("coordinator.ui.style")
|
||||
@ -34,6 +36,9 @@ local border = core.border
|
||||
local bw_fg_bg = style.bw_fg_bg
|
||||
local lu_cpair = style.lu_colors
|
||||
local hzd_fg_bg = style.hzd_fg_bg
|
||||
local dis_colors = style.dis_colors
|
||||
|
||||
local gry_wht = style.gray_white
|
||||
|
||||
local ind_grn = style.ind_grn
|
||||
local ind_yel = style.ind_yel
|
||||
@ -93,7 +98,7 @@ local function init(parent, id)
|
||||
waste.register(u_ps, "waste_fill", waste.update)
|
||||
|
||||
ccool.register(u_ps, "ccool_type", function (type)
|
||||
if type == "mekanism:sodium" then
|
||||
if type == types.FLUID.SODIUM then
|
||||
ccool.recolor(cpair(colors.lightBlue, colors.gray))
|
||||
else
|
||||
ccool.recolor(cpair(colors.blue, colors.gray))
|
||||
@ -101,7 +106,7 @@ local function init(parent, id)
|
||||
end)
|
||||
|
||||
hcool.register(u_ps, "hcool_type", function (type)
|
||||
if type == "mekanism:superheated_sodium" then
|
||||
if type == types.FLUID.SUPERHEATED_SODIUM then
|
||||
hcool.recolor(cpair(colors.orange, colors.gray))
|
||||
else
|
||||
hcool.recolor(cpair(colors.white, colors.gray))
|
||||
@ -130,7 +135,7 @@ local function init(parent, id)
|
||||
|
||||
local u_stat = Rectangle{parent=main,border=border(1,colors.gray,true),thin=true,width=33,height=4,x=46,y=3,fg_bg=bw_fg_bg}
|
||||
local stat_line_1 = TextBox{parent=u_stat,x=1,y=1,text="UNKNOWN",width=33,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=bw_fg_bg}
|
||||
local stat_line_2 = TextBox{parent=u_stat,x=1,y=2,text="awaiting data...",width=33,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=cpair(colors.gray, colors.white)}
|
||||
local stat_line_2 = TextBox{parent=u_stat,x=1,y=2,text="awaiting data...",width=33,height=1,alignment=TEXT_ALIGN.CENTER,fg_bg=gry_wht}
|
||||
|
||||
stat_line_1.register(u_ps, "U_StatusLine1", stat_line_1.set_value)
|
||||
stat_line_2.register(u_ps, "U_StatusLine2", stat_line_2.set_value)
|
||||
@ -341,10 +346,8 @@ local function init(parent, id)
|
||||
-- reactor controls --
|
||||
----------------------
|
||||
|
||||
local dis_colors = cpair(colors.white, colors.lightGray)
|
||||
|
||||
local burn_control = Div{parent=main,x=12,y=28,width=19,height=3,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local burn_rate = SpinboxNumeric{parent=burn_control,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
||||
local burn_control = Div{parent=main,x=12,y=28,width=19,height=3,fg_bg=gry_wht}
|
||||
local burn_rate = SpinboxNumeric{parent=burn_control,x=2,y=1,whole_num_precision=4,fractional_precision=1,min=0.1,arrow_fg_bg=gry_wht,fg_bg=bw_fg_bg}
|
||||
TextBox{parent=burn_control,x=9,y=2,text="mB/t"}
|
||||
|
||||
local set_burn = function () unit.set_burn(burn_rate.get_value()) end
|
||||
@ -480,7 +483,7 @@ local function init(parent, id)
|
||||
auto_div.line_break()
|
||||
|
||||
local function set_group() unit.set_group(group.get_value() - 1) end
|
||||
local set_grp_btn = PushButton{parent=auto_div,text="SET",x=4,min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=style.wh_gray,dis_fg_bg=cpair(colors.gray,colors.white),callback=set_group}
|
||||
local set_grp_btn = PushButton{parent=auto_div,text="SET",x=4,min_width=5,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=style.wh_gray,dis_fg_bg=gry_wht,callback=set_group}
|
||||
|
||||
auto_div.line_break()
|
||||
|
||||
|
@ -23,7 +23,6 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local sprintf = util.sprintf
|
||||
|
||||
local cpair = core.cpair
|
||||
local border = core.border
|
||||
local pipe = core.pipe
|
||||
|
||||
@ -31,6 +30,7 @@ local wh_gray = style.wh_gray
|
||||
local bw_fg_bg = style.bw_fg_bg
|
||||
local text_c = style.text_colors
|
||||
local lu_c = style.lu_colors
|
||||
local lg_gray = style.lg_gray
|
||||
|
||||
local ind_grn = style.ind_grn
|
||||
local ind_wht = style.ind_wht
|
||||
@ -64,8 +64,6 @@ local function make(parent, x, y, wide, unit)
|
||||
-- bounding box div
|
||||
local root = Div{parent=parent,x=x,y=y,width=_wide(136, 114),height=height}
|
||||
|
||||
local lg_gray = cpair(colors.lightGray, colors.gray)
|
||||
|
||||
------------------
|
||||
-- COOLING LOOP --
|
||||
------------------
|
||||
|
@ -261,7 +261,7 @@ local function init(main)
|
||||
if tank_defs[i] > 0 then
|
||||
local vy = 3 + y_ofs(i)
|
||||
|
||||
TextBox{parent=main,x=12,y=vy,text="\x10\x11",fg_bg=cpair(colors.black,colors.lightGray),width=2,height=1}
|
||||
TextBox{parent=main,x=12,y=vy,text="\x10\x11",fg_bg=text_col,width=2,height=1}
|
||||
|
||||
local conn = IndicatorLight{parent=main,x=9,y=vy+1,label=util.sprintf("PV%02d-EMC", i * 5),colors=style.ind_grn}
|
||||
local open = IndicatorLight{parent=main,x=9,y=vy+2,label="OPEN",colors=style.ind_wht}
|
||||
@ -288,7 +288,7 @@ local function init(main)
|
||||
|
||||
local tank = Div{parent=main,x=3,y=7+y_offset,width=20,height=14}
|
||||
|
||||
TextBox{parent=tank,text=" ",height=1,x=1,y=1,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||
TextBox{parent=tank,text=" ",height=1,x=1,y=1,fg_bg=style.lg_gray}
|
||||
TextBox{parent=tank,text="DYNAMIC TANK "..id,alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.wh_gray}
|
||||
|
||||
local tank_box = Rectangle{parent=tank,border=border(1,colors.gray,true),width=20,height=12}
|
||||
@ -338,7 +338,7 @@ local function init(main)
|
||||
|
||||
local sps = Div{parent=main,x=140,y=3,height=12}
|
||||
|
||||
TextBox{parent=sps,text=" ",width=24,height=1,x=1,y=1,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||
TextBox{parent=sps,text=" ",width=24,height=1,x=1,y=1,fg_bg=style.lg_gray}
|
||||
TextBox{parent=sps,text="SPS",alignment=TEXT_ALIGN.CENTER,width=24,height=1,fg_bg=wh_gray}
|
||||
|
||||
local sps_box = Rectangle{parent=sps,border=border(1,colors.gray,true),width=24,height=10}
|
||||
|
@ -2,32 +2,34 @@
|
||||
-- Coordinator Front Panel GUI
|
||||
--
|
||||
|
||||
local types = require("scada-common.types")
|
||||
local util = require("scada-common.util")
|
||||
local types = require("scada-common.types")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
|
||||
local pgi = require("coordinator.ui.pgi")
|
||||
local style = require("coordinator.ui.style")
|
||||
local pgi = require("coordinator.ui.pgi")
|
||||
local style = require("coordinator.ui.style")
|
||||
|
||||
local pkt_entry = require("coordinator.ui.components.pkt_entry")
|
||||
local pkt_entry = require("coordinator.ui.components.pkt_entry")
|
||||
|
||||
local core = require("graphics.core")
|
||||
local core = require("graphics.core")
|
||||
|
||||
local Div = require("graphics.elements.div")
|
||||
local ListBox = require("graphics.elements.listbox")
|
||||
local MultiPane = require("graphics.elements.multipane")
|
||||
local TextBox = require("graphics.elements.textbox")
|
||||
local Div = require("graphics.elements.div")
|
||||
local ListBox = require("graphics.elements.listbox")
|
||||
local MultiPane = require("graphics.elements.multipane")
|
||||
local TextBox = require("graphics.elements.textbox")
|
||||
|
||||
local TabBar = require("graphics.elements.controls.tabbar")
|
||||
local TabBar = require("graphics.elements.controls.tabbar")
|
||||
|
||||
local LED = require("graphics.elements.indicators.led")
|
||||
local RGBLED = require("graphics.elements.indicators.ledrgb")
|
||||
local LED = require("graphics.elements.indicators.led")
|
||||
local RGBLED = require("graphics.elements.indicators.ledrgb")
|
||||
|
||||
local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local cpair = core.cpair
|
||||
|
||||
local led_grn = style.led_grn
|
||||
|
||||
-- create new front panel view
|
||||
---@param panel graphics_element main displaybox
|
||||
---@param num_units integer number of units (number of unit monitors)
|
||||
@ -47,13 +49,13 @@ local function init(panel, num_units)
|
||||
local system = Div{parent=main_page,width=14,height=17,x=2,y=2}
|
||||
|
||||
local status = LED{parent=system,label="STATUS",colors=cpair(colors.green,colors.red)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=led_grn}
|
||||
status.update(true)
|
||||
system.line_break()
|
||||
|
||||
heartbeat.register(ps, "heartbeat", heartbeat.update)
|
||||
|
||||
local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)}
|
||||
local modem = LED{parent=system,label="MODEM",colors=led_grn}
|
||||
local network = RGBLED{parent=system,label="NETWORK",colors={colors.green,colors.red,colors.orange,colors.yellow,colors.gray}}
|
||||
network.update(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||
system.line_break()
|
||||
@ -61,25 +63,25 @@ local function init(panel, num_units)
|
||||
modem.register(ps, "has_modem", modem.update)
|
||||
network.register(ps, "link_state", network.update)
|
||||
|
||||
local speaker = LED{parent=system,label="SPEAKER",colors=cpair(colors.green,colors.green_off)}
|
||||
local speaker = LED{parent=system,label="SPEAKER",colors=led_grn}
|
||||
speaker.register(ps, "has_speaker", speaker.update)
|
||||
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local comp_id = util.sprintf("(%d)", os.getComputerID())
|
||||
TextBox{parent=system,x=9,y=4,width=6,height=1,text=comp_id,fg_bg=cpair(colors.lightGray,colors.ivory)}
|
||||
TextBox{parent=system,x=9,y=4,width=6,height=1,text=comp_id,fg_bg=style.fp_label}
|
||||
|
||||
local monitors = Div{parent=main_page,width=16,height=17,x=18,y=2}
|
||||
|
||||
local main_monitor = LED{parent=monitors,label="MAIN MONITOR",colors=cpair(colors.green,colors.green_off)}
|
||||
local main_monitor = LED{parent=monitors,label="MAIN MONITOR",colors=led_grn}
|
||||
main_monitor.register(ps, "main_monitor", main_monitor.update)
|
||||
|
||||
local flow_monitor = LED{parent=monitors,label="FLOW MONITOR",colors=cpair(colors.green,colors.green_off)}
|
||||
local flow_monitor = LED{parent=monitors,label="FLOW MONITOR",colors=led_grn}
|
||||
flow_monitor.register(ps, "flow_monitor", flow_monitor.update)
|
||||
|
||||
monitors.line_break()
|
||||
|
||||
for i = 1, num_units do
|
||||
local unit_monitor = LED{parent=monitors,label="UNIT "..i.." MONITOR",colors=cpair(colors.green,colors.green_off)}
|
||||
local unit_monitor = LED{parent=monitors,label="UNIT "..i.." MONITOR",colors=led_grn}
|
||||
unit_monitor.register(ps, "unit_monitor_" .. i, unit_monitor.update)
|
||||
end
|
||||
|
||||
@ -87,7 +89,7 @@ local function init(panel, num_units)
|
||||
-- about footer
|
||||
--
|
||||
|
||||
local about = Div{parent=main_page,width=15,height=3,x=1,y=16,fg_bg=cpair(colors.lightGray,colors.ivory)}
|
||||
local about = Div{parent=main_page,width=15,height=3,x=1,y=16,fg_bg=style.fp_label}
|
||||
local fw_v = TextBox{parent=about,x=1,y=1,text="FW: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
local comms_v = TextBox{parent=about,x=1,y=2,text="NT: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
|
||||
@ -101,7 +103,7 @@ local function init(panel, num_units)
|
||||
-- API page
|
||||
|
||||
local api_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
||||
local api_list = ListBox{parent=api_page,x=1,y=1,height=17,width=51,scroll_height=1000,fg_bg=cpair(colors.black,colors.ivory),nav_fg_bg=cpair(colors.gray,colors.lightGray),nav_active=cpair(colors.black,colors.gray)}
|
||||
local api_list = ListBox{parent=api_page,x=1,y=1,height=17,width=51,scroll_height=1000,fg_bg=style.fp_text,nav_fg_bg=cpair(colors.gray,colors.lightGray),nav_active=cpair(colors.black,colors.gray)}
|
||||
local _ = Div{parent=api_list,height=1,hidden=true} -- padding
|
||||
|
||||
-- assemble page panes
|
||||
@ -111,11 +113,11 @@ local function init(panel, num_units)
|
||||
local page_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes}
|
||||
|
||||
local tabs = {
|
||||
{ name = "CRD", color = cpair(colors.black, colors.ivory) },
|
||||
{ name = "API", color = cpair(colors.black, colors.ivory) },
|
||||
{ name = "CRD", color = style.fp_text },
|
||||
{ name = "API", color = style.fp_text },
|
||||
}
|
||||
|
||||
TabBar{parent=panel,y=2,tabs=tabs,min_width=9,callback=page_pane.set_value,fg_bg=cpair(colors.black,colors.white)}
|
||||
TabBar{parent=panel,y=2,tabs=tabs,min_width=9,callback=page_pane.set_value,fg_bg=style.bw_fg_bg}
|
||||
|
||||
-- link pocket API list management to PGI
|
||||
pgi.link_elements(api_list, pkt_entry)
|
||||
|
@ -2,8 +2,6 @@
|
||||
-- Main SCADA Coordinator GUI
|
||||
--
|
||||
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local iocontrol = require("coordinator.iocontrol")
|
||||
|
||||
local style = require("coordinator.ui.style")
|
||||
@ -20,8 +18,6 @@ local DataIndicator = require("graphics.elements.indicators.data")
|
||||
|
||||
local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local cpair = core.cpair
|
||||
|
||||
-- create new main view
|
||||
---@param main graphics_element main displaybox
|
||||
local function init(main)
|
||||
@ -30,7 +26,7 @@ local function init(main)
|
||||
|
||||
-- window header message
|
||||
local header = TextBox{parent=main,y=1,text="Nuclear Generation Facility SCADA Coordinator",alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.header}
|
||||
local ping = DataIndicator{parent=main,x=1,y=1,label="SVTT",format="%d",value=0,unit="ms",lu_colors=cpair(colors.lightGray, colors.white),width=12,fg_bg=style.header}
|
||||
local ping = DataIndicator{parent=main,x=1,y=1,label="SVTT",format="%d",value=0,unit="ms",lu_colors=style.lg_white,width=12,fg_bg=style.header}
|
||||
-- max length example: "01:23:45 AM - Wednesday, September 28 2022"
|
||||
local datetime = TextBox{parent=main,x=(header.get_width()-42),y=1,text="",alignment=TEXT_ALIGN.RIGHT,width=42,height=1,fg_bg=style.header}
|
||||
|
||||
@ -77,7 +73,7 @@ local function init(main)
|
||||
|
||||
assert(cnc_bottom_align_start >= cnc_y_start, "main display not of sufficient vertical resolution (add an additional row of monitors)")
|
||||
|
||||
TextBox{parent=main,y=cnc_bottom_align_start,text=util.strrep("\x8c", header.get_width()),alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=cpair(colors.lightGray,colors.gray)}
|
||||
TextBox{parent=main,y=cnc_bottom_align_start,text=string.rep("\x8c", header.get_width()),alignment=TEXT_ALIGN.CENTER,height=1,fg_bg=style.lg_gray}
|
||||
|
||||
cnc_bottom_align_start = cnc_bottom_align_start + 2
|
||||
|
||||
|
@ -78,11 +78,19 @@ style.lu_colors = cpair(colors.gray, colors.gray)
|
||||
style.hzd_fg_bg = style.wh_gray
|
||||
style.dis_colors = cpair(colors.white, colors.lightGray)
|
||||
|
||||
style.lg_gray = cpair(colors.lightGray, colors.gray)
|
||||
style.lg_white = cpair(colors.lightGray, colors.white)
|
||||
style.gray_white = cpair(colors.gray, colors.white)
|
||||
|
||||
style.ind_grn = cpair(colors.green, colors.gray)
|
||||
style.ind_yel = cpair(colors.yellow, colors.gray)
|
||||
style.ind_red = cpair(colors.red, colors.gray)
|
||||
style.ind_wht = style.wh_gray
|
||||
|
||||
style.fp_text = cpair(colors.black, colors.ivory)
|
||||
style.fp_label = cpair(colors.lightGray, colors.ivory)
|
||||
style.led_grn = cpair(colors.green, colors.green_off)
|
||||
|
||||
-- UI COMPONENTS --
|
||||
|
||||
style.reactor = {
|
||||
|
@ -7,7 +7,7 @@ local flasher = require("graphics.flasher")
|
||||
|
||||
local core = {}
|
||||
|
||||
core.version = "1.1.1"
|
||||
core.version = "1.1.2"
|
||||
|
||||
core.flasher = flasher
|
||||
core.events = events
|
||||
@ -35,11 +35,7 @@ core.TEXT_ALIGN = {
|
||||
---@param even? boolean whether to pad width extra to account for rectangular pixels, defaults to false
|
||||
---@return graphics_border
|
||||
function core.border(width, color, even)
|
||||
return {
|
||||
width = width,
|
||||
color = color,
|
||||
even = even or false -- convert nil to false
|
||||
}
|
||||
return { width = width, color = color, even = even or false }
|
||||
end
|
||||
|
||||
---@class graphics_frame
|
||||
@ -56,12 +52,7 @@ end
|
||||
---@param h integer
|
||||
---@return graphics_frame
|
||||
function core.gframe(x, y, w, h)
|
||||
return {
|
||||
x = x,
|
||||
y = y,
|
||||
w = w,
|
||||
h = h
|
||||
}
|
||||
return { x = x, y = y, w = w, h = h }
|
||||
end
|
||||
|
||||
---@class cpair
|
||||
|
@ -166,6 +166,31 @@ function element.new(args, child_offset_x, child_offset_y)
|
||||
self.bounds.x2 = self.position.x + f.w - 1
|
||||
self.bounds.y1 = self.position.y
|
||||
self.bounds.y2 = self.position.y + f.h - 1
|
||||
|
||||
-- alias functions
|
||||
|
||||
-- window set cursor position
|
||||
---@param x integer
|
||||
---@param y integer
|
||||
function protected.w_set_cur(x, y) protected.window.setCursorPos(x, y) end
|
||||
|
||||
-- set background color
|
||||
---@param c color
|
||||
function protected.w_set_bkg(c) protected.window.setBackgroundColor(c) end
|
||||
|
||||
-- set foreground (text) color
|
||||
---@param c color
|
||||
function protected.w_set_fgd(c) protected.window.setTextColor(c) end
|
||||
|
||||
-- write text
|
||||
---@param str string
|
||||
function protected.w_write(str) protected.window.write(str) end
|
||||
|
||||
-- blit text
|
||||
---@param str string
|
||||
---@param fg string
|
||||
---@param bg string
|
||||
function protected.w_blit(str, fg, bg) protected.window.blit(str, fg, bg) end
|
||||
end
|
||||
|
||||
-- check if a coordinate relative to the parent is within the bounds of this element
|
||||
|
@ -36,49 +36,49 @@ local function waiting(args)
|
||||
|
||||
if state >= 0 and state < 7 then
|
||||
-- top
|
||||
e.window.setCursorPos(1 + math.floor(state / 2), 1)
|
||||
e.w_set_cur(1 + math.floor(state / 2), 1)
|
||||
if state % 2 == 0 then
|
||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
||||
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||
else
|
||||
e.window.blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
||||
e.w_blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
||||
end
|
||||
|
||||
-- bottom
|
||||
e.window.setCursorPos(4 - math.ceil(state / 2), 3)
|
||||
e.w_set_cur(4 - math.ceil(state / 2), 3)
|
||||
if state % 2 == 0 then
|
||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
||||
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||
else
|
||||
e.window.blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
||||
e.w_blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
||||
end
|
||||
else
|
||||
local st = state - 7
|
||||
|
||||
-- right
|
||||
if st % 3 == 0 then
|
||||
e.window.setCursorPos(4, 1 + math.floor(st / 3))
|
||||
e.window.blit("\x83", blit_bg, blit_fg)
|
||||
e.w_set_cur(4, 1 + math.floor(st / 3))
|
||||
e.w_blit("\x83", blit_bg, blit_fg)
|
||||
elseif st % 3 == 1 then
|
||||
e.window.setCursorPos(4, 1 + math.floor(st / 3))
|
||||
e.window.blit("\x8f", blit_bg, blit_fg)
|
||||
e.window.setCursorPos(4, 2 + math.floor(st / 3))
|
||||
e.window.blit("\x83", blit_fg, blit_bg)
|
||||
e.w_set_cur(4, 1 + math.floor(st / 3))
|
||||
e.w_blit("\x8f", blit_bg, blit_fg)
|
||||
e.w_set_cur(4, 2 + math.floor(st / 3))
|
||||
e.w_blit("\x83", blit_fg, blit_bg)
|
||||
else
|
||||
e.window.setCursorPos(4, 2 + math.floor(st / 3))
|
||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
||||
e.w_set_cur(4, 2 + math.floor(st / 3))
|
||||
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||
end
|
||||
|
||||
-- left
|
||||
if st % 3 == 0 then
|
||||
e.window.setCursorPos(1, 3 - math.floor(st / 3))
|
||||
e.window.blit("\x83", blit_fg, blit_bg)
|
||||
e.window.setCursorPos(1, 2 - math.floor(st / 3))
|
||||
e.window.blit("\x8f", blit_bg, blit_fg)
|
||||
e.w_set_cur(1, 3 - math.floor(st / 3))
|
||||
e.w_blit("\x83", blit_fg, blit_bg)
|
||||
e.w_set_cur(1, 2 - math.floor(st / 3))
|
||||
e.w_blit("\x8f", blit_bg, blit_fg)
|
||||
elseif st % 3 == 1 then
|
||||
e.window.setCursorPos(1, 2 - math.floor(st / 3))
|
||||
e.window.blit("\x83", blit_bg, blit_fg)
|
||||
e.w_set_cur(1, 2 - math.floor(st / 3))
|
||||
e.w_blit("\x83", blit_bg, blit_fg)
|
||||
else
|
||||
e.window.setCursorPos(1, 2 - math.floor(st / 3))
|
||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
||||
e.w_set_cur(1, 2 - math.floor(st / 3))
|
||||
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -25,8 +25,8 @@ local function colormap(args)
|
||||
local e = element.new(args)
|
||||
|
||||
-- draw color map
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.blit(spaces, bkg, bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_blit(spaces, bkg, bkg)
|
||||
|
||||
return e.complete()
|
||||
end
|
||||
|
@ -36,9 +36,8 @@ local function app_button(args)
|
||||
local e = element.new(args)
|
||||
|
||||
-- write app title, centered
|
||||
e.window.setCursorPos(1, 4)
|
||||
e.window.setCursorPos(math.floor((e.frame.w - string.len(args.title)) / 2) + 1, 4)
|
||||
e.window.write(args.title)
|
||||
e.w_set_cur(math.floor((e.frame.w - string.len(args.title)) / 2) + 1, 4)
|
||||
e.w_write(args.title)
|
||||
|
||||
-- draw the app button
|
||||
local function draw()
|
||||
@ -51,36 +50,36 @@ local function app_button(args)
|
||||
end
|
||||
|
||||
-- draw icon
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.setTextColor(fgd)
|
||||
e.window.setBackgroundColor(bkg)
|
||||
e.window.write("\x9f\x83\x83\x83")
|
||||
e.window.setTextColor(bkg)
|
||||
e.window.setBackgroundColor(fgd)
|
||||
e.window.write("\x90")
|
||||
e.window.setTextColor(fgd)
|
||||
e.window.setBackgroundColor(bkg)
|
||||
e.window.setCursorPos(1, 2)
|
||||
e.window.write("\x95 ")
|
||||
e.window.setTextColor(bkg)
|
||||
e.window.setBackgroundColor(fgd)
|
||||
e.window.write("\x95")
|
||||
e.window.setCursorPos(1, 3)
|
||||
e.window.write("\x82\x8f\x8f\x8f\x81")
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_set_fgd(fgd)
|
||||
e.w_set_bkg(bkg)
|
||||
e.w_write("\x9f\x83\x83\x83")
|
||||
e.w_set_fgd(bkg)
|
||||
e.w_set_bkg(fgd)
|
||||
e.w_write("\x90")
|
||||
e.w_set_fgd(fgd)
|
||||
e.w_set_bkg(bkg)
|
||||
e.w_set_cur(1, 2)
|
||||
e.w_write("\x95 ")
|
||||
e.w_set_fgd(bkg)
|
||||
e.w_set_bkg(fgd)
|
||||
e.w_write("\x95")
|
||||
e.w_set_cur(1, 3)
|
||||
e.w_write("\x82\x8f\x8f\x8f\x81")
|
||||
|
||||
-- write the icon text
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.setTextColor(fgd)
|
||||
e.window.setBackgroundColor(bkg)
|
||||
e.window.write(args.text)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_set_fgd(fgd)
|
||||
e.w_set_bkg(bkg)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
|
||||
-- draw the app button as pressed (if active_fg_bg set)
|
||||
local function show_pressed()
|
||||
if e.enabled and args.active_fg_bg ~= nil then
|
||||
e.value = true
|
||||
e.window.setTextColor(args.active_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(args.active_fg_bg.bkg)
|
||||
e.w_set_fgd(args.active_fg_bg.fgd)
|
||||
e.w_set_bkg(args.active_fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
@ -89,8 +88,8 @@ local function app_button(args)
|
||||
local function show_unpressed()
|
||||
if e.enabled and args.active_fg_bg ~= nil then
|
||||
e.value = false
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
|
@ -32,24 +32,24 @@ local function checkbox(args)
|
||||
|
||||
-- show the button state
|
||||
local function draw()
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if e.value then
|
||||
-- show as selected
|
||||
e.window.setTextColor(args.box_fg_bg.bkg)
|
||||
e.window.setBackgroundColor(args.box_fg_bg.fgd)
|
||||
e.window.write("\x88")
|
||||
e.window.setTextColor(args.box_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write("\x95")
|
||||
e.w_set_fgd(args.box_fg_bg.bkg)
|
||||
e.w_set_bkg(args.box_fg_bg.fgd)
|
||||
e.w_write("\x88")
|
||||
e.w_set_fgd(args.box_fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write("\x95")
|
||||
else
|
||||
-- show as unselected
|
||||
e.window.setTextColor(e.fg_bg.bkg)
|
||||
e.window.setBackgroundColor(args.box_fg_bg.bkg)
|
||||
e.window.write("\x88")
|
||||
e.window.setTextColor(args.box_fg_bg.bkg)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write("\x95")
|
||||
e.w_set_fgd(e.fg_bg.bkg)
|
||||
e.w_set_bkg(args.box_fg_bg.bkg)
|
||||
e.w_write("\x88")
|
||||
e.w_set_fgd(args.box_fg_bg.bkg)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write("\x95")
|
||||
end
|
||||
end
|
||||
|
||||
@ -71,10 +71,10 @@ local function checkbox(args)
|
||||
end
|
||||
|
||||
-- write label text
|
||||
e.window.setCursorPos(3, 1)
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write(args.label)
|
||||
|
||||
-- initial draw
|
||||
draw()
|
||||
|
@ -1,7 +1,6 @@
|
||||
-- Hazard-bordered Button Graphics Element
|
||||
|
||||
local tcd = require("scada-common.tcd")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local core = require("graphics.core")
|
||||
local element = require("graphics.element")
|
||||
@ -34,35 +33,35 @@ local function hazard_button(args)
|
||||
local e = element.new(args)
|
||||
|
||||
-- write the button text
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
|
||||
-- draw border
|
||||
---@param accent color accent color
|
||||
local function draw_border(accent)
|
||||
-- top
|
||||
e.window.setTextColor(accent)
|
||||
e.window.setBackgroundColor(args.fg_bg.bkg)
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.write("\x99" .. util.strrep("\x89", args.width - 2) .. "\x99")
|
||||
e.w_set_fgd(accent)
|
||||
e.w_set_bkg(args.fg_bg.bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_write("\x99" .. string.rep("\x89", args.width - 2) .. "\x99")
|
||||
|
||||
-- center left
|
||||
e.window.setCursorPos(1, 2)
|
||||
e.window.setTextColor(args.fg_bg.bkg)
|
||||
e.window.setBackgroundColor(accent)
|
||||
e.window.write("\x99")
|
||||
e.w_set_cur(1, 2)
|
||||
e.w_set_fgd(args.fg_bg.bkg)
|
||||
e.w_set_bkg(accent)
|
||||
e.w_write("\x99")
|
||||
|
||||
-- center right
|
||||
e.window.setTextColor(args.fg_bg.bkg)
|
||||
e.window.setBackgroundColor(accent)
|
||||
e.window.setCursorPos(args.width, 2)
|
||||
e.window.write("\x99")
|
||||
e.w_set_fgd(args.fg_bg.bkg)
|
||||
e.w_set_bkg(accent)
|
||||
e.w_set_cur(args.width, 2)
|
||||
e.w_write("\x99")
|
||||
|
||||
-- bottom
|
||||
e.window.setTextColor(accent)
|
||||
e.window.setBackgroundColor(args.fg_bg.bkg)
|
||||
e.window.setCursorPos(1, 3)
|
||||
e.window.write("\x99" .. util.strrep("\x98", args.width - 2) .. "\x99")
|
||||
e.w_set_fgd(accent)
|
||||
e.w_set_bkg(args.fg_bg.bkg)
|
||||
e.w_set_cur(1, 3)
|
||||
e.w_write("\x99" .. string.rep("\x98", args.width - 2) .. "\x99")
|
||||
end
|
||||
|
||||
-- on request timeout: recursively calls itself to double flash button text
|
||||
@ -73,9 +72,9 @@ local function hazard_button(args)
|
||||
|
||||
if n == 0 then
|
||||
-- go back off
|
||||
e.window.setTextColor(args.fg_bg.fgd)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.fg_bg.fgd)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
|
||||
if n >= 4 then
|
||||
@ -83,18 +82,18 @@ local function hazard_button(args)
|
||||
elseif n % 2 == 0 then
|
||||
-- toggle text color on after 0.25 seconds
|
||||
tcd.dispatch(0.25, function ()
|
||||
e.window.setTextColor(args.accent)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.accent)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
on_timeout(n + 1)
|
||||
on_timeout(n + 1)
|
||||
end)
|
||||
elseif n % 1 then
|
||||
-- toggle text color off after 0.25 seconds
|
||||
tcd.dispatch(0.25, function ()
|
||||
e.window.setTextColor(args.fg_bg.fgd)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.fg_bg.fgd)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
on_timeout(n + 1)
|
||||
end)
|
||||
end
|
||||
@ -102,9 +101,9 @@ local function hazard_button(args)
|
||||
|
||||
-- blink routine for success indication
|
||||
local function on_success()
|
||||
e.window.setTextColor(args.fg_bg.fgd)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.fg_bg.fgd)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
|
||||
-- blink routine for failure indication
|
||||
@ -115,9 +114,9 @@ local function hazard_button(args)
|
||||
|
||||
if n == 0 then
|
||||
-- go back off
|
||||
e.window.setTextColor(args.fg_bg.fgd)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.fg_bg.fgd)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
|
||||
if n >= 2 then
|
||||
@ -125,17 +124,17 @@ local function hazard_button(args)
|
||||
elseif n % 2 == 0 then
|
||||
-- toggle text color on after 0.5 seconds
|
||||
tcd.dispatch(0.5, function ()
|
||||
e.window.setTextColor(args.accent)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.accent)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
on_failure(n + 1)
|
||||
end)
|
||||
elseif n % 1 then
|
||||
-- toggle text color off after 0.25 seconds
|
||||
tcd.dispatch(0.25, function ()
|
||||
e.window.setTextColor(args.fg_bg.fgd)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.fg_bg.fgd)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
on_failure(n + 1)
|
||||
end)
|
||||
end
|
||||
@ -147,9 +146,9 @@ local function hazard_button(args)
|
||||
if e.enabled then
|
||||
if core.events.was_clicked(event.type) then
|
||||
-- change text color to indicate clicked
|
||||
e.window.setTextColor(args.accent)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.accent)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
|
||||
-- abort any other callbacks
|
||||
tcd.abort(on_timeout)
|
||||
@ -182,18 +181,18 @@ local function hazard_button(args)
|
||||
function e.disable()
|
||||
if args.dis_colors then
|
||||
draw_border(args.dis_colors.color_a)
|
||||
e.window.setTextColor(args.dis_colors.color_b)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.dis_colors.color_b)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
end
|
||||
|
||||
-- show the button as enabled
|
||||
function e.enable()
|
||||
draw_border(args.accent)
|
||||
e.window.setTextColor(args.fg_bg.fgd)
|
||||
e.window.setCursorPos(3, 2)
|
||||
e.window.write(args.text)
|
||||
e.w_set_fgd(args.fg_bg.fgd)
|
||||
e.w_set_cur(3, 2)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
|
||||
-- initial draw of border
|
||||
|
@ -75,19 +75,19 @@ local function multi_button(args)
|
||||
for i = 1, #args.options do
|
||||
local opt = args.options[i] ---@type button_option
|
||||
|
||||
e.window.setCursorPos(opt._start_x, 1)
|
||||
e.w_set_cur(opt._start_x, 1)
|
||||
|
||||
if e.value == i then
|
||||
-- show as pressed
|
||||
e.window.setTextColor(opt.active_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(opt.active_fg_bg.bkg)
|
||||
e.w_set_fgd(opt.active_fg_bg.fgd)
|
||||
e.w_set_bkg(opt.active_fg_bg.bkg)
|
||||
else
|
||||
-- show as unpressed
|
||||
e.window.setTextColor(opt.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(opt.fg_bg.bkg)
|
||||
e.w_set_fgd(opt.fg_bg.fgd)
|
||||
e.w_set_bkg(opt.fg_bg.bkg)
|
||||
end
|
||||
|
||||
e.window.write(util.pad(opt.text, button_width))
|
||||
e.w_write(util.pad(opt.text, button_width))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -48,16 +48,16 @@ local function push_button(args)
|
||||
e.window.clear()
|
||||
|
||||
-- write the button text
|
||||
e.window.setCursorPos(h_pad, v_pad)
|
||||
e.window.write(args.text)
|
||||
e.w_set_cur(h_pad, v_pad)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
|
||||
-- draw the button as pressed (if active_fg_bg set)
|
||||
local function show_pressed()
|
||||
if e.enabled and args.active_fg_bg ~= nil then
|
||||
e.value = true
|
||||
e.window.setTextColor(args.active_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(args.active_fg_bg.bkg)
|
||||
e.w_set_fgd(args.active_fg_bg.fgd)
|
||||
e.w_set_bkg(args.active_fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
@ -66,8 +66,8 @@ local function push_button(args)
|
||||
local function show_unpressed()
|
||||
if e.enabled and args.active_fg_bg ~= nil then
|
||||
e.value = false
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
@ -102,8 +102,8 @@ local function push_button(args)
|
||||
function e.enable()
|
||||
if args.dis_fg_bg ~= nil then
|
||||
e.value = false
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
@ -112,8 +112,8 @@ local function push_button(args)
|
||||
function e.disable()
|
||||
if args.dis_fg_bg ~= nil then
|
||||
e.value = false
|
||||
e.window.setTextColor(args.dis_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(args.dis_fg_bg.bkg)
|
||||
e.w_set_fgd(args.dis_fg_bg.fgd)
|
||||
e.w_set_bkg(args.dis_fg_bg.bkg)
|
||||
draw()
|
||||
end
|
||||
end
|
||||
|
@ -56,28 +56,28 @@ local function radio_button(args)
|
||||
for i = 1, #args.options do
|
||||
local opt = args.options[i] ---@type string
|
||||
|
||||
e.window.setCursorPos(1, i)
|
||||
e.w_set_cur(1, i)
|
||||
|
||||
if e.value == i then
|
||||
-- show as selected
|
||||
e.window.setTextColor(args.radio_colors.color_a)
|
||||
e.window.setBackgroundColor(args.radio_bg)
|
||||
e.w_set_fgd(args.radio_colors.color_a)
|
||||
e.w_set_bkg(args.radio_bg)
|
||||
else
|
||||
-- show as unselected
|
||||
e.window.setTextColor(args.radio_colors.color_b)
|
||||
e.window.setBackgroundColor(args.radio_bg)
|
||||
e.w_set_fgd(args.radio_colors.color_b)
|
||||
e.w_set_bkg(args.radio_bg)
|
||||
end
|
||||
|
||||
e.window.write("\x88")
|
||||
e.w_write("\x88")
|
||||
|
||||
e.window.setTextColor(args.radio_bg)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write("\x95")
|
||||
e.w_set_fgd(args.radio_bg)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write("\x95")
|
||||
|
||||
-- write button text
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.write(opt)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_write(opt)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -52,27 +52,27 @@ local function sidebar(args)
|
||||
|
||||
local y = ((i - 1) * 3) + 1
|
||||
|
||||
e.window.setCursorPos(1, y)
|
||||
e.w_set_cur(1, y)
|
||||
|
||||
if pressed and i == pressed_idx then
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
else
|
||||
e.window.setTextColor(tab.color.fgd)
|
||||
e.window.setBackgroundColor(tab.color.bkg)
|
||||
e.w_set_fgd(tab.color.fgd)
|
||||
e.w_set_bkg(tab.color.bkg)
|
||||
end
|
||||
|
||||
e.window.write(" ")
|
||||
e.window.setCursorPos(1, y + 1)
|
||||
e.w_write(" ")
|
||||
e.w_set_cur(1, y + 1)
|
||||
if e.value == i then
|
||||
-- show as selected
|
||||
e.window.write(" " .. tab.char .. "\x10")
|
||||
e.w_write(" " .. tab.char .. "\x10")
|
||||
else
|
||||
-- show as unselected
|
||||
e.window.write(" " .. tab.char .. " ")
|
||||
e.w_write(" " .. tab.char .. " ")
|
||||
end
|
||||
e.window.setCursorPos(1, y + 2)
|
||||
e.window.write(" ")
|
||||
e.w_set_cur(1, y + 2)
|
||||
e.w_write(" ")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -58,17 +58,17 @@ local function spinbox(args)
|
||||
|
||||
-- draw the arrows
|
||||
local function draw_arrows(color)
|
||||
e.window.setBackgroundColor(args.arrow_fg_bg.bkg)
|
||||
e.window.setTextColor(color)
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.write(util.strrep("\x1e", wn_prec))
|
||||
e.window.setCursorPos(1, 3)
|
||||
e.window.write(util.strrep("\x1f", wn_prec))
|
||||
e.w_set_bkg(args.arrow_fg_bg.bkg)
|
||||
e.w_set_fgd(color)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_write(string.rep("\x1e", wn_prec))
|
||||
e.w_set_cur(1, 3)
|
||||
e.w_write(string.rep("\x1f", wn_prec))
|
||||
if fr_prec > 0 then
|
||||
e.window.setCursorPos(1 + wn_prec, 1)
|
||||
e.window.write(" " .. util.strrep("\x1e", fr_prec))
|
||||
e.window.setCursorPos(1 + wn_prec, 3)
|
||||
e.window.write(" " .. util.strrep("\x1f", fr_prec))
|
||||
e.w_set_cur(1 + wn_prec, 1)
|
||||
e.w_write(" " .. string.rep("\x1e", fr_prec))
|
||||
e.w_set_cur(1 + wn_prec, 3)
|
||||
e.w_write(" " .. string.rep("\x1f", fr_prec))
|
||||
end
|
||||
end
|
||||
|
||||
@ -119,10 +119,10 @@ local function spinbox(args)
|
||||
end
|
||||
|
||||
-- draw
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setCursorPos(1, 2)
|
||||
e.window.write(util.sprintf(fmt, e.value))
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_cur(1, 2)
|
||||
e.w_write(util.sprintf(fmt, e.value))
|
||||
end
|
||||
|
||||
-- init with the default value
|
||||
|
@ -47,20 +47,20 @@ local function switch_button(args)
|
||||
local function draw_state()
|
||||
if e.value then
|
||||
-- show as pressed
|
||||
e.window.setTextColor(args.active_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(args.active_fg_bg.bkg)
|
||||
e.w_set_fgd(args.active_fg_bg.fgd)
|
||||
e.w_set_bkg(args.active_fg_bg.bkg)
|
||||
else
|
||||
-- show as unpressed
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
end
|
||||
|
||||
-- clear to redraw background
|
||||
e.window.clear()
|
||||
|
||||
-- write the button text
|
||||
e.window.setCursorPos(h_pad, v_pad)
|
||||
e.window.write(args.text)
|
||||
e.w_set_cur(h_pad, v_pad)
|
||||
e.w_write(args.text)
|
||||
end
|
||||
|
||||
-- initial draw
|
||||
|
@ -71,17 +71,17 @@ local function tabbar(args)
|
||||
for i = 1, #args.tabs do
|
||||
local tab = args.tabs[i] ---@type tabbar_tab
|
||||
|
||||
e.window.setCursorPos(tab._start_x, 1)
|
||||
e.w_set_cur(tab._start_x, 1)
|
||||
|
||||
if e.value == i then
|
||||
e.window.setTextColor(tab.color.fgd)
|
||||
e.window.setBackgroundColor(tab.color.bkg)
|
||||
e.w_set_fgd(tab.color.fgd)
|
||||
e.w_set_bkg(tab.color.bkg)
|
||||
else
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
end
|
||||
|
||||
e.window.write(util.pad(tab.name, button_width))
|
||||
e.w_write(util.pad(tab.name, button_width))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -53,17 +53,17 @@ local function alarm_indicator_light(args)
|
||||
|
||||
-- called by flasher when enabled
|
||||
local function flash_callback()
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if flash_on then
|
||||
if e.value == 2 then
|
||||
e.window.blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
else
|
||||
if e.value == 3 then
|
||||
e.window.blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
else
|
||||
e.window.blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
@ -76,7 +76,7 @@ local function alarm_indicator_light(args)
|
||||
local was_off = e.value ~= 2
|
||||
|
||||
e.value = new_state
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if args.flash then
|
||||
if was_off and (new_state == 2) then
|
||||
@ -87,17 +87,17 @@ local function alarm_indicator_light(args)
|
||||
flasher.stop(flash_callback)
|
||||
|
||||
if new_state == 3 then
|
||||
e.window.blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
else
|
||||
e.window.blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
elseif new_state == 2 then
|
||||
e.window.blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
elseif new_state == 3 then
|
||||
e.window.blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
else
|
||||
e.window.blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
@ -107,7 +107,7 @@ local function alarm_indicator_light(args)
|
||||
|
||||
-- write label and initial indicator light
|
||||
e.on_update(1)
|
||||
e.window.write(args.label)
|
||||
e.w_write(args.label)
|
||||
|
||||
return e.complete()
|
||||
end
|
||||
|
@ -47,25 +47,25 @@ local function core_map(args)
|
||||
|
||||
-- create coordinate grid and frame
|
||||
local function draw_frame()
|
||||
e.window.setTextColor(colors.white)
|
||||
e.w_set_fgd(colors.white)
|
||||
|
||||
for x = 0, (inner_width - 1) do
|
||||
e.window.setCursorPos(x + start_x, 1)
|
||||
e.window.write(util.sprintf("%X", x))
|
||||
e.w_set_cur(x + start_x, 1)
|
||||
e.w_write(util.sprintf("%X", x))
|
||||
end
|
||||
|
||||
for y = 0, (inner_height - 1) do
|
||||
e.window.setCursorPos(1, y + start_y)
|
||||
e.window.write(util.sprintf("%X", y))
|
||||
e.w_set_cur(1, y + start_y)
|
||||
e.w_write(util.sprintf("%X", y))
|
||||
end
|
||||
|
||||
-- even out bottom edge
|
||||
e.window.setTextColor(e.fg_bg.bkg)
|
||||
e.window.setBackgroundColor(args.parent.get_fg_bg().bkg)
|
||||
e.window.setCursorPos(1, e.frame.h)
|
||||
e.window.write(util.strrep("\x8f", e.frame.w))
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.bkg)
|
||||
e.w_set_bkg(args.parent.get_fg_bg().bkg)
|
||||
e.w_set_cur(1, e.frame.h)
|
||||
e.w_write(string.rep("\x8f", e.frame.w))
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
end
|
||||
|
||||
-- draw the core
|
||||
@ -102,13 +102,13 @@ local function core_map(args)
|
||||
|
||||
-- draw pattern
|
||||
for y = start_y, inner_height + (start_y - 1) do
|
||||
e.window.setCursorPos(start_x, y)
|
||||
e.w_set_cur(start_x, y)
|
||||
for _ = 1, inner_width do
|
||||
if alternator then
|
||||
i = i + 1
|
||||
e.window.blit("\x07", text_c, back_c)
|
||||
e.w_blit("\x07", text_c, back_c)
|
||||
else
|
||||
e.window.blit("\x07", "7", "8")
|
||||
e.w_blit("\x07", "7", "8")
|
||||
end
|
||||
|
||||
alternator = not alternator
|
||||
|
@ -37,12 +37,12 @@ local function data(args)
|
||||
|
||||
-- label color
|
||||
if args.lu_colors ~= nil then
|
||||
e.window.setTextColor(args.lu_colors.color_a)
|
||||
e.w_set_fgd(args.lu_colors.color_a)
|
||||
end
|
||||
|
||||
-- write label
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_write(args.label)
|
||||
|
||||
local value_color = e.fg_bg.fgd
|
||||
local label_len = string.len(args.label)
|
||||
@ -60,25 +60,25 @@ local function data(args)
|
||||
e.value = value
|
||||
|
||||
-- clear old data and label
|
||||
e.window.setCursorPos(data_start, 1)
|
||||
e.window.write(util.spaces(clear_width))
|
||||
e.w_set_cur(data_start, 1)
|
||||
e.w_write(util.spaces(clear_width))
|
||||
|
||||
-- write data
|
||||
local data_str = util.sprintf(args.format, value)
|
||||
e.window.setCursorPos(data_start, 1)
|
||||
e.window.setTextColor(value_color)
|
||||
e.w_set_cur(data_start, 1)
|
||||
e.w_set_fgd(value_color)
|
||||
if args.commas then
|
||||
e.window.write(util.comma_format(data_str))
|
||||
e.w_write(util.comma_format(data_str))
|
||||
else
|
||||
e.window.write(data_str)
|
||||
e.w_write(data_str)
|
||||
end
|
||||
|
||||
-- write label
|
||||
if args.unit ~= nil then
|
||||
if args.lu_colors ~= nil then
|
||||
e.window.setTextColor(args.lu_colors.color_b)
|
||||
e.w_set_fgd(args.lu_colors.color_b)
|
||||
end
|
||||
e.window.write(" " .. args.unit)
|
||||
e.w_write(" " .. args.unit)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -87,16 +87,16 @@ local function hbar(args)
|
||||
|
||||
-- draw bar
|
||||
for y = 1, e.frame.h do
|
||||
e.window.setCursorPos(1, y)
|
||||
e.w_set_cur(1, y)
|
||||
-- intentionally swapped fgd/bkg since we use spaces as fill, but they are the opposite
|
||||
e.window.blit(spaces, bkg, fgd)
|
||||
e.w_blit(spaces, bkg, fgd)
|
||||
end
|
||||
end
|
||||
|
||||
-- update percentage
|
||||
if args.show_percent then
|
||||
e.window.setCursorPos(bar_width + 2, math.max(1, math.ceil(e.frame.h / 2)))
|
||||
e.window.write(util.sprintf("%3.0f%%", fraction * 100))
|
||||
e.w_set_cur(bar_width + 2, math.max(1, math.ceil(e.frame.h / 2)))
|
||||
e.w_write(util.sprintf("%3.0f%%", fraction * 100))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
-- Icon Indicator Graphics Element
|
||||
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local element = require("graphics.element")
|
||||
|
||||
---@class icon_sym_color
|
||||
@ -44,22 +42,22 @@ local function icon(args)
|
||||
|
||||
table.insert(state_blit_cmds, {
|
||||
text = " " .. sym_color.symbol .. " ",
|
||||
fgd = util.strrep(sym_color.color.blit_fgd, 3),
|
||||
bkg = util.strrep(sym_color.color.blit_bkg, 3)
|
||||
fgd = string.rep(sym_color.color.blit_fgd, 3),
|
||||
bkg = string.rep(sym_color.color.blit_bkg, 3)
|
||||
})
|
||||
end
|
||||
|
||||
-- write label and initial indicator light
|
||||
e.window.setCursorPos(5, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(5, 1)
|
||||
e.w_write(args.label)
|
||||
|
||||
-- on state change
|
||||
---@param new_state integer indicator state
|
||||
function e.on_update(new_state)
|
||||
local blit_cmd = state_blit_cmds[new_state]
|
||||
e.value = new_state
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
||||
end
|
||||
|
||||
-- set indicator state
|
||||
|
@ -44,12 +44,12 @@ local function indicator_led(args)
|
||||
|
||||
-- called by flasher when enabled
|
||||
local function flash_callback()
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if flash_on then
|
||||
e.window.blit("\x8c", args.colors.blit_a, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", args.colors.blit_a, e.fg_bg.blit_bkg)
|
||||
else
|
||||
e.window.blit("\x8c", args.colors.blit_b, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", args.colors.blit_b, e.fg_bg.blit_bkg)
|
||||
end
|
||||
|
||||
flash_on = not flash_on
|
||||
@ -61,8 +61,8 @@ local function indicator_led(args)
|
||||
flash_on = true
|
||||
flasher.start(flash_callback, args.period)
|
||||
else
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.blit("\x8c", args.colors.blit_a, e.fg_bg.blit_bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_blit("\x8c", args.colors.blit_a, e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
@ -73,8 +73,8 @@ local function indicator_led(args)
|
||||
flasher.stop(flash_callback)
|
||||
end
|
||||
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.blit("\x8c", args.colors.blit_b, e.fg_bg.blit_bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_blit("\x8c", args.colors.blit_b, e.fg_bg.blit_bkg)
|
||||
end
|
||||
|
||||
-- on state change
|
||||
@ -91,8 +91,8 @@ local function indicator_led(args)
|
||||
-- write label and initial indicator light
|
||||
e.on_update(false)
|
||||
if string.len(args.label) > 0 then
|
||||
e.window.setCursorPos(3, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_write(args.label)
|
||||
end
|
||||
|
||||
return e.complete()
|
||||
|
@ -56,16 +56,16 @@ local function indicator_led_pair(args)
|
||||
|
||||
-- called by flasher when enabled
|
||||
local function flash_callback()
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if flash_on then
|
||||
if e.value == 2 then
|
||||
e.window.blit("\x8c", c1, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", c1, e.fg_bg.blit_bkg)
|
||||
elseif e.value == 3 then
|
||||
e.window.blit("\x8c", c2, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", c2, e.fg_bg.blit_bkg)
|
||||
end
|
||||
else
|
||||
e.window.blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||
end
|
||||
|
||||
flash_on = not flash_on
|
||||
@ -77,7 +77,7 @@ local function indicator_led_pair(args)
|
||||
local was_off = e.value <= 1
|
||||
|
||||
e.value = new_state
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if args.flash then
|
||||
if was_off and (new_state > 1) then
|
||||
@ -87,14 +87,14 @@ local function indicator_led_pair(args)
|
||||
flash_on = false
|
||||
flasher.stop(flash_callback)
|
||||
|
||||
e.window.blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||
end
|
||||
elseif new_state == 2 then
|
||||
e.window.blit("\x8c", c1, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", c1, e.fg_bg.blit_bkg)
|
||||
elseif new_state == 3 then
|
||||
e.window.blit("\x8c", c2, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", c2, e.fg_bg.blit_bkg)
|
||||
else
|
||||
e.window.blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
@ -105,8 +105,8 @@ local function indicator_led_pair(args)
|
||||
-- write label and initial indicator light
|
||||
e.on_update(1)
|
||||
if string.len(args.label) > 0 then
|
||||
e.window.setCursorPos(3, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_write(args.label)
|
||||
end
|
||||
|
||||
return e.complete()
|
||||
|
@ -37,9 +37,9 @@ local function indicator_led_rgb(args)
|
||||
---@param new_state integer indicator state
|
||||
function e.on_update(new_state)
|
||||
e.value = new_state
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
if type(args.colors[new_state]) == "number" then
|
||||
e.window.blit("\x8c", colors.toBlit(args.colors[new_state]), e.fg_bg.blit_bkg)
|
||||
e.w_blit("\x8c", colors.toBlit(args.colors[new_state]), e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
@ -50,8 +50,8 @@ local function indicator_led_rgb(args)
|
||||
-- write label and initial indicator light
|
||||
e.on_update(1)
|
||||
if string.len(args.label) > 0 then
|
||||
e.window.setCursorPos(3, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_write(args.label)
|
||||
end
|
||||
|
||||
return e.complete()
|
||||
|
@ -44,12 +44,12 @@ local function indicator_light(args)
|
||||
|
||||
-- called by flasher when enabled
|
||||
local function flash_callback()
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if flash_on then
|
||||
e.window.blit(" \x95", "0" .. args.colors.blit_a, args.colors.blit_a .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. args.colors.blit_a, args.colors.blit_a .. e.fg_bg.blit_bkg)
|
||||
else
|
||||
e.window.blit(" \x95", "0" .. args.colors.blit_b, args.colors.blit_b .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. args.colors.blit_b, args.colors.blit_b .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
|
||||
flash_on = not flash_on
|
||||
@ -61,8 +61,8 @@ local function indicator_light(args)
|
||||
flash_on = true
|
||||
flasher.start(flash_callback, args.period)
|
||||
else
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.blit(" \x95", "0" .. args.colors.blit_a, args.colors.blit_a .. e.fg_bg.blit_bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_blit(" \x95", "0" .. args.colors.blit_a, args.colors.blit_a .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
@ -73,8 +73,8 @@ local function indicator_light(args)
|
||||
flasher.stop(flash_callback)
|
||||
end
|
||||
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.blit(" \x95", "0" .. args.colors.blit_b, args.colors.blit_b .. e.fg_bg.blit_bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_blit(" \x95", "0" .. args.colors.blit_b, args.colors.blit_b .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
|
||||
-- on state change
|
||||
@ -90,8 +90,8 @@ local function indicator_light(args)
|
||||
|
||||
-- write label and initial indicator light
|
||||
e.on_update(false)
|
||||
e.window.setCursorPos(3, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(3, 1)
|
||||
e.w_write(args.label)
|
||||
|
||||
return e.complete()
|
||||
end
|
||||
|
@ -34,12 +34,12 @@ local function power(args)
|
||||
|
||||
-- label color
|
||||
if args.lu_colors ~= nil then
|
||||
e.window.setTextColor(args.lu_colors.color_a)
|
||||
e.w_set_fgd(args.lu_colors.color_a)
|
||||
end
|
||||
|
||||
-- write label
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_write(args.label)
|
||||
|
||||
local data_start = string.len(args.label) + 2
|
||||
if string.len(args.label) == 0 then data_start = 1 end
|
||||
@ -52,13 +52,13 @@ local function power(args)
|
||||
local data_str, unit = util.power_format(value, false, args.format)
|
||||
|
||||
-- write data
|
||||
e.window.setCursorPos(data_start, 1)
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.write(util.comma_format(data_str))
|
||||
e.w_set_cur(data_start, 1)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_write(util.comma_format(data_str))
|
||||
|
||||
-- write unit
|
||||
if args.lu_colors ~= nil then
|
||||
e.window.setTextColor(args.lu_colors.color_b)
|
||||
e.w_set_fgd(args.lu_colors.color_b)
|
||||
end
|
||||
|
||||
-- append per tick if rate is set
|
||||
@ -70,7 +70,7 @@ local function power(args)
|
||||
if unit == "FE" then unit = "FE " end
|
||||
end
|
||||
|
||||
e.window.write(" " .. unit)
|
||||
e.w_write(" " .. unit)
|
||||
end
|
||||
|
||||
-- set the value
|
||||
|
@ -36,12 +36,12 @@ local function rad(args)
|
||||
|
||||
-- label color
|
||||
if args.lu_colors ~= nil then
|
||||
e.window.setTextColor(args.lu_colors.color_a)
|
||||
e.w_set_fgd(args.lu_colors.color_a)
|
||||
end
|
||||
|
||||
-- write label
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.write(args.label)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_write(args.label)
|
||||
|
||||
local label_len = string.len(args.label)
|
||||
local data_start = 1
|
||||
@ -58,24 +58,24 @@ local function rad(args)
|
||||
e.value = value.radiation
|
||||
|
||||
-- clear old data and label
|
||||
e.window.setCursorPos(data_start, 1)
|
||||
e.window.write(util.spaces(clear_width))
|
||||
e.w_set_cur(data_start, 1)
|
||||
e.w_write(util.spaces(clear_width))
|
||||
|
||||
-- write data
|
||||
local data_str = util.sprintf(args.format, e.value)
|
||||
e.window.setCursorPos(data_start, 1)
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.w_set_cur(data_start, 1)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
if args.commas then
|
||||
e.window.write(util.comma_format(data_str))
|
||||
e.w_write(util.comma_format(data_str))
|
||||
else
|
||||
e.window.write(data_str)
|
||||
e.w_write(data_str)
|
||||
end
|
||||
|
||||
-- write unit
|
||||
if args.lu_colors ~= nil then
|
||||
e.window.setTextColor(args.lu_colors.color_b)
|
||||
e.w_set_fgd(args.lu_colors.color_b)
|
||||
end
|
||||
e.window.write(" " .. value.unit)
|
||||
e.w_write(" " .. value.unit)
|
||||
end
|
||||
|
||||
-- set the value
|
||||
|
@ -51,8 +51,8 @@ local function state_indicator(args)
|
||||
|
||||
table.insert(state_blit_cmds, {
|
||||
text = text,
|
||||
fgd = util.strrep(state_def.color.blit_fgd, string.len(text)),
|
||||
bkg = util.strrep(state_def.color.blit_bkg, string.len(text))
|
||||
fgd = string.rep(state_def.color.blit_fgd, string.len(text)),
|
||||
bkg = string.rep(state_def.color.blit_bkg, string.len(text))
|
||||
})
|
||||
end
|
||||
|
||||
@ -64,8 +64,8 @@ local function state_indicator(args)
|
||||
function e.on_update(new_state)
|
||||
local blit_cmd = state_blit_cmds[new_state]
|
||||
e.value = new_state
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.window.blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
||||
e.w_set_cur(1, 1)
|
||||
e.w_blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
||||
end
|
||||
|
||||
-- set indicator state
|
||||
|
@ -56,16 +56,16 @@ local function tristate_indicator_light(args)
|
||||
|
||||
-- called by flasher when enabled
|
||||
local function flash_callback()
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if flash_on then
|
||||
if e.value == 2 then
|
||||
e.window.blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
elseif e.value == 3 then
|
||||
e.window.blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
else
|
||||
e.window.blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
|
||||
flash_on = not flash_on
|
||||
@ -77,7 +77,7 @@ local function tristate_indicator_light(args)
|
||||
local was_off = e.value <= 1
|
||||
|
||||
e.value = new_state
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
if args.flash then
|
||||
if was_off and (new_state > 1) then
|
||||
@ -87,14 +87,14 @@ local function tristate_indicator_light(args)
|
||||
flash_on = false
|
||||
flasher.stop(flash_callback)
|
||||
|
||||
e.window.blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
elseif new_state == 2 then
|
||||
e.window.blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c2, c2 .. e.fg_bg.blit_bkg)
|
||||
elseif new_state == 3 then
|
||||
e.window.blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c3, c3 .. e.fg_bg.blit_bkg)
|
||||
else
|
||||
e.window.blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
e.w_blit(" \x95", "0" .. c1, c1 .. e.fg_bg.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
@ -104,7 +104,7 @@ local function tristate_indicator_light(args)
|
||||
|
||||
-- write label and initial indicator light
|
||||
e.on_update(1)
|
||||
e.window.write(args.label)
|
||||
e.w_write(args.label)
|
||||
|
||||
return e.complete()
|
||||
end
|
||||
|
@ -27,11 +27,11 @@ local function vbar(args)
|
||||
local e = element.new(args)
|
||||
|
||||
-- blit strings
|
||||
local fgd = util.strrep(e.fg_bg.blit_fgd, e.frame.w)
|
||||
local bkg = util.strrep(e.fg_bg.blit_bkg, e.frame.w)
|
||||
local fgd = string.rep(e.fg_bg.blit_fgd, e.frame.w)
|
||||
local bkg = string.rep(e.fg_bg.blit_bkg, e.frame.w)
|
||||
local spaces = util.spaces(e.frame.w)
|
||||
local one_third = util.strrep("\x8f", e.frame.w)
|
||||
local two_thirds = util.strrep("\x83", e.frame.w)
|
||||
local one_third = string.rep("\x8f", e.frame.w)
|
||||
local two_thirds = string.rep("\x83", e.frame.w)
|
||||
|
||||
-- handle data changes
|
||||
---@param fraction number 0.0 to 1.0
|
||||
@ -56,28 +56,28 @@ local function vbar(args)
|
||||
local y = e.frame.h
|
||||
|
||||
-- start at base of vertical bar
|
||||
e.window.setCursorPos(1, y)
|
||||
e.w_set_cur(1, y)
|
||||
|
||||
-- fill percentage
|
||||
for _ = 1, num_bars / 3 do
|
||||
e.window.blit(spaces, bkg, fgd)
|
||||
e.w_blit(spaces, bkg, fgd)
|
||||
y = y - 1
|
||||
e.window.setCursorPos(1, y)
|
||||
e.w_set_cur(1, y)
|
||||
end
|
||||
|
||||
-- add fractional bar if needed
|
||||
if num_bars % 3 == 1 then
|
||||
e.window.blit(one_third, bkg, fgd)
|
||||
e.w_blit(one_third, bkg, fgd)
|
||||
y = y - 1
|
||||
elseif num_bars % 3 == 2 then
|
||||
e.window.blit(two_thirds, bkg, fgd)
|
||||
e.w_blit(two_thirds, bkg, fgd)
|
||||
y = y - 1
|
||||
end
|
||||
|
||||
-- fill the rest blank
|
||||
while y > 0 do
|
||||
e.window.setCursorPos(1, y)
|
||||
e.window.blit(spaces, fgd, bkg)
|
||||
e.w_set_cur(1, y)
|
||||
e.w_blit(spaces, fgd, bkg)
|
||||
y = y - 1
|
||||
end
|
||||
end
|
||||
@ -86,8 +86,8 @@ local function vbar(args)
|
||||
-- change bar color
|
||||
---@param fg_bg cpair new bar colors
|
||||
function e.recolor(fg_bg)
|
||||
fgd = util.strrep(fg_bg.blit_fgd, e.frame.w)
|
||||
bkg = util.strrep(fg_bg.blit_bkg, e.frame.w)
|
||||
fgd = string.rep(fg_bg.blit_fgd, e.frame.w)
|
||||
bkg = string.rep(fg_bg.blit_bkg, e.frame.w)
|
||||
|
||||
-- re-draw
|
||||
last_num_bars = 0
|
||||
|
@ -63,34 +63,34 @@ local function listbox(args)
|
||||
|
||||
-- draw up/down arrows
|
||||
if pressed_arrow == 1 then
|
||||
e.window.setTextColor(active_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(active_fg_bg.bkg)
|
||||
e.window.setCursorPos(e.frame.w, 1)
|
||||
e.window.write("\x1e")
|
||||
e.window.setTextColor(nav_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(nav_fg_bg.bkg)
|
||||
e.window.setCursorPos(e.frame.w, e.frame.h)
|
||||
e.window.write("\x1f")
|
||||
e.w_set_fgd(active_fg_bg.fgd)
|
||||
e.w_set_bkg(active_fg_bg.bkg)
|
||||
e.w_set_cur(e.frame.w, 1)
|
||||
e.w_write("\x1e")
|
||||
e.w_set_fgd(nav_fg_bg.fgd)
|
||||
e.w_set_bkg(nav_fg_bg.bkg)
|
||||
e.w_set_cur(e.frame.w, e.frame.h)
|
||||
e.w_write("\x1f")
|
||||
elseif pressed_arrow == -1 then
|
||||
e.window.setTextColor(nav_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(nav_fg_bg.bkg)
|
||||
e.window.setCursorPos(e.frame.w, 1)
|
||||
e.window.write("\x1e")
|
||||
e.window.setTextColor(active_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(active_fg_bg.bkg)
|
||||
e.window.setCursorPos(e.frame.w, e.frame.h)
|
||||
e.window.write("\x1f")
|
||||
e.w_set_fgd(nav_fg_bg.fgd)
|
||||
e.w_set_bkg(nav_fg_bg.bkg)
|
||||
e.w_set_cur(e.frame.w, 1)
|
||||
e.w_write("\x1e")
|
||||
e.w_set_fgd(active_fg_bg.fgd)
|
||||
e.w_set_bkg(active_fg_bg.bkg)
|
||||
e.w_set_cur(e.frame.w, e.frame.h)
|
||||
e.w_write("\x1f")
|
||||
else
|
||||
e.window.setTextColor(nav_fg_bg.fgd)
|
||||
e.window.setBackgroundColor(nav_fg_bg.bkg)
|
||||
e.window.setCursorPos(e.frame.w, 1)
|
||||
e.window.write("\x1e")
|
||||
e.window.setCursorPos(e.frame.w, e.frame.h)
|
||||
e.window.write("\x1f")
|
||||
e.w_set_fgd(nav_fg_bg.fgd)
|
||||
e.w_set_bkg(nav_fg_bg.bkg)
|
||||
e.w_set_cur(e.frame.w, 1)
|
||||
e.w_write("\x1e")
|
||||
e.w_set_cur(e.frame.w, e.frame.h)
|
||||
e.w_write("\x1f")
|
||||
end
|
||||
|
||||
e.window.setTextColor(e.fg_bg.fgd)
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_fgd(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
end
|
||||
|
||||
-- render the scroll bar and re-cacluate height & bounds
|
||||
@ -115,23 +115,23 @@ local function listbox(args)
|
||||
for i = 2, e.frame.h - 1 do
|
||||
if (i >= offset and i < (bar_height + offset)) and (bar_height ~= max_bar_height) then
|
||||
if args.nav_fg_bg ~= nil then
|
||||
e.window.setBackgroundColor(args.nav_fg_bg.fgd)
|
||||
e.w_set_bkg(args.nav_fg_bg.fgd)
|
||||
else
|
||||
e.window.setBackgroundColor(e.fg_bg.fgd)
|
||||
e.w_set_bkg(e.fg_bg.fgd)
|
||||
end
|
||||
else
|
||||
if args.nav_fg_bg ~= nil then
|
||||
e.window.setBackgroundColor(args.nav_fg_bg.bkg)
|
||||
e.w_set_bkg(args.nav_fg_bg.bkg)
|
||||
else
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
end
|
||||
end
|
||||
|
||||
e.window.setCursorPos(e.frame.w, i)
|
||||
e.window.write(" ")
|
||||
e.w_set_cur(e.frame.w, i)
|
||||
e.w_write(" ")
|
||||
end
|
||||
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
e.w_set_bkg(e.fg_bg.bkg)
|
||||
end
|
||||
|
||||
-- update item y positions and move elements
|
||||
|
@ -73,7 +73,7 @@ local function pipenet(args)
|
||||
y_step = util.trinary(pipe.y1 == pipe.y2, 0, y_step)
|
||||
end
|
||||
|
||||
e.window.setCursorPos(x, y)
|
||||
e.w_set_cur(x, y)
|
||||
|
||||
local c = core.cpair(pipe.color, e.fg_bg.bkg)
|
||||
|
||||
@ -84,24 +84,24 @@ local function pipenet(args)
|
||||
if i == pipe.w then
|
||||
-- corner
|
||||
if y_step > 0 then
|
||||
e.window.blit("\x93", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit("\x93", c.blit_bkg, c.blit_fgd)
|
||||
else
|
||||
e.window.blit("\x8e", c.blit_fgd, c.blit_bkg)
|
||||
e.w_blit("\x8e", c.blit_fgd, c.blit_bkg)
|
||||
end
|
||||
else
|
||||
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||
e.w_blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||
end
|
||||
else
|
||||
if i == pipe.w and y_step > 0 then
|
||||
-- corner
|
||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit(" ", c.blit_bkg, c.blit_fgd)
|
||||
else
|
||||
e.window.blit("\x8f", c.blit_fgd, c.blit_bkg)
|
||||
e.w_blit("\x8f", c.blit_fgd, c.blit_bkg)
|
||||
end
|
||||
end
|
||||
|
||||
x = x + x_step
|
||||
e.window.setCursorPos(x, y)
|
||||
e.w_set_cur(x, y)
|
||||
end
|
||||
|
||||
-- back up one
|
||||
@ -109,12 +109,12 @@ local function pipenet(args)
|
||||
|
||||
for _ = 1, pipe.h - 1 do
|
||||
y = y + y_step
|
||||
e.window.setCursorPos(x, y)
|
||||
e.w_set_cur(x, y)
|
||||
|
||||
if pipe.thin then
|
||||
e.window.blit("\x95", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit("\x95", c.blit_bkg, c.blit_fgd)
|
||||
else
|
||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit(" ", c.blit_bkg, c.blit_fgd)
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -124,26 +124,26 @@ local function pipenet(args)
|
||||
if i == pipe.h then
|
||||
-- corner
|
||||
if y_step < 0 then
|
||||
e.window.blit("\x97", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit("\x97", c.blit_bkg, c.blit_fgd)
|
||||
elseif y_step > 0 then
|
||||
e.window.blit("\x8d", c.blit_fgd, c.blit_bkg)
|
||||
e.w_blit("\x8d", c.blit_fgd, c.blit_bkg)
|
||||
else
|
||||
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||
e.w_blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||
end
|
||||
else
|
||||
e.window.blit("\x95", c.blit_fgd, c.blit_bkg)
|
||||
e.w_blit("\x95", c.blit_fgd, c.blit_bkg)
|
||||
end
|
||||
else
|
||||
if i == pipe.h and y_step < 0 then
|
||||
-- corner
|
||||
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||
else
|
||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit(" ", c.blit_bkg, c.blit_fgd)
|
||||
end
|
||||
end
|
||||
|
||||
y = y + y_step
|
||||
e.window.setCursorPos(x, y)
|
||||
e.w_set_cur(x, y)
|
||||
end
|
||||
|
||||
-- back up one
|
||||
@ -151,12 +151,12 @@ local function pipenet(args)
|
||||
|
||||
for _ = 1, pipe.w - 1 do
|
||||
x = x + x_step
|
||||
e.window.setCursorPos(x, y)
|
||||
e.w_set_cur(x, y)
|
||||
|
||||
if pipe.thin then
|
||||
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||
e.w_blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||
else
|
||||
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||
e.w_blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -298,12 +298,12 @@ local function pipenet(args)
|
||||
end
|
||||
end
|
||||
|
||||
e.window.setCursorPos(x, y)
|
||||
e.w_set_cur(x, y)
|
||||
|
||||
if invert then
|
||||
e.window.blit(char, entry.bg, entry.fg)
|
||||
e.w_blit(char, entry.bg, entry.fg)
|
||||
else
|
||||
e.window.blit(char, entry.fg, entry.bg)
|
||||
e.w_blit(char, entry.fg, entry.bg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -56,7 +56,7 @@ local function rectangle(args)
|
||||
-- draw bordered box if requested
|
||||
-- element constructor will have drawn basic colored rectangle regardless
|
||||
if args.border ~= nil then
|
||||
e.window.setCursorPos(1, 1)
|
||||
e.w_set_cur(1, 1)
|
||||
|
||||
local border_width = offset_x
|
||||
local border_height = offset_y
|
||||
@ -70,45 +70,45 @@ local function rectangle(args)
|
||||
|
||||
-- form the basic line strings and top/bottom blit strings
|
||||
local spaces = util.spaces(e.frame.w)
|
||||
local blit_fg = util.strrep(e.fg_bg.blit_fgd, e.frame.w)
|
||||
local blit_fg = string.rep(e.fg_bg.blit_fgd, e.frame.w)
|
||||
local blit_fg_sides = blit_fg
|
||||
local blit_bg_sides = ""
|
||||
local blit_bg_top_bot = util.strrep(border_blit, e.frame.w)
|
||||
local blit_bg_top_bot = string.rep(border_blit, e.frame.w)
|
||||
|
||||
-- partial bars
|
||||
local p_a, p_b, p_s
|
||||
if args.thin == true then
|
||||
if args.even_inner == true then
|
||||
p_a = "\x9c" .. util.strrep("\x8c", inner_width) .. "\x93"
|
||||
p_b = "\x8d" .. util.strrep("\x8c", inner_width) .. "\x8e"
|
||||
p_a = "\x9c" .. string.rep("\x8c", inner_width) .. "\x93"
|
||||
p_b = "\x8d" .. string.rep("\x8c", inner_width) .. "\x8e"
|
||||
else
|
||||
p_a = "\x97" .. util.strrep("\x83", inner_width) .. "\x94"
|
||||
p_b = "\x8a" .. util.strrep("\x8f", inner_width) .. "\x85"
|
||||
p_a = "\x97" .. string.rep("\x83", inner_width) .. "\x94"
|
||||
p_b = "\x8a" .. string.rep("\x8f", inner_width) .. "\x85"
|
||||
end
|
||||
|
||||
p_s = "\x95" .. util.spaces(inner_width) .. "\x95"
|
||||
else
|
||||
if args.even_inner == true then
|
||||
p_a = util.strrep("\x83", inner_width + width_x2)
|
||||
p_b = util.strrep("\x8f", inner_width + width_x2)
|
||||
p_a = string.rep("\x83", inner_width + width_x2)
|
||||
p_b = string.rep("\x8f", inner_width + width_x2)
|
||||
else
|
||||
p_a = util.spaces(border_width) .. util.strrep("\x8f", inner_width) .. util.spaces(border_width)
|
||||
p_b = util.spaces(border_width) .. util.strrep("\x83", inner_width) .. util.spaces(border_width)
|
||||
p_a = util.spaces(border_width) .. string.rep("\x8f", inner_width) .. util.spaces(border_width)
|
||||
p_b = util.spaces(border_width) .. string.rep("\x83", inner_width) .. util.spaces(border_width)
|
||||
end
|
||||
|
||||
p_s = spaces
|
||||
end
|
||||
|
||||
local p_inv_fg = util.strrep(border_blit, border_width) .. util.strrep(e.fg_bg.blit_bkg, inner_width) ..
|
||||
util.strrep(border_blit, border_width)
|
||||
local p_inv_bg = util.strrep(e.fg_bg.blit_bkg, border_width) .. util.strrep(border_blit, inner_width) ..
|
||||
util.strrep(e.fg_bg.blit_bkg, border_width)
|
||||
local p_inv_fg = string.rep(border_blit, border_width) .. string.rep(e.fg_bg.blit_bkg, inner_width) ..
|
||||
string.rep(border_blit, border_width)
|
||||
local p_inv_bg = string.rep(e.fg_bg.blit_bkg, border_width) .. string.rep(border_blit, inner_width) ..
|
||||
string.rep(e.fg_bg.blit_bkg, border_width)
|
||||
|
||||
if args.thin == true then
|
||||
p_inv_fg = e.fg_bg.blit_bkg .. util.strrep(e.fg_bg.blit_bkg, inner_width) .. util.strrep(border_blit, border_width)
|
||||
p_inv_bg = border_blit .. util.strrep(border_blit, inner_width) .. util.strrep(e.fg_bg.blit_bkg, border_width)
|
||||
p_inv_fg = e.fg_bg.blit_bkg .. string.rep(e.fg_bg.blit_bkg, inner_width) .. string.rep(border_blit, border_width)
|
||||
p_inv_bg = border_blit .. string.rep(border_blit, inner_width) .. string.rep(e.fg_bg.blit_bkg, border_width)
|
||||
|
||||
blit_fg_sides = border_blit .. util.strrep(e.fg_bg.blit_bkg, inner_width) .. e.fg_bg.blit_bkg
|
||||
blit_fg_sides = border_blit .. string.rep(e.fg_bg.blit_bkg, inner_width) .. e.fg_bg.blit_bkg
|
||||
end
|
||||
|
||||
-- form the body blit strings (sides are border, inside is normal)
|
||||
@ -127,28 +127,28 @@ local function rectangle(args)
|
||||
|
||||
-- draw rectangle with borders
|
||||
for y = 1, e.frame.h do
|
||||
e.window.setCursorPos(1, y)
|
||||
e.w_set_cur(1, y)
|
||||
-- top border
|
||||
if y <= border_height then
|
||||
-- partial pixel fill
|
||||
if args.border.even and y == border_height then
|
||||
if args.thin == true then
|
||||
e.window.blit(p_a, p_inv_bg, p_inv_fg)
|
||||
e.w_blit(p_a, p_inv_bg, p_inv_fg)
|
||||
else
|
||||
local _fg = util.trinary(args.even_inner == true, util.strrep(e.fg_bg.blit_bkg, e.frame.w), p_inv_bg)
|
||||
local _fg = util.trinary(args.even_inner == true, string.rep(e.fg_bg.blit_bkg, e.frame.w), p_inv_bg)
|
||||
local _bg = util.trinary(args.even_inner == true, blit_bg_top_bot, p_inv_fg)
|
||||
|
||||
if width_x2 % 3 == 1 then
|
||||
e.window.blit(p_b, _fg, _bg)
|
||||
e.w_blit(p_b, _fg, _bg)
|
||||
elseif width_x2 % 3 == 2 then
|
||||
e.window.blit(p_a, _fg, _bg)
|
||||
e.w_blit(p_a, _fg, _bg)
|
||||
else
|
||||
-- skip line
|
||||
e.window.blit(spaces, blit_fg, blit_bg_sides)
|
||||
e.w_blit(spaces, blit_fg, blit_bg_sides)
|
||||
end
|
||||
end
|
||||
else
|
||||
e.window.blit(spaces, blit_fg, blit_bg_top_bot)
|
||||
e.w_blit(spaces, blit_fg, blit_bg_top_bot)
|
||||
end
|
||||
-- bottom border
|
||||
elseif y > (e.frame.h - border_width) then
|
||||
@ -156,31 +156,31 @@ local function rectangle(args)
|
||||
if args.border.even and y == ((e.frame.h - border_width) + 1) then
|
||||
if args.thin == true then
|
||||
if args.even_inner == true then
|
||||
e.window.blit(p_b, blit_bg_top_bot, util.strrep(e.fg_bg.blit_bkg, e.frame.w))
|
||||
e.w_blit(p_b, blit_bg_top_bot, string.rep(e.fg_bg.blit_bkg, e.frame.w))
|
||||
else
|
||||
e.window.blit(p_b, util.strrep(e.fg_bg.blit_bkg, e.frame.w), blit_bg_top_bot)
|
||||
e.w_blit(p_b, string.rep(e.fg_bg.blit_bkg, e.frame.w), blit_bg_top_bot)
|
||||
end
|
||||
else
|
||||
local _fg = util.trinary(args.even_inner == true, blit_bg_top_bot, p_inv_fg)
|
||||
local _bg = util.trinary(args.even_inner == true, util.strrep(e.fg_bg.blit_bkg, e.frame.w), blit_bg_top_bot)
|
||||
local _bg = util.trinary(args.even_inner == true, string.rep(e.fg_bg.blit_bkg, e.frame.w), blit_bg_top_bot)
|
||||
|
||||
if width_x2 % 3 == 1 then
|
||||
e.window.blit(p_a, _fg, _bg)
|
||||
e.w_blit(p_a, _fg, _bg)
|
||||
elseif width_x2 % 3 == 2 then
|
||||
e.window.blit(p_b, _fg, _bg)
|
||||
e.w_blit(p_b, _fg, _bg)
|
||||
else
|
||||
-- skip line
|
||||
e.window.blit(spaces, blit_fg, blit_bg_sides)
|
||||
e.w_blit(spaces, blit_fg, blit_bg_sides)
|
||||
end
|
||||
end
|
||||
else
|
||||
e.window.blit(spaces, blit_fg, blit_bg_top_bot)
|
||||
e.w_blit(spaces, blit_fg, blit_bg_top_bot)
|
||||
end
|
||||
else
|
||||
if args.thin == true then
|
||||
e.window.blit(p_s, blit_fg_sides, blit_bg_sides)
|
||||
e.w_blit(p_s, blit_fg_sides, blit_bg_sides)
|
||||
else
|
||||
e.window.blit(p_s, blit_fg, blit_bg_sides)
|
||||
e.w_blit(p_s, blit_fg, blit_bg_sides)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -45,14 +45,14 @@ local function textbox(args)
|
||||
|
||||
-- use cursor position to align this line
|
||||
if alignment == TEXT_ALIGN.CENTER then
|
||||
e.window.setCursorPos(math.floor((e.frame.w - len) / 2) + 1, i)
|
||||
e.w_set_cur(math.floor((e.frame.w - len) / 2) + 1, i)
|
||||
elseif alignment == TEXT_ALIGN.RIGHT then
|
||||
e.window.setCursorPos((e.frame.w - len) + 1, i)
|
||||
e.w_set_cur((e.frame.w - len) + 1, i)
|
||||
else
|
||||
e.window.setCursorPos(1, i)
|
||||
e.w_set_cur(1, i)
|
||||
end
|
||||
|
||||
e.window.write(lines[i])
|
||||
e.w_write(lines[i])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -42,7 +42,7 @@ local function tiling(args)
|
||||
|
||||
-- border
|
||||
if args.border_c ~= nil then
|
||||
e.window.setBackgroundColor(args.border_c)
|
||||
e.w_set_bkg(args.border_c)
|
||||
e.window.clear()
|
||||
|
||||
start_x = 1 + util.trinary(even, 2, 1)
|
||||
@ -60,19 +60,19 @@ local function tiling(args)
|
||||
|
||||
-- create pattern
|
||||
for y = start_y, inner_height + (start_y - 1) do
|
||||
e.window.setCursorPos(start_x, y)
|
||||
e.w_set_cur(start_x, y)
|
||||
for _ = 1, inner_width do
|
||||
if alternator then
|
||||
if even then
|
||||
e.window.blit(" ", "00", fill_a .. fill_a)
|
||||
e.w_blit(" ", "00", fill_a .. fill_a)
|
||||
else
|
||||
e.window.blit(" ", "0", fill_a)
|
||||
e.w_blit(" ", "0", fill_a)
|
||||
end
|
||||
else
|
||||
if even then
|
||||
e.window.blit(" ", "00", fill_b .. fill_b)
|
||||
e.w_blit(" ", "00", fill_b .. fill_b)
|
||||
else
|
||||
e.window.blit(" ", "0", fill_b)
|
||||
e.w_blit(" ", "0", fill_b)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -7,7 +7,7 @@ local iocontrol = require("pocket.iocontrol")
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
local LINK_STATE = iocontrol.LINK_STATE
|
||||
|
||||
@ -51,7 +51,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
nic.open(pkt_channel)
|
||||
|
||||
-- send a management packet to the supervisor
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_sv(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -65,7 +65,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
end
|
||||
|
||||
-- send a management packet to the coordinator
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_crd(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -80,24 +80,24 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
|
||||
-- attempt supervisor connection establishment
|
||||
local function _send_sv_establish()
|
||||
_send_sv(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
_send_sv(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
end
|
||||
|
||||
-- attempt coordinator API connection establishment
|
||||
local function _send_api_establish()
|
||||
_send_crd(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
_send_crd(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PKT })
|
||||
end
|
||||
|
||||
-- keep alive ack to supervisor
|
||||
---@param srv_time integer
|
||||
local function _send_sv_keep_alive_ack(srv_time)
|
||||
_send_sv(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_sv(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- keep alive ack to coordinator
|
||||
---@param srv_time integer
|
||||
local function _send_api_keep_alive_ack(srv_time)
|
||||
_send_crd(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_crd(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -111,7 +111,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
self.sv.linked = false
|
||||
self.sv.r_seq_num = nil
|
||||
self.sv.addr = comms.BROADCAST
|
||||
_send_sv(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_sv(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- close connection to coordinator API server
|
||||
@ -120,7 +120,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
self.api.linked = false
|
||||
self.api.r_seq_num = nil
|
||||
self.api.addr = comms.BROADCAST
|
||||
_send_crd(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_crd(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- close the connections to the servers
|
||||
@ -157,21 +157,21 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
|
||||
-- supervisor get active alarm tones
|
||||
function public.diag__get_alarm_tones()
|
||||
if self.sv.linked then _send_sv(SCADA_MGMT_TYPE.DIAG_TONE_GET, {}) end
|
||||
if self.sv.linked then _send_sv(MGMT_TYPE.DIAG_TONE_GET, {}) end
|
||||
end
|
||||
|
||||
-- supervisor test alarm tones by tone
|
||||
---@param id TONE|0 tone ID, or 0 to stop all
|
||||
---@param state boolean tone state
|
||||
function public.diag__set_alarm_tone(id, state)
|
||||
if self.sv.linked then _send_sv(SCADA_MGMT_TYPE.DIAG_TONE_SET, { id, state }) end
|
||||
if self.sv.linked then _send_sv(MGMT_TYPE.DIAG_TONE_SET, { id, state }) end
|
||||
end
|
||||
|
||||
-- supervisor test alarm tones by alarm
|
||||
---@param id ALARM|0 alarm ID, 0 to stop all
|
||||
---@param state boolean alarm state
|
||||
function public.diag__set_alarm(id, state)
|
||||
if self.sv.linked then _send_sv(SCADA_MGMT_TYPE.DIAG_ALARM_SET, { id, state }) end
|
||||
if self.sv.linked then _send_sv(MGMT_TYPE.DIAG_ALARM_SET, { id, state }) end
|
||||
end
|
||||
|
||||
-- parse a packet
|
||||
@ -180,7 +180,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
---@param reply_to integer
|
||||
---@param message any
|
||||
---@param distance integer
|
||||
---@return mgmt_frame|capi_frame|nil packet
|
||||
---@return mgmt_frame|crdn_frame|nil packet
|
||||
function public.parse_packet(side, sender, reply_to, message, distance)
|
||||
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
||||
local pkt = nil
|
||||
@ -192,11 +192,11 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
if mgmt_pkt.decode(s_pkt) then
|
||||
pkt = mgmt_pkt.get()
|
||||
end
|
||||
-- get as coordinator API packet
|
||||
elseif s_pkt.protocol() == PROTOCOL.COORD_API then
|
||||
local capi_pkt = comms.capi_packet()
|
||||
if capi_pkt.decode(s_pkt) then
|
||||
pkt = capi_pkt.get()
|
||||
-- get as coordinator packet
|
||||
elseif s_pkt.protocol() == PROTOCOL.SCADA_CRDN then
|
||||
local crdn_pkt = comms.crdn_packet()
|
||||
if crdn_pkt.decode(s_pkt) then
|
||||
pkt = crdn_pkt.get()
|
||||
end
|
||||
else
|
||||
log.debug("attempted parse of illegal packet type " .. s_pkt.protocol(), true)
|
||||
@ -207,7 +207,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
---@param packet mgmt_frame|capi_frame|nil
|
||||
---@param packet mgmt_frame|crdn_frame|nil
|
||||
function public.handle_packet(packet)
|
||||
local diag = iocontrol.get_db().diag
|
||||
|
||||
@ -240,7 +240,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
if protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
if self.api.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 then
|
||||
local timestamp = packet.data[1]
|
||||
@ -256,7 +256,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("coordinator SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
api_watchdog.cancel()
|
||||
self.api.linked = false
|
||||
@ -266,7 +266,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from coordinator")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- connection with coordinator established
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
@ -330,7 +330,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
if protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
if self.sv.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 then
|
||||
local timestamp = packet.data[1]
|
||||
@ -346,14 +346,14 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("supervisor SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
sv_watchdog.cancel()
|
||||
self.sv.linked = false
|
||||
self.sv.r_seq_num = nil
|
||||
self.sv.addr = comms.BROADCAST
|
||||
log.info("supervisor server connection closed by remote host")
|
||||
elseif packet.type == SCADA_MGMT_TYPE.DIAG_TONE_GET then
|
||||
elseif packet.type == MGMT_TYPE.DIAG_TONE_GET then
|
||||
if packet.length == 8 then
|
||||
for i = 1, #packet.data do
|
||||
diag.tone_test.tone_indicators[i].update(packet.data[i] == true)
|
||||
@ -361,7 +361,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("supervisor SCADA diag alarm states packet length mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.DIAG_TONE_SET then
|
||||
elseif packet.type == MGMT_TYPE.DIAG_TONE_SET then
|
||||
if packet.length == 1 and packet.data[1] == false then
|
||||
diag.tone_test.ready_warn.set_value("testing denied")
|
||||
log.debug("supervisor SCADA diag tone set failed")
|
||||
@ -380,7 +380,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("supervisor SCADA diag tone set packet length/type mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.DIAG_ALARM_SET then
|
||||
elseif packet.type == MGMT_TYPE.DIAG_ALARM_SET then
|
||||
if packet.length == 1 and packet.data[1] == false then
|
||||
diag.tone_test.ready_warn.set_value("testing denied")
|
||||
log.debug("supervisor SCADA diag alarm set failed")
|
||||
@ -401,7 +401,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
||||
else
|
||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from supervisor")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- connection with supervisor established
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
|
@ -18,7 +18,7 @@ local iocontrol = require("pocket.iocontrol")
|
||||
local pocket = require("pocket.pocket")
|
||||
local renderer = require("pocket.renderer")
|
||||
|
||||
local POCKET_VERSION = "v0.6.0-alpha"
|
||||
local POCKET_VERSION = "v0.6.1-alpha"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -28,6 +28,9 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
local cpair = core.cpair
|
||||
local border = core.border
|
||||
|
||||
local ind_grn = style.ind_grn
|
||||
local ind_red = style.ind_red
|
||||
|
||||
-- create new front panel view
|
||||
---@param panel graphics_element main displaybox
|
||||
local function init(panel)
|
||||
@ -41,14 +44,14 @@ local function init(panel)
|
||||
local system = Div{parent=panel,width=14,height=18,x=2,y=3}
|
||||
|
||||
local init_ok = LED{parent=system,label="STATUS",colors=cpair(colors.green,colors.red)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=ind_grn}
|
||||
system.line_break()
|
||||
|
||||
init_ok.register(databus.ps, "init_ok", init_ok.update)
|
||||
heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
|
||||
|
||||
local reactor = LEDPair{parent=system,label="REACTOR",off=colors.red,c1=colors.yellow,c2=colors.green}
|
||||
local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)}
|
||||
local modem = LED{parent=system,label="MODEM",colors=ind_grn}
|
||||
local network = RGBLED{parent=system,label="NETWORK",colors={colors.green,colors.red,colors.orange,colors.yellow,colors.gray}}
|
||||
network.update(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||
system.line_break()
|
||||
@ -57,11 +60,11 @@ local function init(panel)
|
||||
modem.register(databus.ps, "has_modem", modem.update)
|
||||
network.register(databus.ps, "link_state", network.update)
|
||||
|
||||
local rt_main = LED{parent=system,label="RT MAIN",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_rps = LED{parent=system,label="RT RPS",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_cmtx = LED{parent=system,label="RT COMMS TX",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_cmrx = LED{parent=system,label="RT COMMS RX",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_sctl = LED{parent=system,label="RT SPCTL",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_main = LED{parent=system,label="RT MAIN",colors=ind_grn}
|
||||
local rt_rps = LED{parent=system,label="RT RPS",colors=ind_grn}
|
||||
local rt_cmtx = LED{parent=system,label="RT COMMS TX",colors=ind_grn}
|
||||
local rt_cmrx = LED{parent=system,label="RT COMMS RX",colors=ind_grn}
|
||||
local rt_sctl = LED{parent=system,label="RT SPCTL",colors=ind_grn}
|
||||
system.line_break()
|
||||
|
||||
rt_main.register(databus.ps, "routine__main", rt_main.update)
|
||||
@ -80,7 +83,7 @@ local function init(panel)
|
||||
|
||||
local status = Div{parent=panel,width=19,height=18,x=17,y=3}
|
||||
|
||||
local active = LED{parent=status,x=2,width=12,label="RCT ACTIVE",colors=cpair(colors.green,colors.green_off)}
|
||||
local active = LED{parent=status,x=2,width=12,label="RCT ACTIVE",colors=ind_grn}
|
||||
|
||||
-- only show emergency coolant LED if emergency coolant is configured for this device
|
||||
if type(config.EMERGENCY_COOL) == "table" then
|
||||
@ -90,7 +93,7 @@ local function init(panel)
|
||||
|
||||
local status_trip_rct = Rectangle{parent=status,width=20,height=3,x=1,border=border(1,colors.lightGray,true),even_inner=true,fg_bg=cpair(colors.black,colors.ivory)}
|
||||
local status_trip = Div{parent=status_trip_rct,width=18,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
local scram = LED{parent=status_trip,width=10,label="RPS TRIP",colors=cpair(colors.red,colors.red_off),flash=true,period=flasher.PERIOD.BLINK_250_MS}
|
||||
local scram = LED{parent=status_trip,width=10,label="RPS TRIP",colors=ind_red,flash=true,period=flasher.PERIOD.BLINK_250_MS}
|
||||
|
||||
local controls_rct = Rectangle{parent=status,width=17,height=3,x=1,border=border(1,colors.white,true),even_inner=true,fg_bg=cpair(colors.black,colors.ivory)}
|
||||
local controls = Div{parent=controls_rct,width=15,height=1,fg_bg=cpair(colors.black,colors.white)}
|
||||
@ -116,20 +119,20 @@ local function init(panel)
|
||||
--
|
||||
|
||||
local rps = Rectangle{parent=panel,width=16,height=16,x=36,y=3,border=border(1,colors.lightGray),thin=true,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
local rps_man = LED{parent=rps,label="MANUAL",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_auto = LED{parent=rps,label="AUTOMATIC",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_tmo = LED{parent=rps,label="TIMEOUT",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_flt = LED{parent=rps,label="PLC FAULT",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_fail = LED{parent=rps,label="RCT FAULT",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_man = LED{parent=rps,label="MANUAL",colors=ind_red}
|
||||
local rps_auto = LED{parent=rps,label="AUTOMATIC",colors=ind_red}
|
||||
local rps_tmo = LED{parent=rps,label="TIMEOUT",colors=ind_red}
|
||||
local rps_flt = LED{parent=rps,label="PLC FAULT",colors=ind_red}
|
||||
local rps_fail = LED{parent=rps,label="RCT FAULT",colors=ind_red}
|
||||
rps.line_break()
|
||||
local rps_dmg = LED{parent=rps,label="HI DAMAGE",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_tmp = LED{parent=rps,label="HI TEMP",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_dmg = LED{parent=rps,label="HI DAMAGE",colors=ind_red}
|
||||
local rps_tmp = LED{parent=rps,label="HI TEMP",colors=ind_red}
|
||||
rps.line_break()
|
||||
local rps_nof = LED{parent=rps,label="LO FUEL",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_wst = LED{parent=rps,label="HI WASTE",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_nof = LED{parent=rps,label="LO FUEL",colors=ind_red}
|
||||
local rps_wst = LED{parent=rps,label="HI WASTE",colors=ind_red}
|
||||
rps.line_break()
|
||||
local rps_ccl = LED{parent=rps,label="LO CCOOLANT",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_hcl = LED{parent=rps,label="HI HCOOLANT",colors=cpair(colors.red,colors.red_off)}
|
||||
local rps_ccl = LED{parent=rps,label="LO CCOOLANT",colors=ind_red}
|
||||
local rps_hcl = LED{parent=rps,label="HI HCOOLANT",colors=ind_red}
|
||||
|
||||
rps_man.register(databus.ps, "rps_manual", rps_man.update)
|
||||
rps_auto.register(databus.ps, "rps_automatic", rps_auto.update)
|
||||
|
@ -39,4 +39,9 @@ style.colors = {
|
||||
{ c = colors.brown, hex = 0x672223 } -- RED OFF
|
||||
}
|
||||
|
||||
-- COMMON COLOR PAIRS --
|
||||
|
||||
style.ind_grn = cpair(colors.green, colors.green_off)
|
||||
style.ind_red = cpair(colors.red, colors.red_off)
|
||||
|
||||
return style
|
||||
|
@ -16,7 +16,7 @@ local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local RPLC_TYPE = comms.RPLC_TYPE
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local AUTO_ACK = comms.PLC_AUTO_ACK
|
||||
|
||||
local RPS_LIMITS = const.RPS_LIMITS
|
||||
@ -489,7 +489,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -600,7 +600,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
-- keep alive ack
|
||||
---@param srv_time integer
|
||||
local function _send_keep_alive_ack(srv_time)
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- general ack
|
||||
@ -668,12 +668,12 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
function public.close()
|
||||
conn_watchdog.cancel()
|
||||
public.unlink()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- attempt to establish link with supervisor
|
||||
function public.send_link_req()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PLC, id })
|
||||
_send_mgmt(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.PLC, id })
|
||||
end
|
||||
|
||||
-- send live status information
|
||||
@ -929,7 +929,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
---@cast packet mgmt_frame
|
||||
-- if linked, only accept packets from configured supervisor
|
||||
if self.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||
local timestamp = packet.data[1]
|
||||
@ -945,7 +945,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
else
|
||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- handle session close
|
||||
conn_watchdog.cancel()
|
||||
public.unlink()
|
||||
@ -954,7 +954,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
||||
else
|
||||
log.debug("received unsupported SCADA_MGMT packet type " .. packet.type)
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- link request confirmation
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
|
@ -19,7 +19,7 @@ local plc = require("reactor-plc.plc")
|
||||
local renderer = require("reactor-plc.renderer")
|
||||
local threads = require("reactor-plc.threads")
|
||||
|
||||
local R_PLC_VERSION = "v1.5.7"
|
||||
local R_PLC_VERSION = "v1.5.8"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
@ -22,8 +22,11 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local cpair = core.cpair
|
||||
|
||||
local UNIT_TYPE_LABELS = { "UNKNOWN", "REDSTONE", "BOILER", "TURBINE", "DYNAMIC TANK", "IND MATRIX", "SPS", "SNA", "ENV DETECTOR" }
|
||||
local fp_label = style.fp_label
|
||||
|
||||
local ind_grn = style.ind_grn
|
||||
|
||||
local UNIT_TYPE_LABELS = { "UNKNOWN", "REDSTONE", "BOILER", "TURBINE", "DYNAMIC TANK", "IND MATRIX", "SPS", "SNA", "ENV DETECTOR" }
|
||||
|
||||
-- create new front panel view
|
||||
---@param panel graphics_element main displaybox
|
||||
@ -38,13 +41,13 @@ local function init(panel, units)
|
||||
local system = Div{parent=panel,width=14,height=18,x=2,y=3}
|
||||
|
||||
local on = LED{parent=system,label="STATUS",colors=cpair(colors.green,colors.red)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=ind_grn}
|
||||
on.update(true)
|
||||
system.line_break()
|
||||
|
||||
heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
|
||||
|
||||
local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)}
|
||||
local modem = LED{parent=system,label="MODEM",colors=ind_grn}
|
||||
local network = RGBLED{parent=system,label="NETWORK",colors={colors.green,colors.red,colors.orange,colors.yellow,colors.gray}}
|
||||
network.update(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||
system.line_break()
|
||||
@ -52,8 +55,8 @@ local function init(panel, units)
|
||||
modem.register(databus.ps, "has_modem", modem.update)
|
||||
network.register(databus.ps, "link_state", network.update)
|
||||
|
||||
local rt_main = LED{parent=system,label="RT MAIN",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_comm = LED{parent=system,label="RT COMMS",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_main = LED{parent=system,label="RT MAIN",colors=ind_grn}
|
||||
local rt_comm = LED{parent=system,label="RT COMMS",colors=ind_grn}
|
||||
system.line_break()
|
||||
|
||||
rt_main.register(databus.ps, "routine__main", rt_main.update)
|
||||
@ -61,7 +64,7 @@ local function init(panel, units)
|
||||
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local comp_id = util.sprintf("(%d)", os.getComputerID())
|
||||
TextBox{parent=system,x=9,y=4,width=6,height=1,text=comp_id,fg_bg=cpair(colors.lightGray,colors.ivory)}
|
||||
TextBox{parent=system,x=9,y=4,width=6,height=1,text=comp_id,fg_bg=fp_label}
|
||||
|
||||
TextBox{parent=system,x=1,y=14,text="SPEAKERS",height=1,width=8,fg_bg=style.label}
|
||||
local speaker_count = DataIndicator{parent=system,x=10,y=14,label="",format="%3d",value=0,width=3,fg_bg=cpair(colors.gray,colors.white)}
|
||||
@ -71,7 +74,7 @@ local function init(panel, units)
|
||||
-- about label
|
||||
--
|
||||
|
||||
local about = Div{parent=panel,width=15,height=3,x=1,y=18,fg_bg=cpair(colors.lightGray,colors.ivory)}
|
||||
local about = Div{parent=panel,width=15,height=3,x=1,y=18,fg_bg=fp_label}
|
||||
local fw_v = TextBox{parent=about,x=1,y=1,text="FW: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
local comms_v = TextBox{parent=about,x=1,y=2,text="NT: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
|
||||
@ -90,7 +93,7 @@ local function init(panel, units)
|
||||
-- show routine statuses
|
||||
for i = 1, list_length do
|
||||
TextBox{parent=threads,x=1,y=i,text=util.sprintf("%02d",i),height=1}
|
||||
local rt_unit = LED{parent=threads,x=4,y=i,label="RT",colors=cpair(colors.green,colors.green_off)}
|
||||
local rt_unit = LED{parent=threads,x=4,y=i,label="RT",colors=ind_grn}
|
||||
rt_unit.register(databus.ps, "routine__unit_" .. i, rt_unit.update)
|
||||
end
|
||||
|
||||
@ -115,7 +118,7 @@ local function init(panel, units)
|
||||
|
||||
-- assignment (unit # or facility)
|
||||
local for_unit = util.trinary(unit.reactor == 0, "\x1a FACIL ", "\x1a UNIT " .. unit.reactor)
|
||||
TextBox{parent=unit_hw_statuses,y=i,x=19,text=for_unit,height=1,fg_bg=cpair(colors.lightGray,colors.ivory)}
|
||||
TextBox{parent=unit_hw_statuses,y=i,x=19,text=for_unit,height=1,fg_bg=fp_label}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -39,4 +39,10 @@ style.colors = {
|
||||
{ c = colors.brown, hex = 0x672223 } -- RED OFF
|
||||
}
|
||||
|
||||
-- COMMON COLOR PAIRS --
|
||||
|
||||
style.fp_label = cpair(colors.lightGray, colors.ivory)
|
||||
|
||||
style.ind_grn = cpair(colors.green, colors.green_off)
|
||||
|
||||
return style
|
||||
|
24
rtu/rtu.lua
24
rtu/rtu.lua
@ -14,7 +14,7 @@ local rtu = {}
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
|
||||
-- create a new RTU unit
|
||||
@ -227,7 +227,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
nic.open(rtu_channel)
|
||||
|
||||
-- send a scada management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -243,7 +243,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
-- keep alive ack
|
||||
---@param srv_time integer
|
||||
local function _send_keep_alive_ack(srv_time)
|
||||
_send(SCADA_MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
_send(MGMT_TYPE.KEEP_ALIVE, { srv_time, util.time() })
|
||||
end
|
||||
|
||||
-- generate device advertisement table
|
||||
@ -298,25 +298,25 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
function public.close(rtu_state)
|
||||
conn_watchdog.cancel()
|
||||
public.unlink(rtu_state)
|
||||
_send(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send(MGMT_TYPE.CLOSE, {})
|
||||
end
|
||||
|
||||
-- send establish request (includes advertisement)
|
||||
---@param units table
|
||||
function public.send_establish(units)
|
||||
_send(SCADA_MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.RTU, _generate_advertisement(units) })
|
||||
_send(MGMT_TYPE.ESTABLISH, { comms.version, version, DEVICE_TYPE.RTU, _generate_advertisement(units) })
|
||||
end
|
||||
|
||||
-- send capability advertisement
|
||||
---@param units table
|
||||
function public.send_advertisement(units)
|
||||
_send(SCADA_MGMT_TYPE.RTU_ADVERT, _generate_advertisement(units))
|
||||
_send(MGMT_TYPE.RTU_ADVERT, _generate_advertisement(units))
|
||||
end
|
||||
|
||||
-- notify that a peripheral was remounted
|
||||
---@param unit_index integer RTU unit ID
|
||||
function public.send_remounted(unit_index)
|
||||
_send(SCADA_MGMT_TYPE.RTU_DEV_REMOUNT, { unit_index })
|
||||
_send(MGMT_TYPE.RTU_DEV_REMOUNT, { unit_index })
|
||||
end
|
||||
|
||||
-- parse a MODBUS/SCADA packet
|
||||
@ -433,7 +433,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
---@cast packet mgmt_frame
|
||||
-- SCADA management packet
|
||||
if rtu_state.linked then
|
||||
if packet.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if packet.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive request received, echo back
|
||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||
local timestamp = packet.data[1]
|
||||
@ -449,16 +449,16 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
else
|
||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||
-- close connection
|
||||
conn_watchdog.cancel()
|
||||
public.unlink(rtu_state)
|
||||
println_ts("server connection closed by remote host")
|
||||
log.warning("server connection closed by remote host")
|
||||
elseif packet.type == SCADA_MGMT_TYPE.RTU_ADVERT then
|
||||
elseif packet.type == MGMT_TYPE.RTU_ADVERT then
|
||||
-- request for capabilities again
|
||||
public.send_advertisement(units)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.RTU_TONE_ALARM then
|
||||
elseif packet.type == MGMT_TYPE.RTU_TONE_ALARM then
|
||||
-- alarm tone update from supervisor
|
||||
if (packet.length == 1) and type(packet.data[1] == "table") and (#packet.data[1] == 8) then
|
||||
local states = packet.data[1]
|
||||
@ -474,7 +474,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
||||
-- not supported
|
||||
log.debug("received unsupported SCADA_MGMT message type " .. packet.type)
|
||||
end
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
if packet.length == 1 then
|
||||
local est_ack = packet.data[1]
|
||||
|
||||
|
@ -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.6.2"
|
||||
local RTU_VERSION = "v1.6.3"
|
||||
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
||||
|
@ -6,23 +6,25 @@ local log = require("scada-common.log")
|
||||
|
||||
local insert = table.insert
|
||||
|
||||
---@type integer computer ID
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local COMPUTER_ID = os.getComputerID() ---@type integer computer ID
|
||||
local COMPUTER_ID = os.getComputerID()
|
||||
|
||||
local max_distance = nil ---@type number|nil maximum acceptable transmission distance
|
||||
---@type number|nil maximum acceptable transmission distance
|
||||
local max_distance = nil
|
||||
|
||||
---@class comms
|
||||
local comms = {}
|
||||
|
||||
comms.version = "2.2.1"
|
||||
-- protocol version (non-protocol changes tracked by util.lua version)
|
||||
comms.version = "2.3.0"
|
||||
|
||||
---@enum PROTOCOL
|
||||
local PROTOCOL = {
|
||||
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
||||
MODBUS_TCP = 0, -- the "MODBUS TCP"-esque protocol
|
||||
RPLC = 1, -- reactor PLC protocol
|
||||
SCADA_MGMT = 2, -- SCADA supervisor management, device advertisements, etc
|
||||
SCADA_CRDN = 3, -- data/control packets for coordinators to/from supervisory controllers
|
||||
COORD_API = 4 -- data/control packets for pocket computers to/from coordinators
|
||||
SCADA_CRDN = 3 -- data/control packets for coordinators to/from supervisory controllers
|
||||
}
|
||||
|
||||
---@enum RPLC_TYPE
|
||||
@ -40,8 +42,8 @@ local RPLC_TYPE = {
|
||||
AUTO_BURN_RATE = 10 -- set an automatic burn rate, PLC will respond with status, enable toggle speed limited
|
||||
}
|
||||
|
||||
---@enum SCADA_MGMT_TYPE
|
||||
local SCADA_MGMT_TYPE = {
|
||||
---@enum MGMT_TYPE
|
||||
local MGMT_TYPE = {
|
||||
ESTABLISH = 0, -- establish new connection
|
||||
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
||||
CLOSE = 2, -- close a connection
|
||||
@ -53,8 +55,8 @@ local SCADA_MGMT_TYPE = {
|
||||
DIAG_ALARM_SET = 8 -- diagnostic: set alarm to simulate audio for
|
||||
}
|
||||
|
||||
---@enum SCADA_CRDN_TYPE
|
||||
local SCADA_CRDN_TYPE = {
|
||||
---@enum CRDN_TYPE
|
||||
local CRDN_TYPE = {
|
||||
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
||||
FAC_BUILDS = 1, -- facility RTU builds
|
||||
FAC_STATUS = 2, -- state of facility and facility devices
|
||||
@ -64,10 +66,6 @@ local SCADA_CRDN_TYPE = {
|
||||
UNIT_CMD = 6 -- command a reactor unit
|
||||
}
|
||||
|
||||
---@enum CAPI_TYPE
|
||||
local CAPI_TYPE = {
|
||||
}
|
||||
|
||||
---@enum ESTABLISH_ACK
|
||||
local ESTABLISH_ACK = {
|
||||
ALLOW = 0, -- link approved
|
||||
@ -76,14 +74,8 @@ local ESTABLISH_ACK = {
|
||||
BAD_VERSION = 3 -- link denied due to comms version mismatch
|
||||
}
|
||||
|
||||
---@enum DEVICE_TYPE
|
||||
local DEVICE_TYPE = {
|
||||
PLC = 0, -- PLC device type for establish
|
||||
RTU = 1, -- RTU device type for establish
|
||||
SV = 2, -- supervisor device type for establish
|
||||
CRDN = 3, -- coordinator device type for establish
|
||||
PKT = 4 -- pocket device type for establish
|
||||
}
|
||||
---@enum DEVICE_TYPE device types for establish messages
|
||||
local DEVICE_TYPE = { PLC = 0, RTU = 1, SVR = 2, CRD = 3, PKT = 4 }
|
||||
|
||||
---@enum PLC_AUTO_ACK
|
||||
local PLC_AUTO_ACK = {
|
||||
@ -119,9 +111,8 @@ local UNIT_COMMAND = {
|
||||
comms.PROTOCOL = PROTOCOL
|
||||
|
||||
comms.RPLC_TYPE = RPLC_TYPE
|
||||
comms.SCADA_MGMT_TYPE = SCADA_MGMT_TYPE
|
||||
comms.SCADA_CRDN_TYPE = SCADA_CRDN_TYPE
|
||||
comms.CAPI_TYPE = CAPI_TYPE
|
||||
comms.MGMT_TYPE = MGMT_TYPE
|
||||
comms.CRDN_TYPE = CRDN_TYPE
|
||||
|
||||
comms.ESTABLISH_ACK = ESTABLISH_ACK
|
||||
comms.DEVICE_TYPE = DEVICE_TYPE
|
||||
@ -134,8 +125,8 @@ comms.FAC_COMMAND = FAC_COMMAND
|
||||
-- destination broadcast address (to all devices)
|
||||
comms.BROADCAST = -1
|
||||
|
||||
---@alias packet scada_packet|modbus_packet|rplc_packet|mgmt_packet|crdn_packet|capi_packet
|
||||
---@alias frame modbus_frame|rplc_frame|mgmt_frame|crdn_frame|capi_frame
|
||||
---@alias packet scada_packet|modbus_packet|rplc_packet|mgmt_packet|crdn_packet
|
||||
---@alias frame modbus_frame|rplc_frame|mgmt_frame|crdn_frame
|
||||
|
||||
-- configure the maximum allowable message receive distance<br>
|
||||
-- packets received with distances greater than this will be silently discarded
|
||||
@ -144,7 +135,7 @@ function comms.set_trusted_range(distance)
|
||||
if distance == 0 then max_distance = nil else max_distance = distance end
|
||||
end
|
||||
|
||||
-- generic SCADA packet object
|
||||
-- generic SCADA packet
|
||||
---@nodiscard
|
||||
function comms.scada_packet()
|
||||
local self = {
|
||||
@ -199,9 +190,9 @@ function comms.scada_packet()
|
||||
self.valid = false
|
||||
self.raw = self.modem_msg_in.msg
|
||||
|
||||
if (type(max_distance) == "number") and (distance > max_distance) then
|
||||
if (type(max_distance) == "number") and (type(distance) == "number") and (distance > max_distance) then
|
||||
-- outside of maximum allowable transmission distance
|
||||
-- log.debug("comms.scada_packet.receive(): discarding packet with distance " .. distance .. " outside of trusted range")
|
||||
-- log.debug("comms.scada_packet.receive(): discarding packet with distance " .. distance .. " (outside trusted range)")
|
||||
else
|
||||
if type(self.raw) == "table" then
|
||||
if #self.raw == 5 then
|
||||
@ -227,12 +218,8 @@ function comms.scada_packet()
|
||||
-- check if this packet is destined for this device
|
||||
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
||||
|
||||
self.valid = is_destination and
|
||||
type(self.src_addr) == "number" and
|
||||
type(self.dest_addr) == "number" and
|
||||
type(self.seq_num) == "number" and
|
||||
type(self.protocol) == "number" and
|
||||
type(self.payload) == "table"
|
||||
self.valid = is_destination and type(self.src_addr) == "number" and type(self.dest_addr) == "number" and
|
||||
type(self.seq_num) == "number" and type(self.protocol) == "number" and type(self.payload) == "table"
|
||||
end
|
||||
end
|
||||
|
||||
@ -275,7 +262,7 @@ function comms.scada_packet()
|
||||
return public
|
||||
end
|
||||
|
||||
-- authenticated SCADA packet object
|
||||
-- authenticated SCADA packet
|
||||
---@nodiscard
|
||||
function comms.authd_packet()
|
||||
local self = {
|
||||
@ -325,7 +312,7 @@ function comms.authd_packet()
|
||||
|
||||
if (type(max_distance) == "number") and (type(distance) == "number") and (distance > max_distance) then
|
||||
-- outside of maximum allowable transmission distance
|
||||
-- log.debug("comms.authd_packet.receive(): discarding packet with distance " .. distance .. " outside of trusted range")
|
||||
-- log.debug("comms.authd_packet.receive(): discarding packet with distance " .. distance .. " (outside trusted range)")
|
||||
else
|
||||
if type(self.raw) == "table" then
|
||||
if #self.raw == 4 then
|
||||
@ -343,11 +330,8 @@ function comms.authd_packet()
|
||||
-- check if this packet is destined for this device
|
||||
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
||||
|
||||
self.valid = is_destination and
|
||||
type(self.src_addr) == "number" and
|
||||
type(self.dest_addr) == "number" and
|
||||
type(self.mac) == "string" and
|
||||
type(self.payload) == "string"
|
||||
self.valid = is_destination and type(self.src_addr) == "number" and type(self.dest_addr) == "number" and
|
||||
type(self.mac) == "string" and type(self.payload) == "string"
|
||||
end
|
||||
end
|
||||
|
||||
@ -381,8 +365,7 @@ function comms.authd_packet()
|
||||
return public
|
||||
end
|
||||
|
||||
-- MODBUS packet<br>
|
||||
-- modeled after MODBUS TCP packet
|
||||
-- MODBUS packet, modeled after MODBUS TCP
|
||||
---@nodiscard
|
||||
function comms.modbus_packet()
|
||||
local self = {
|
||||
@ -436,9 +419,7 @@ function comms.modbus_packet()
|
||||
public.make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
|
||||
end
|
||||
|
||||
local valid = type(self.txn_id) == "number" and
|
||||
type(self.unit_id) == "number" and
|
||||
type(self.func_code) == "number"
|
||||
local valid = type(self.txn_id) == "number" and type(self.unit_id) == "number" and type(self.func_code) == "number"
|
||||
|
||||
return size_ok and valid
|
||||
else
|
||||
@ -489,21 +470,6 @@ function comms.rplc_packet()
|
||||
---@class rplc_packet
|
||||
local public = {}
|
||||
|
||||
-- check that type is known
|
||||
local function _rplc_type_valid()
|
||||
return self.type == RPLC_TYPE.STATUS or
|
||||
self.type == RPLC_TYPE.MEK_STRUCT or
|
||||
self.type == RPLC_TYPE.MEK_BURN_RATE or
|
||||
self.type == RPLC_TYPE.RPS_ENABLE or
|
||||
self.type == RPLC_TYPE.RPS_SCRAM or
|
||||
self.type == RPLC_TYPE.RPS_ASCRAM or
|
||||
self.type == RPLC_TYPE.RPS_STATUS or
|
||||
self.type == RPLC_TYPE.RPS_ALARM or
|
||||
self.type == RPLC_TYPE.RPS_RESET or
|
||||
self.type == RPLC_TYPE.RPS_AUTO_RESET or
|
||||
self.type == RPLC_TYPE.AUTO_BURN_RATE
|
||||
end
|
||||
|
||||
-- make an RPLC packet
|
||||
---@param id integer
|
||||
---@param packet_type RPLC_TYPE
|
||||
@ -539,7 +505,6 @@ function comms.rplc_packet()
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], data[2], { table.unpack(data, 3, #data) })
|
||||
ok = _rplc_type_valid()
|
||||
end
|
||||
|
||||
ok = ok and type(self.id) == "number"
|
||||
@ -583,7 +548,7 @@ function comms.mgmt_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
raw = {},
|
||||
type = 0, ---@type SCADA_MGMT_TYPE
|
||||
type = 0, ---@type MGMT_TYPE
|
||||
length = 0,
|
||||
data = {}
|
||||
}
|
||||
@ -591,22 +556,8 @@ function comms.mgmt_packet()
|
||||
---@class mgmt_packet
|
||||
local public = {}
|
||||
|
||||
-- check that type is known
|
||||
local function _scada_type_valid()
|
||||
return self.type == SCADA_MGMT_TYPE.ESTABLISH or
|
||||
self.type == SCADA_MGMT_TYPE.KEEP_ALIVE or
|
||||
self.type == SCADA_MGMT_TYPE.CLOSE or
|
||||
self.type == SCADA_MGMT_TYPE.REMOTE_LINKED or
|
||||
self.type == SCADA_MGMT_TYPE.RTU_ADVERT or
|
||||
self.type == SCADA_MGMT_TYPE.RTU_DEV_REMOUNT or
|
||||
self.type == SCADA_MGMT_TYPE.RTU_TONE_ALARM or
|
||||
self.type == SCADA_MGMT_TYPE.DIAG_TONE_GET or
|
||||
self.type == SCADA_MGMT_TYPE.DIAG_TONE_SET or
|
||||
self.type == SCADA_MGMT_TYPE.DIAG_ALARM_SET
|
||||
end
|
||||
|
||||
-- make a SCADA management packet
|
||||
---@param packet_type SCADA_MGMT_TYPE
|
||||
---@param packet_type MGMT_TYPE
|
||||
---@param data table
|
||||
function public.make(packet_type, data)
|
||||
if type(data) == "table" then
|
||||
@ -638,7 +589,6 @@ function comms.mgmt_packet()
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||
ok = _scada_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
@ -679,7 +629,7 @@ function comms.crdn_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
raw = {},
|
||||
type = 0, ---@type SCADA_CRDN_TYPE
|
||||
type = 0, ---@type CRDN_TYPE
|
||||
length = 0,
|
||||
data = {}
|
||||
}
|
||||
@ -687,20 +637,8 @@ function comms.crdn_packet()
|
||||
---@class crdn_packet
|
||||
local public = {}
|
||||
|
||||
-- check that type is known
|
||||
---@nodiscard
|
||||
local function _crdn_type_valid()
|
||||
return self.type == SCADA_CRDN_TYPE.INITIAL_BUILDS or
|
||||
self.type == SCADA_CRDN_TYPE.FAC_BUILDS or
|
||||
self.type == SCADA_CRDN_TYPE.FAC_STATUS or
|
||||
self.type == SCADA_CRDN_TYPE.FAC_CMD or
|
||||
self.type == SCADA_CRDN_TYPE.UNIT_BUILDS or
|
||||
self.type == SCADA_CRDN_TYPE.UNIT_STATUSES or
|
||||
self.type == SCADA_CRDN_TYPE.UNIT_CMD
|
||||
end
|
||||
|
||||
-- make a coordinator packet
|
||||
---@param packet_type SCADA_CRDN_TYPE
|
||||
---@param packet_type CRDN_TYPE
|
||||
---@param data table
|
||||
function public.make(packet_type, data)
|
||||
if type(data) == "table" then
|
||||
@ -732,7 +670,6 @@ function comms.crdn_packet()
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||
ok = _crdn_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
@ -767,92 +704,4 @@ function comms.crdn_packet()
|
||||
return public
|
||||
end
|
||||
|
||||
-- coordinator API (CAPI) packet
|
||||
---@todo implement for pocket access, set enum type for self.type
|
||||
---@nodiscard
|
||||
function comms.capi_packet()
|
||||
local self = {
|
||||
frame = nil,
|
||||
raw = {},
|
||||
type = 0,
|
||||
length = 0,
|
||||
data = {}
|
||||
}
|
||||
|
||||
---@class capi_packet
|
||||
local public = {}
|
||||
|
||||
local function _capi_type_valid()
|
||||
---@todo
|
||||
return false
|
||||
end
|
||||
|
||||
-- make a coordinator API packet
|
||||
---@param packet_type CAPI_TYPE
|
||||
---@param data table
|
||||
function public.make(packet_type, data)
|
||||
if type(data) == "table" then
|
||||
-- packet accessor properties
|
||||
self.type = packet_type
|
||||
self.length = #data
|
||||
self.data = data
|
||||
|
||||
-- populate raw array
|
||||
self.raw = { self.type }
|
||||
for i = 1, #data do
|
||||
insert(self.raw, data[i])
|
||||
end
|
||||
else
|
||||
log.error("comms.capi_packet.make(): data not table")
|
||||
end
|
||||
end
|
||||
|
||||
-- decode a coordinator API packet from a SCADA frame
|
||||
---@param frame scada_packet
|
||||
---@return boolean success
|
||||
function public.decode(frame)
|
||||
if frame then
|
||||
self.frame = frame
|
||||
|
||||
if frame.protocol() == PROTOCOL.COORD_API then
|
||||
local ok = frame.length() >= 1
|
||||
|
||||
if ok then
|
||||
local data = frame.data()
|
||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||
ok = _capi_type_valid()
|
||||
end
|
||||
|
||||
return ok
|
||||
else
|
||||
log.debug("attempted COORD_API parse of incorrect protocol " .. frame.protocol(), true)
|
||||
return false
|
||||
end
|
||||
else
|
||||
log.debug("nil frame encountered", true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- get raw to send
|
||||
---@nodiscard
|
||||
function public.raw_sendable() return self.raw end
|
||||
|
||||
-- get this packet as a frame with an immutable relation to this object
|
||||
---@nodiscard
|
||||
function public.get()
|
||||
---@class capi_frame
|
||||
local frame = {
|
||||
scada_frame = self.frame,
|
||||
type = self.type,
|
||||
length = self.length,
|
||||
data = self.data
|
||||
}
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
return public
|
||||
end
|
||||
|
||||
return comms
|
||||
|
@ -8,7 +8,7 @@ local cc_strings = require("cc.strings")
|
||||
local util = {}
|
||||
|
||||
-- scada-common version
|
||||
util.version = "1.0.2"
|
||||
util.version = "1.1.0"
|
||||
|
||||
-- ENVIRONMENT CONSTANTS --
|
||||
|
||||
@ -76,25 +76,12 @@ function util.strval(val)
|
||||
end
|
||||
end
|
||||
|
||||
-- repeat a string n times
|
||||
---@nodiscard
|
||||
---@param str string
|
||||
---@param n integer
|
||||
---@return string
|
||||
function util.strrep(str, n)
|
||||
local repeated = ""
|
||||
|
||||
for _ = 1, n do repeated = repeated .. str end
|
||||
|
||||
return repeated
|
||||
end
|
||||
|
||||
-- repeat a space n times
|
||||
---@nodiscard
|
||||
---@param n integer
|
||||
---@return string
|
||||
function util.spaces(n)
|
||||
return util.strrep(" ", n)
|
||||
return string.rep(" ", n)
|
||||
end
|
||||
|
||||
-- pad text to a minimum width
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
local databus = require("supervisor.databus")
|
||||
|
||||
local style = require("supervisor.panel.style")
|
||||
|
||||
local core = require("graphics.core")
|
||||
|
||||
local Div = require("graphics.elements.div")
|
||||
@ -15,28 +17,31 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local cpair = core.cpair
|
||||
|
||||
local black_lg = style.black_lg
|
||||
local lg_white = style.lg_white
|
||||
|
||||
-- create a pocket diagnostics list entry
|
||||
---@param parent graphics_element parent
|
||||
---@param id integer PDG session ID
|
||||
local function init(parent, id)
|
||||
-- root div
|
||||
local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true}
|
||||
local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=cpair(colors.black,colors.white)}
|
||||
local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=style.bw_fg_bg}
|
||||
|
||||
local ps_prefix = "pdg_" .. id .. "_"
|
||||
|
||||
TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
local pdg_addr = TextBox{parent=entry,x=1,y=2,text="@ C ??",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)}
|
||||
TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=black_lg}
|
||||
local pdg_addr = TextBox{parent=entry,x=1,y=2,text="@ C ??",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=black_lg,nav_active=cpair(colors.gray,colors.black)}
|
||||
TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=black_lg}
|
||||
pdg_addr.register(databus.ps, ps_prefix .. "addr", pdg_addr.set_value)
|
||||
|
||||
TextBox{parent=entry,x=10,y=2,text="FW:",width=3,height=1}
|
||||
local pdg_fw_v = TextBox{parent=entry,x=14,y=2,text=" ------- ",width=20,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local pdg_fw_v = TextBox{parent=entry,x=14,y=2,text=" ------- ",width=20,height=1,fg_bg=lg_white}
|
||||
pdg_fw_v.register(databus.ps, ps_prefix .. "fw", pdg_fw_v.set_value)
|
||||
|
||||
TextBox{parent=entry,x=35,y=2,text="RTT:",width=4,height=1}
|
||||
local pdg_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local pdg_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=lg_white}
|
||||
TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=lg_white}
|
||||
pdg_rtt.register(databus.ps, ps_prefix .. "rtt", pdg_rtt.update)
|
||||
pdg_rtt.register(databus.ps, ps_prefix .. "rtt_color", pdg_rtt.recolor)
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
local databus = require("supervisor.databus")
|
||||
|
||||
local style = require("supervisor.panel.style")
|
||||
|
||||
local core = require("graphics.core")
|
||||
|
||||
local Div = require("graphics.elements.div")
|
||||
@ -15,32 +17,35 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local cpair = core.cpair
|
||||
|
||||
local black_lg = style.black_lg
|
||||
local lg_white = style.lg_white
|
||||
|
||||
-- create an RTU list entry
|
||||
---@param parent graphics_element parent
|
||||
---@param id integer RTU session ID
|
||||
local function init(parent, id)
|
||||
-- root div
|
||||
local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true}
|
||||
local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=cpair(colors.black,colors.white)}
|
||||
local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=style.bw_fg_bg}
|
||||
|
||||
local ps_prefix = "rtu_" .. id .. "_"
|
||||
|
||||
TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
local rtu_addr = TextBox{parent=entry,x=1,y=2,text="@ C ??",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)}
|
||||
TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
TextBox{parent=entry,x=1,y=1,text="",width=8,height=1,fg_bg=black_lg}
|
||||
local rtu_addr = TextBox{parent=entry,x=1,y=2,text="@ C ??",alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=black_lg,nav_active=cpair(colors.gray,colors.black)}
|
||||
TextBox{parent=entry,x=1,y=3,text="",width=8,height=1,fg_bg=black_lg}
|
||||
rtu_addr.register(databus.ps, ps_prefix .. "addr", rtu_addr.set_value)
|
||||
|
||||
TextBox{parent=entry,x=10,y=2,text="UNITS:",width=7,height=1}
|
||||
local unit_count = DataIndicator{parent=entry,x=17,y=2,label="",unit="",format="%2d",value=0,width=2,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local unit_count = DataIndicator{parent=entry,x=17,y=2,label="",unit="",format="%2d",value=0,width=2,fg_bg=style.gray_white}
|
||||
unit_count.register(databus.ps, ps_prefix .. "units", unit_count.set_value)
|
||||
|
||||
TextBox{parent=entry,x=21,y=2,text="FW:",width=3,height=1}
|
||||
local rtu_fw_v = TextBox{parent=entry,x=25,y=2,text=" ------- ",width=9,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local rtu_fw_v = TextBox{parent=entry,x=25,y=2,text=" ------- ",width=9,height=1,fg_bg=lg_white}
|
||||
rtu_fw_v.register(databus.ps, ps_prefix .. "fw", rtu_fw_v.set_value)
|
||||
|
||||
TextBox{parent=entry,x=36,y=2,text="RTT:",width=4,height=1}
|
||||
local rtu_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local rtu_rtt = DataIndicator{parent=entry,x=40,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=lg_white}
|
||||
TextBox{parent=entry,x=46,y=2,text="ms",width=4,height=1,fg_bg=lg_white}
|
||||
rtu_rtt.register(databus.ps, ps_prefix .. "rtt", rtu_rtt.update)
|
||||
rtu_rtt.register(databus.ps, ps_prefix .. "rtt_color", rtu_rtt.recolor)
|
||||
|
||||
|
@ -29,6 +29,14 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
||||
|
||||
local cpair = core.cpair
|
||||
|
||||
local bw_fg_bg = style.bw_fg_bg
|
||||
|
||||
local black_lg = style.black_lg
|
||||
local lg_white = style.lg_white
|
||||
local gry_wht = style.gray_white
|
||||
|
||||
local ind_grn = style.ind_grn
|
||||
|
||||
-- create new front panel view
|
||||
---@param panel graphics_element main displaybox
|
||||
local function init(panel)
|
||||
@ -45,26 +53,26 @@ local function init(panel)
|
||||
local system = Div{parent=main_page,width=14,height=17,x=2,y=2}
|
||||
|
||||
local on = LED{parent=system,label="STATUS",colors=cpair(colors.green,colors.red)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=cpair(colors.green,colors.green_off)}
|
||||
local heartbeat = LED{parent=system,label="HEARTBEAT",colors=ind_grn}
|
||||
on.update(true)
|
||||
system.line_break()
|
||||
|
||||
heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
|
||||
|
||||
local modem = LED{parent=system,label="MODEM",colors=cpair(colors.green,colors.green_off)}
|
||||
local modem = LED{parent=system,label="MODEM",colors=ind_grn}
|
||||
system.line_break()
|
||||
|
||||
modem.register(databus.ps, "has_modem", modem.update)
|
||||
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local comp_id = util.sprintf("(%d)", os.getComputerID())
|
||||
TextBox{parent=system,x=9,y=4,width=6,height=1,text=comp_id,fg_bg=cpair(colors.lightGray,colors.ivory)}
|
||||
TextBox{parent=system,x=9,y=4,width=6,height=1,text=comp_id,fg_bg=style.fp_label}
|
||||
|
||||
--
|
||||
-- about footer
|
||||
--
|
||||
|
||||
local about = Div{parent=main_page,width=15,height=3,x=1,y=16,fg_bg=cpair(colors.lightGray,colors.ivory)}
|
||||
local about = Div{parent=main_page,width=15,height=3,x=1,y=16,fg_bg=style.fp_label}
|
||||
local fw_v = TextBox{parent=about,x=1,y=1,text="FW: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
local comms_v = TextBox{parent=about,x=1,y=2,text="NT: v00.00.00",alignment=TEXT_ALIGN.LEFT,height=1}
|
||||
|
||||
@ -82,25 +90,25 @@ local function init(panel)
|
||||
|
||||
for i = 1, config.NUM_REACTORS do
|
||||
local ps_prefix = "plc_" .. i .. "_"
|
||||
local plc_entry = Div{parent=plc_list,height=3,fg_bg=cpair(colors.black,colors.white)}
|
||||
local plc_entry = Div{parent=plc_list,height=3,fg_bg=bw_fg_bg}
|
||||
|
||||
TextBox{parent=plc_entry,x=1,y=1,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
TextBox{parent=plc_entry,x=1,y=2,text="UNIT "..i,alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
TextBox{parent=plc_entry,x=1,y=3,text="",width=8,height=1,fg_bg=cpair(colors.black,colors.lightGray)}
|
||||
TextBox{parent=plc_entry,x=1,y=1,text="",width=8,height=1,fg_bg=black_lg}
|
||||
TextBox{parent=plc_entry,x=1,y=2,text="UNIT "..i,alignment=TEXT_ALIGN.CENTER,width=8,height=1,fg_bg=black_lg}
|
||||
TextBox{parent=plc_entry,x=1,y=3,text="",width=8,height=1,fg_bg=black_lg}
|
||||
|
||||
local conn = LED{parent=plc_entry,x=10,y=2,label="LINK",colors=cpair(colors.green,colors.green_off)}
|
||||
local conn = LED{parent=plc_entry,x=10,y=2,label="LINK",colors=ind_grn}
|
||||
conn.register(databus.ps, ps_prefix .. "conn", conn.update)
|
||||
|
||||
local plc_addr = TextBox{parent=plc_entry,x=17,y=2,text=" --- ",width=5,height=1,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local plc_addr = TextBox{parent=plc_entry,x=17,y=2,text=" --- ",width=5,height=1,fg_bg=gry_wht}
|
||||
plc_addr.register(databus.ps, ps_prefix .. "addr", plc_addr.set_value)
|
||||
|
||||
TextBox{parent=plc_entry,x=23,y=2,text="FW:",width=3,height=1}
|
||||
local plc_fw_v = TextBox{parent=plc_entry,x=27,y=2,text=" ------- ",width=9,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local plc_fw_v = TextBox{parent=plc_entry,x=27,y=2,text=" ------- ",width=9,height=1,fg_bg=lg_white}
|
||||
plc_fw_v.register(databus.ps, ps_prefix .. "fw", plc_fw_v.set_value)
|
||||
|
||||
TextBox{parent=plc_entry,x=37,y=2,text="RTT:",width=4,height=1}
|
||||
local plc_rtt = DataIndicator{parent=plc_entry,x=42,y=2,label="",unit="",format="%4d",value=0,width=4,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
TextBox{parent=plc_entry,x=47,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local plc_rtt = DataIndicator{parent=plc_entry,x=42,y=2,label="",unit="",format="%4d",value=0,width=4,fg_bg=lg_white}
|
||||
TextBox{parent=plc_entry,x=47,y=2,text="ms",width=4,height=1,fg_bg=lg_white}
|
||||
plc_rtt.register(databus.ps, ps_prefix .. "rtt", plc_rtt.update)
|
||||
plc_rtt.register(databus.ps, ps_prefix .. "rtt_color", plc_rtt.recolor)
|
||||
|
||||
@ -116,22 +124,22 @@ local function init(panel)
|
||||
-- coordinator page
|
||||
|
||||
local crd_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
||||
local crd_box = Div{parent=crd_page,x=2,y=2,width=49,height=4,fg_bg=cpair(colors.black,colors.white)}
|
||||
local crd_box = Div{parent=crd_page,x=2,y=2,width=49,height=4,fg_bg=bw_fg_bg}
|
||||
|
||||
local crd_conn = LED{parent=crd_box,x=2,y=2,label="CONNECTION",colors=cpair(colors.green,colors.green_off)}
|
||||
local crd_conn = LED{parent=crd_box,x=2,y=2,label="CONNECTION",colors=ind_grn}
|
||||
crd_conn.register(databus.ps, "crd_conn", crd_conn.update)
|
||||
|
||||
TextBox{parent=crd_box,x=4,y=3,text="COMPUTER",width=8,height=1,fg_bg=cpair(colors.gray,colors.white)}
|
||||
local crd_addr = TextBox{parent=crd_box,x=13,y=3,text="---",width=5,height=1,fg_bg=cpair(colors.gray,colors.white)}
|
||||
TextBox{parent=crd_box,x=4,y=3,text="COMPUTER",width=8,height=1,fg_bg=gry_wht}
|
||||
local crd_addr = TextBox{parent=crd_box,x=13,y=3,text="---",width=5,height=1,fg_bg=gry_wht}
|
||||
crd_addr.register(databus.ps, "crd_addr", crd_addr.set_value)
|
||||
|
||||
TextBox{parent=crd_box,x=22,y=2,text="FW:",width=3,height=1}
|
||||
local crd_fw_v = TextBox{parent=crd_box,x=26,y=2,text=" ------- ",width=9,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local crd_fw_v = TextBox{parent=crd_box,x=26,y=2,text=" ------- ",width=9,height=1,fg_bg=lg_white}
|
||||
crd_fw_v.register(databus.ps, "crd_fw", crd_fw_v.set_value)
|
||||
|
||||
TextBox{parent=crd_box,x=36,y=2,text="RTT:",width=4,height=1}
|
||||
local crd_rtt = DataIndicator{parent=crd_box,x=41,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
TextBox{parent=crd_box,x=47,y=2,text="ms",width=4,height=1,fg_bg=cpair(colors.lightGray,colors.white)}
|
||||
local crd_rtt = DataIndicator{parent=crd_box,x=41,y=2,label="",unit="",format="%5d",value=0,width=5,fg_bg=lg_white}
|
||||
TextBox{parent=crd_box,x=47,y=2,text="ms",width=4,height=1,fg_bg=lg_white}
|
||||
crd_rtt.register(databus.ps, "crd_rtt", crd_rtt.update)
|
||||
crd_rtt.register(databus.ps, "crd_rtt_color", crd_rtt.recolor)
|
||||
|
||||
@ -155,7 +163,7 @@ local function init(panel)
|
||||
{ name = "PKT", color = cpair(colors.black, colors.ivory) },
|
||||
}
|
||||
|
||||
TabBar{parent=panel,y=2,tabs=tabs,min_width=9,callback=page_pane.set_value,fg_bg=cpair(colors.black,colors.white)}
|
||||
TabBar{parent=panel,y=2,tabs=tabs,min_width=9,callback=page_pane.set_value,fg_bg=bw_fg_bg}
|
||||
|
||||
-- link RTU/PDG list management to PGI
|
||||
pgi.link_elements(rtu_list, rtu_entry, pdg_list, pdg_entry)
|
||||
|
@ -39,4 +39,16 @@ style.colors = {
|
||||
{ c = colors.brown, hex = 0x672223 } -- RED OFF
|
||||
}
|
||||
|
||||
-- COMMON COLOR PAIRS --
|
||||
|
||||
style.text_fg_bg = cpair(colors.black, colors.ivory)
|
||||
style.bw_fg_bg = cpair(colors.black, colors.white)
|
||||
style.fp_label = cpair(colors.lightGray, colors.ivory)
|
||||
|
||||
style.black_lg = cpair(colors.black, colors.lightGray)
|
||||
style.lg_white = cpair(colors.lightGray, colors.white)
|
||||
style.gray_white = cpair(colors.gray, colors.white)
|
||||
|
||||
style.ind_grn = cpair(colors.green, colors.green_off)
|
||||
|
||||
return style
|
||||
|
@ -10,8 +10,8 @@ local svqtypes = require("supervisor.session.svqtypes")
|
||||
local coordinator = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local CRDN_TYPE = comms.CRDN_TYPE
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
local FAC_COMMAND = comms.FAC_COMMAND
|
||||
|
||||
@ -94,7 +94,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
|
||||
-- send a CRDN packet
|
||||
---@param msg_type SCADA_CRDN_TYPE
|
||||
---@param msg_type CRDN_TYPE
|
||||
---@param msg table
|
||||
local function _send(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -108,7 +108,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -130,12 +130,12 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
unit_builds[unit.get_id()] = unit.get_build()
|
||||
end
|
||||
|
||||
_send(SCADA_CRDN_TYPE.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
||||
_send(CRDN_TYPE.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
||||
end
|
||||
|
||||
-- send facility builds
|
||||
local function _send_fac_builds()
|
||||
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build() })
|
||||
_send(CRDN_TYPE.FAC_BUILDS, { facility.get_build() })
|
||||
end
|
||||
|
||||
-- send unit builds
|
||||
@ -147,7 +147,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
builds[unit.get_id()] = unit.get_build()
|
||||
end
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
end
|
||||
|
||||
-- send facility status
|
||||
@ -158,7 +158,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
facility.get_alarm_tones()
|
||||
}
|
||||
|
||||
_send(SCADA_CRDN_TYPE.FAC_STATUS, status)
|
||||
_send(CRDN_TYPE.FAC_STATUS, status)
|
||||
end
|
||||
|
||||
-- send unit statuses
|
||||
@ -178,7 +178,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
}
|
||||
end
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_STATUSES, status)
|
||||
_send(CRDN_TYPE.UNIT_STATUSES, status)
|
||||
end
|
||||
|
||||
-- handle a packet
|
||||
@ -200,7 +200,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
-- process packet
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -219,7 +219,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
else
|
||||
@ -227,22 +227,22 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||
---@cast pkt crdn_frame
|
||||
if pkt.type == SCADA_CRDN_TYPE.INITIAL_BUILDS then
|
||||
if pkt.type == CRDN_TYPE.INITIAL_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.FAC_BUILDS then
|
||||
elseif pkt.type == CRDN_TYPE.FAC_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.fac_builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.FAC_CMD then
|
||||
elseif pkt.type == CRDN_TYPE.FAC_CMD then
|
||||
if pkt.length >= 1 then
|
||||
local cmd = pkt.data[1]
|
||||
|
||||
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||
facility.scram_all()
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
elseif cmd == FAC_COMMAND.STOP then
|
||||
facility.auto_stop()
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
elseif cmd == FAC_COMMAND.START then
|
||||
if pkt.length == 6 then
|
||||
---@type coord_auto_config
|
||||
@ -254,22 +254,22 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
limits = pkt.data[6]
|
||||
}
|
||||
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, table.unpack(facility.auto_start(config)) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, table.unpack(facility.auto_start(config)) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN auto start (with configuration) packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||
facility.ack_all()
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||
if pkt.length == 2 then
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, facility.set_waste_product(pkt.data[2]) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_waste_product(pkt.data[2]) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN set waste mode packet length mismatch")
|
||||
end
|
||||
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||
if pkt.length == 2 then
|
||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2]) })
|
||||
_send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2]) })
|
||||
else
|
||||
log.debug(log_header .. "CRDN set pu fallback packet length mismatch")
|
||||
end
|
||||
@ -279,10 +279,10 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
else
|
||||
log.debug(log_header .. "CRDN facility command packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
||||
elseif pkt.type == CRDN_TYPE.UNIT_BUILDS then
|
||||
-- acknowledgement to coordinator receiving builds
|
||||
self.acks.unit_builds = true
|
||||
elseif pkt.type == SCADA_CRDN_TYPE.UNIT_CMD then
|
||||
elseif pkt.type == CRDN_TYPE.UNIT_CMD then
|
||||
if pkt.length >= 2 then
|
||||
-- get command and unit id
|
||||
local cmd = pkt.data[1]
|
||||
@ -315,7 +315,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
end
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||
unit.ack_all()
|
||||
_send(SCADA_CRDN_TYPE.UNIT_CMD, { cmd, uid, true })
|
||||
_send(CRDN_TYPE.UNIT_CMD, { cmd, uid, true })
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
||||
if pkt.length == 3 then
|
||||
unit.ack_alarm(pkt.data[3])
|
||||
@ -331,7 +331,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
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
|
||||
facility.set_group(unit.get_id(), pkt.data[3])
|
||||
_send(SCADA_CRDN_TYPE.UNIT_CMD, { cmd, uid, pkt.data[3] })
|
||||
_send(CRDN_TYPE.UNIT_CMD, { cmd, uid, pkt.data[3] })
|
||||
else
|
||||
log.debug(log_header .. "CRDN unit command set group missing group id")
|
||||
end
|
||||
@ -374,7 +374,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println("connection to coordinator " .. id .. " closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -406,7 +406,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
|
||||
if cmd.key == CRD_S_DATA.CMD_ACK then
|
||||
local ack = cmd.val ---@type coord_ack
|
||||
_send(SCADA_CRDN_TYPE.UNIT_CMD, { ack.cmd, ack.unit, ack.ack })
|
||||
_send(CRDN_TYPE.UNIT_CMD, { ack.cmd, ack.unit, ack.ack })
|
||||
elseif cmd.key == CRD_S_DATA.RESEND_PLC_BUILD then
|
||||
-- re-send PLC build
|
||||
-- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update
|
||||
@ -419,7 +419,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
local unit = self.units[unit_id] ---@type reactor_unit
|
||||
builds[unit_id] = unit.get_build(-1)
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
elseif cmd.key == CRD_S_DATA.RESEND_RTU_BUILD then
|
||||
local unit_id = cmd.val.unit
|
||||
if unit_id > 0 then
|
||||
@ -433,14 +433,14 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
local unit = self.units[unit_id] ---@type reactor_unit
|
||||
builds[unit_id] = unit.get_build(cmd.val.type)
|
||||
|
||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||
else
|
||||
-- re-send facility RTU builds
|
||||
-- retry logic will be kept as-is, so as long as no retry is needed, this will be a small update
|
||||
self.retry_times.f_builds_packet = util.time() + PARTIAL_RETRY_PERIOD
|
||||
self.acks.fac_builds = false
|
||||
|
||||
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type) })
|
||||
_send(CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type) })
|
||||
end
|
||||
else
|
||||
log.error(log_header .. "unsupported data command received in in_queue (this is a bug)", true)
|
||||
@ -474,7 +474,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -12,7 +12,7 @@ local plc = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local RPLC_TYPE = comms.RPLC_TYPE
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local PLC_AUTO_ACK = comms.PLC_AUTO_ACK
|
||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||
|
||||
@ -258,7 +258,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -482,7 +482,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
end
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -501,7 +501,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
else
|
||||
@ -595,7 +595,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println("connection to reactor " .. reactor_id .. " PLC closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -726,7 +726,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -7,7 +7,7 @@ local databus = require("supervisor.databus")
|
||||
local pocket = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
-- retry time constants in ms
|
||||
-- local INITIAL_WAIT = 1500
|
||||
@ -76,7 +76,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -108,7 +108,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
-- process packet
|
||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -127,13 +127,13 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_TONE_GET then
|
||||
elseif pkt.type == MGMT_TYPE.DIAG_TONE_GET then
|
||||
-- get the state of alarm tones
|
||||
_send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_GET, facility.get_alarm_tones())
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_TONE_SET then
|
||||
_send_mgmt(MGMT_TYPE.DIAG_TONE_GET, facility.get_alarm_tones())
|
||||
elseif pkt.type == MGMT_TYPE.DIAG_TONE_SET then
|
||||
local valid = false
|
||||
|
||||
-- attempt to set a tone state
|
||||
@ -144,7 +144,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
|
||||
-- try to set tone states, then send back if testing is allowed
|
||||
local allow_testing, test_tone_states = facility.diag_set_test_tone(pkt.data[1], pkt.data[2])
|
||||
_send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_SET, { allow_testing, test_tone_states })
|
||||
_send_mgmt(MGMT_TYPE.DIAG_TONE_SET, { allow_testing, test_tone_states })
|
||||
else
|
||||
log.debug(log_header .. "SCADA diag tone set packet data type mismatch")
|
||||
end
|
||||
@ -155,8 +155,8 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
log.debug(log_header .. "DIAG_TONE_SET is blocked without HMAC for security")
|
||||
end
|
||||
|
||||
if not valid then _send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_SET, { false }) end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_ALARM_SET then
|
||||
if not valid then _send_mgmt(MGMT_TYPE.DIAG_TONE_SET, { false }) end
|
||||
elseif pkt.type == MGMT_TYPE.DIAG_ALARM_SET then
|
||||
local valid = false
|
||||
|
||||
-- attempt to set an alarm state
|
||||
@ -167,7 +167,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
|
||||
-- try to set alarm states, then send back if testing is allowed
|
||||
local allow_testing, test_alarm_states = facility.diag_set_test_alarm(pkt.data[1], pkt.data[2])
|
||||
_send_mgmt(SCADA_MGMT_TYPE.DIAG_ALARM_SET, { allow_testing, test_alarm_states })
|
||||
_send_mgmt(MGMT_TYPE.DIAG_ALARM_SET, { allow_testing, test_alarm_states })
|
||||
else
|
||||
log.debug(log_header .. "SCADA diag alarm set packet data type mismatch")
|
||||
end
|
||||
@ -178,7 +178,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
log.debug(log_header .. "DIAG_ALARM_SET is blocked without HMAC for security")
|
||||
end
|
||||
|
||||
if not valid then _send_mgmt(SCADA_MGMT_TYPE.DIAG_ALARM_SET, { false }) end
|
||||
if not valid then _send_mgmt(MGMT_TYPE.DIAG_ALARM_SET, { false }) end
|
||||
else
|
||||
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
||||
end
|
||||
@ -204,7 +204,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println("connection to pocket diag session " .. id .. " closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -261,7 +261,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
|
@ -22,7 +22,7 @@ local svrs_turbinev = require("supervisor.session.rtu.turbinev")
|
||||
local rtu = {}
|
||||
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||
|
||||
local PERIODICS = {
|
||||
@ -223,7 +223,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
end
|
||||
|
||||
-- send a SCADA management packet
|
||||
---@param msg_type SCADA_MGMT_TYPE
|
||||
---@param msg_type MGMT_TYPE
|
||||
---@param msg table
|
||||
local function _send_mgmt(msg_type, msg)
|
||||
local s_pkt = comms.scada_packet()
|
||||
@ -262,7 +262,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||
---@cast pkt mgmt_frame
|
||||
-- handle management packet
|
||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
||||
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||
-- keep alive reply
|
||||
if pkt.length == 2 then
|
||||
local srv_start = pkt.data[1]
|
||||
@ -281,17 +281,17 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
else
|
||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||
end
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
||||
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||
-- close the session
|
||||
_close()
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.RTU_ADVERT then
|
||||
elseif pkt.type == MGMT_TYPE.RTU_ADVERT then
|
||||
-- RTU unit advertisement
|
||||
log.debug(log_header .. "received updated advertisement")
|
||||
self.advert = pkt.data
|
||||
|
||||
-- handle advertisement; this will re-create all unit sub-sessions
|
||||
_handle_advertisement()
|
||||
elseif pkt.type == SCADA_MGMT_TYPE.RTU_DEV_REMOUNT then
|
||||
elseif pkt.type == MGMT_TYPE.RTU_DEV_REMOUNT then
|
||||
if pkt.length == 1 then
|
||||
local unit_id = pkt.data[1]
|
||||
if self.units[unit_id] ~= nil then
|
||||
@ -322,7 +322,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
-- close the connection
|
||||
function public.close()
|
||||
_close()
|
||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
||||
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||
println(log_header .. "connection to RTU closed by server")
|
||||
log.info(log_header .. "session closed by server")
|
||||
end
|
||||
@ -387,7 +387,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
|
||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
_send_mgmt(MGMT_TYPE.KEEP_ALIVE, { util.time() })
|
||||
periodics.keep_alive = 0
|
||||
end
|
||||
|
||||
@ -395,7 +395,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
||||
|
||||
periodics.alarm_tones = periodics.alarm_tones + elapsed
|
||||
if periodics.alarm_tones >= PERIODICS.ALARM_TONES then
|
||||
_send_mgmt(SCADA_MGMT_TYPE.RTU_TONE_ALARM, { facility.get_alarm_tones() })
|
||||
_send_mgmt(MGMT_TYPE.RTU_TONE_ALARM, { facility.get_alarm_tones() })
|
||||
periodics.alarm_tones = 0
|
||||
end
|
||||
|
||||
|
@ -11,7 +11,7 @@ local supervisor = {}
|
||||
local PROTOCOL = comms.PROTOCOL
|
||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
||||
local MGMT_TYPE = comms.MGMT_TYPE
|
||||
|
||||
-- supervisory controller communications
|
||||
---@nodiscard
|
||||
@ -58,7 +58,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
local s_pkt = comms.scada_packet()
|
||||
local m_pkt = comms.mgmt_packet()
|
||||
|
||||
m_pkt.make(SCADA_MGMT_TYPE.ESTABLISH, { ack, data })
|
||||
m_pkt.make(MGMT_TYPE.ESTABLISH, { ack, data })
|
||||
s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
|
||||
|
||||
nic.transmit(packet.remote_channel(), svr_channel, s_pkt)
|
||||
@ -147,7 +147,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
@ -221,7 +221,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
@ -275,7 +275,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
@ -291,7 +291,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
end
|
||||
|
||||
_send_establish(packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
|
||||
elseif dev_type == DEVICE_TYPE.CRDN then
|
||||
elseif dev_type == DEVICE_TYPE.CRD then
|
||||
-- this is an attempt to establish a new coordinator session
|
||||
local s_id = svsessions.establish_crd_session(src_addr, firmware_v)
|
||||
|
||||
@ -342,7 +342,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
||||
if session ~= nil then
|
||||
-- pass the packet onto the session handler
|
||||
session.in_queue.push_packet(packet)
|
||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||
-- establish a new session
|
||||
local last_ack = self.last_est_acks[src_addr]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user