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.hint.setType": true,
|
||||||
"Lua.diagnostics.disable": [
|
"Lua.diagnostics.disable": [
|
||||||
"duplicate-set-field"
|
"duplicate-set-field",
|
||||||
|
"inject-field"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ local println = util.println
|
|||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
local MGMT_TYPE = comms.MGMT_TYPE
|
||||||
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
local CRDN_TYPE = comms.CRDN_TYPE
|
||||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||||
local FAC_COMMAND = comms.FAC_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)
|
apisessions.init(nic)
|
||||||
|
|
||||||
-- send a packet to the supervisor
|
-- 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
|
---@param msg table
|
||||||
local function _send_sv(protocol, msg_type, msg)
|
local function _send_sv(protocol, msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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 s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_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())
|
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)
|
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
|
-- attempt connection establishment
|
||||||
local function _send_establish()
|
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
|
end
|
||||||
|
|
||||||
-- keep alive ack
|
-- keep alive ack
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_keep_alive_ack(srv_time)
|
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
|
end
|
||||||
|
|
||||||
-- PUBLIC FUNCTIONS --
|
-- PUBLIC FUNCTIONS --
|
||||||
@ -394,20 +394,20 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
self.sv_linked = false
|
self.sv_linked = false
|
||||||
self.sv_r_seq_num = nil
|
self.sv_r_seq_num = nil
|
||||||
iocontrol.fp_link_state(types.PANEL_LINK_STATE.DISCONNECTED)
|
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
|
end
|
||||||
|
|
||||||
-- send a facility command
|
-- send a facility command
|
||||||
---@param cmd FAC_COMMAND command
|
---@param cmd FAC_COMMAND command
|
||||||
---@param option any? optional option options for the optional options (like waste mode)
|
---@param option any? optional option options for the optional options (like waste mode)
|
||||||
function public.send_fac_command(cmd, option)
|
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
|
end
|
||||||
|
|
||||||
-- send the auto process control configuration with a start command
|
-- send the auto process control configuration with a start command
|
||||||
---@param config coord_auto_config configuration
|
---@param config coord_auto_config configuration
|
||||||
function public.send_auto_start(config)
|
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
|
FAC_COMMAND.START, config.mode, config.burn_target, config.charge_target, config.gen_target, config.limits
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@ -417,7 +417,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
---@param unit integer unit ID
|
---@param unit integer unit ID
|
||||||
---@param option any? optional option options for the optional options (like burn rate)
|
---@param option any? optional option options for the optional options (like burn rate)
|
||||||
function public.send_unit_command(cmd, unit, option)
|
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
|
end
|
||||||
|
|
||||||
-- parse a packet
|
-- parse a packet
|
||||||
@ -426,7 +426,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
---@param reply_to integer
|
---@param reply_to integer
|
||||||
---@param message any
|
---@param message any
|
||||||
---@param distance integer
|
---@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)
|
function public.parse_packet(side, sender, reply_to, message, distance)
|
||||||
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
||||||
local pkt = nil
|
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
|
if crdn_pkt.decode(s_pkt) then
|
||||||
pkt = crdn_pkt.get()
|
pkt = crdn_pkt.get()
|
||||||
end
|
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
|
else
|
||||||
log.debug("attempted parse of illegal packet type " .. s_pkt.protocol(), true)
|
log.debug("attempted parse of illegal packet type " .. s_pkt.protocol(), true)
|
||||||
end
|
end
|
||||||
@ -459,7 +453,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle a packet
|
-- handle a packet
|
||||||
---@param packet mgmt_frame|crdn_frame|capi_frame|nil
|
---@param packet mgmt_frame|crdn_frame|nil
|
||||||
---@return boolean close_ui
|
---@return boolean close_ui
|
||||||
function public.handle_packet(packet)
|
function public.handle_packet(packet)
|
||||||
local was_linked = self.sv_linked
|
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
|
elseif r_chan == pkt_channel then
|
||||||
if not self.sv_linked then
|
if not self.sv_linked then
|
||||||
log.debug("discarding pocket API packet before linked to supervisor")
|
log.debug("discarding pocket API packet before linked to supervisor")
|
||||||
elseif protocol == PROTOCOL.COORD_API then
|
elseif protocol == PROTOCOL.SCADA_CRDN then
|
||||||
---@cast packet capi_frame
|
---@cast packet crdn_frame
|
||||||
-- look for an associated session
|
-- look for an associated session
|
||||||
local session = apisessions.find_session(src_addr)
|
local session = apisessions.find_session(src_addr)
|
||||||
|
|
||||||
-- API packet
|
-- coordinator packet
|
||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
session.in_queue.push_packet(packet)
|
||||||
else
|
else
|
||||||
-- any other packet should be session related, discard it
|
-- 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
|
end
|
||||||
elseif protocol == PROTOCOL.SCADA_MGMT then
|
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast packet mgmt_frame
|
---@cast packet mgmt_frame
|
||||||
@ -497,7 +491,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
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
|
-- establish a new session
|
||||||
-- validate packet and continue
|
-- validate packet and continue
|
||||||
if packet.length == 3 and type(packet.data[1]) == "string" and type(packet.data[2]) == "string" then
|
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
|
if protocol == PROTOCOL.SCADA_CRDN then
|
||||||
---@cast packet crdn_frame
|
---@cast packet crdn_frame
|
||||||
if self.sv_linked then
|
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
|
if packet.length == 2 then
|
||||||
-- record builds
|
-- record builds
|
||||||
local fac_builds = iocontrol.record_facility_builds(packet.data[1])
|
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
|
if fac_builds and unit_builds then
|
||||||
-- acknowledge receipt of builds
|
-- acknowledge receipt of builds
|
||||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.INITIAL_BUILDS, {})
|
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.INITIAL_BUILDS, {})
|
||||||
else
|
else
|
||||||
log.debug("received invalid INITIAL_BUILDS packet")
|
log.debug("received invalid INITIAL_BUILDS packet")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug("INITIAL_BUILDS packet length mismatch")
|
log.debug("INITIAL_BUILDS packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_BUILDS then
|
elseif packet.type == CRDN_TYPE.FAC_BUILDS then
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
-- record facility builds
|
-- record facility builds
|
||||||
if iocontrol.record_facility_builds(packet.data[1]) then
|
if iocontrol.record_facility_builds(packet.data[1]) then
|
||||||
-- acknowledge receipt of builds
|
-- acknowledge receipt of builds
|
||||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_BUILDS, {})
|
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.FAC_BUILDS, {})
|
||||||
else
|
else
|
||||||
log.debug("received invalid FAC_BUILDS packet")
|
log.debug("received invalid FAC_BUILDS packet")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug("FAC_BUILDS packet length mismatch")
|
log.debug("FAC_BUILDS packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_STATUS then
|
elseif packet.type == CRDN_TYPE.FAC_STATUS then
|
||||||
-- update facility status
|
-- update facility status
|
||||||
if not iocontrol.update_facility_status(packet.data) then
|
if not iocontrol.update_facility_status(packet.data) then
|
||||||
log.debug("received invalid FAC_STATUS packet")
|
log.debug("received invalid FAC_STATUS packet")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_CMD then
|
elseif packet.type == CRDN_TYPE.FAC_CMD then
|
||||||
-- facility command acknowledgement
|
-- facility command acknowledgement
|
||||||
if packet.length >= 2 then
|
if packet.length >= 2 then
|
||||||
local cmd = packet.data[1]
|
local cmd = packet.data[1]
|
||||||
@ -613,24 +607,24 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
else
|
else
|
||||||
log.debug("SCADA_CRDN facility command ack packet length mismatch")
|
log.debug("SCADA_CRDN facility command ack packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
elseif packet.type == CRDN_TYPE.UNIT_BUILDS then
|
||||||
-- record builds
|
-- record builds
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
if iocontrol.record_unit_builds(packet.data[1]) then
|
if iocontrol.record_unit_builds(packet.data[1]) then
|
||||||
-- acknowledge receipt of builds
|
-- acknowledge receipt of builds
|
||||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_BUILDS, {})
|
_send_sv(PROTOCOL.SCADA_CRDN, CRDN_TYPE.UNIT_BUILDS, {})
|
||||||
else
|
else
|
||||||
log.debug("received invalid UNIT_BUILDS packet")
|
log.debug("received invalid UNIT_BUILDS packet")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug("UNIT_BUILDS packet length mismatch")
|
log.debug("UNIT_BUILDS packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_STATUSES then
|
elseif packet.type == CRDN_TYPE.UNIT_STATUSES then
|
||||||
-- update statuses
|
-- update statuses
|
||||||
if not iocontrol.update_unit_statuses(packet.data) then
|
if not iocontrol.update_unit_statuses(packet.data) then
|
||||||
log.debug("received invalid UNIT_STATUSES packet")
|
log.debug("received invalid UNIT_STATUSES packet")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_CRDN_TYPE.UNIT_CMD then
|
elseif packet.type == CRDN_TYPE.UNIT_CMD then
|
||||||
-- unit command acknowledgement
|
-- unit command acknowledgement
|
||||||
if packet.length == 3 then
|
if packet.length == 3 then
|
||||||
local cmd = packet.data[1]
|
local cmd = packet.data[1]
|
||||||
@ -672,7 +666,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
elseif protocol == PROTOCOL.SCADA_MGMT then
|
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast packet mgmt_frame
|
---@cast packet mgmt_frame
|
||||||
if self.sv_linked then
|
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
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -690,7 +684,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
else
|
else
|
||||||
log.debug("SCADA keep alive packet length mismatch")
|
log.debug("SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||||
-- handle session close
|
-- handle session close
|
||||||
sv_watchdog.cancel()
|
sv_watchdog.cancel()
|
||||||
self.sv_addr = comms.BROADCAST
|
self.sv_addr = comms.BROADCAST
|
||||||
@ -701,7 +695,7 @@ function coordinator.comms(version, nic, num_units, crd_channel, svr_channel, pk
|
|||||||
else
|
else
|
||||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type)
|
log.debug("received unknown SCADA_MGMT packet type " .. packet.type)
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||||
-- connection with supervisor established
|
-- connection with supervisor established
|
||||||
if packet.length == 2 then
|
if packet.length == 2 then
|
||||||
local est_ack = packet.data[1]
|
local est_ack = packet.data[1]
|
||||||
|
@ -8,8 +8,8 @@ local iocontrol = require("coordinator.iocontrol")
|
|||||||
local pocket = {}
|
local pocket = {}
|
||||||
|
|
||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
-- local CAPI_TYPE = comms.CAPI_TYPE
|
-- local CRDN_TYPE = comms.CRDN_TYPE
|
||||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
local MGMT_TYPE = comms.MGMT_TYPE
|
||||||
|
|
||||||
-- retry time constants in ms
|
-- retry time constants in ms
|
||||||
-- local INITIAL_WAIT = 1500
|
-- 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)
|
iocontrol.fp_pkt_disconnected(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send a CAPI packet
|
-- send a CRDN packet
|
||||||
-----@param msg_type CAPI_TYPE
|
-----@param msg_type CRDN_TYPE
|
||||||
-----@param msg table
|
-----@param msg table
|
||||||
-- local function _send(msg_type, msg)
|
-- local function _send(msg_type, msg)
|
||||||
-- local s_pkt = comms.scada_packet()
|
-- local s_pkt = comms.scada_packet()
|
||||||
-- local c_pkt = comms.capi_packet()
|
-- local c_pkt = comms.crdn_packet()
|
||||||
|
|
||||||
-- c_pkt.make(msg_type, msg)
|
-- 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)
|
-- out_queue.push_packet(s_pkt)
|
||||||
-- self.seq_num = self.seq_num + 1
|
-- self.seq_num = self.seq_num + 1
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
@ -101,7 +101,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle a packet
|
-- handle a packet
|
||||||
---@param pkt mgmt_frame|capi_frame
|
---@param pkt mgmt_frame|crdn_frame
|
||||||
local function _handle_packet(pkt)
|
local function _handle_packet(pkt)
|
||||||
-- check sequence number
|
-- check sequence number
|
||||||
if self.r_seq_num == nil then
|
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()
|
self.conn_watchdog.feed()
|
||||||
|
|
||||||
-- process packet
|
-- process packet
|
||||||
if pkt.scada_frame.protocol() == PROTOCOL.COORD_API then
|
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||||
---@cast pkt capi_frame
|
---@cast pkt crdn_frame
|
||||||
|
|
||||||
-- handle packet by type
|
-- handle packet by type
|
||||||
if pkt.type == nil then
|
if pkt.type == nil then
|
||||||
else
|
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
|
end
|
||||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast pkt mgmt_frame
|
---@cast pkt mgmt_frame
|
||||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
@ -146,7 +146,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_close()
|
||||||
else
|
else
|
||||||
@ -174,7 +174,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
|||||||
-- close the connection
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout)
|
|||||||
|
|
||||||
periodics.keep_alive = periodics.keep_alive + elapsed
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
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
|
periodics.keep_alive = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ local sounder = require("coordinator.sounder")
|
|||||||
|
|
||||||
local apisessions = require("coordinator.session.apisessions")
|
local apisessions = require("coordinator.session.apisessions")
|
||||||
|
|
||||||
local COORDINATOR_VERSION = "v1.0.9"
|
local COORDINATOR_VERSION = "v1.0.10"
|
||||||
|
|
||||||
local println = util.println
|
local println = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
@ -12,6 +12,8 @@ local VerticalBar = require("graphics.elements.indicators.vbar")
|
|||||||
local cpair = core.cpair
|
local cpair = core.cpair
|
||||||
local border = core.border
|
local border = core.border
|
||||||
|
|
||||||
|
local text_fg_bg = style.text_colors
|
||||||
|
|
||||||
-- new boiler view
|
-- new boiler view
|
||||||
---@param root graphics_element parent
|
---@param root graphics_element parent
|
||||||
---@param x integer top left x
|
---@param x integer top left x
|
||||||
@ -20,12 +22,9 @@ local border = core.border
|
|||||||
local function new_view(root, x, y, ps)
|
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 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 status = StateIndicator{parent=boiler,x=9,y=1,states=style.boiler.states,value=1,min_width=12}
|
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 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=lu_col,label="Boil:",unit="mB/t",format="%10.0f",value=0,commas=true,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)
|
status.register(ps, "computed_status", status.update)
|
||||||
temp.register(ps, "temperature", temp.update)
|
temp.register(ps, "temperature", temp.update)
|
||||||
|
@ -18,6 +18,9 @@ local border = core.border
|
|||||||
|
|
||||||
local TEXT_ALIGN = core.TEXT_ALIGN
|
local TEXT_ALIGN = core.TEXT_ALIGN
|
||||||
|
|
||||||
|
local text_fg_bg = style.text_colors
|
||||||
|
local lu_col = style.lu_colors
|
||||||
|
|
||||||
-- new induction matrix view
|
-- new induction matrix view
|
||||||
---@param root graphics_element parent
|
---@param root graphics_element parent
|
||||||
---@param x integer top left x
|
---@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}
|
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=" ",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=cpair(colors.lightGray,colors.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 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 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 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}
|
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 iocontrol = require("coordinator.iocontrol")
|
||||||
|
|
||||||
|
local style = require("coordinator.ui.style")
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
|
|
||||||
local Div = require("graphics.elements.div")
|
local Div = require("graphics.elements.div")
|
||||||
@ -15,6 +17,9 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
|||||||
|
|
||||||
local cpair = core.cpair
|
local cpair = core.cpair
|
||||||
|
|
||||||
|
local text_fg_bg = style.text_colors
|
||||||
|
local lg_wh = style.lg_white
|
||||||
|
|
||||||
-- create a pocket list entry
|
-- create a pocket list entry
|
||||||
---@param parent graphics_element parent
|
---@param parent graphics_element parent
|
||||||
---@param id integer PKT session ID
|
---@param id integer PKT session ID
|
||||||
@ -23,22 +28,22 @@ local function init(parent, id)
|
|||||||
|
|
||||||
-- root div
|
-- root div
|
||||||
local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true}
|
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 .. "_"
|
local ps_prefix = "pkt_" .. id .. "_"
|
||||||
|
|
||||||
TextBox{parent=entry,x=1,y=1,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=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)}
|
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=cpair(colors.black,colors.lightGray)}
|
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)
|
pkt_addr.register(ps, ps_prefix .. "addr", pkt_addr.set_value)
|
||||||
|
|
||||||
TextBox{parent=entry,x=10,y=2,text="FW:",width=3,height=1}
|
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)
|
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}
|
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)}
|
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=cpair(colors.lightGray,colors.white)}
|
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", pkt_rtt.update)
|
||||||
pkt_rtt.register(ps, ps_prefix .. "rtt_color", pkt_rtt.recolor)
|
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 hzd_fg_bg = style.hzd_fg_bg
|
||||||
local dis_colors = style.dis_colors
|
local dis_colors = style.dis_colors
|
||||||
|
|
||||||
|
local gry_wht = style.gray_white
|
||||||
|
|
||||||
local ind_grn = style.ind_grn
|
local ind_grn = style.ind_grn
|
||||||
local ind_yel = style.ind_yel
|
local ind_yel = style.ind_yel
|
||||||
local ind_red = style.ind_red
|
local ind_red = style.ind_red
|
||||||
@ -47,6 +49,10 @@ local period = core.flasher.PERIOD
|
|||||||
local function new_view(root, x, y)
|
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)")
|
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 facility = iocontrol.get_db().facility
|
||||||
local units = iocontrol.get_db().units
|
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 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}
|
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 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=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
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"}
|
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)
|
b_target.register(facility.ps, "process_burn_target", b_target.set_value)
|
||||||
burn_sum.register(facility.ps, "burn_sum", burn_sum.update)
|
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}
|
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 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=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
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"}
|
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)
|
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)
|
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}
|
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 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=cpair(colors.gray,colors.white),fg_bg=bw_fg_bg}
|
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"}
|
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)
|
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)
|
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
|
for i = 1, 4 do
|
||||||
local unit
|
local unit
|
||||||
local tag_fg_bg = cpair(colors.gray,colors.white)
|
local tag_fg_bg = gry_wht
|
||||||
local lim_fg_bg = cpair(colors.lightGray,colors.white)
|
local lim_fg_bg = style.lg_white
|
||||||
local ctl_fg = colors.lightGray
|
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
|
local cur_lu = colors.lightGray
|
||||||
|
|
||||||
if i <= facility.num_units then
|
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)
|
tag_fg_bg = cpair(colors.black,colors.lightBlue)
|
||||||
lim_fg_bg = bw_fg_bg
|
lim_fg_bg = bw_fg_bg
|
||||||
ctl_fg = colors.gray
|
ctl_fg = colors.gray
|
||||||
cur_fg_bg = cpair(colors.black,colors.brown)
|
cur_fg_bg = blk_brn
|
||||||
cur_lu = colors.black
|
cur_lu = colors.black
|
||||||
end
|
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}
|
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_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}
|
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}
|
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}
|
local stat_div = Div{parent=proc,width=22,height=24,x=57,y=6}
|
||||||
|
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
local tag_fg_bg = cpair(colors.gray, colors.white)
|
local tag_fg_bg = gry_wht
|
||||||
local ind_fg_bg = cpair(colors.lightGray, colors.white)
|
local ind_fg_bg = style.lg_white
|
||||||
local ind_off = colors.lightGray
|
local ind_off = colors.lightGray
|
||||||
|
|
||||||
if i <= facility.num_units then
|
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 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_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_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)
|
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
|
-- save the automatic process control configuration without starting
|
||||||
local function _save_cfg()
|
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}
|
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)}
|
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}
|
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 cpair = core.cpair
|
||||||
local border = core.border
|
local border = core.border
|
||||||
|
|
||||||
|
local text_fg_bg = style.text_colors
|
||||||
|
local lu_col = style.lu_colors
|
||||||
|
|
||||||
-- create new reactor view
|
-- create new reactor view
|
||||||
---@param root graphics_element parent
|
---@param root graphics_element parent
|
||||||
---@param x integer top left x
|
---@param x integer top left x
|
||||||
@ -22,9 +25,6 @@ local border = core.border
|
|||||||
local function new_view(root, x, y, ps)
|
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 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 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 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}
|
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,6 +15,9 @@ local VerticalBar = require("graphics.elements.indicators.vbar")
|
|||||||
local cpair = core.cpair
|
local cpair = core.cpair
|
||||||
local border = core.border
|
local border = core.border
|
||||||
|
|
||||||
|
local text_fg_bg = style.text_colors
|
||||||
|
local lu_col = style.lu_colors
|
||||||
|
|
||||||
-- new turbine view
|
-- new turbine view
|
||||||
---@param root graphics_element parent
|
---@param root graphics_element parent
|
||||||
---@param x integer top left x
|
---@param x integer top left x
|
||||||
@ -23,9 +26,6 @@ local border = core.border
|
|||||||
local function new_view(root, x, y, ps)
|
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 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 status = StateIndicator{parent=turbine,x=7,y=1,states=style.turbine.states,value=1,min_width=12}
|
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}
|
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}
|
||||||
local flow_rate = DataIndicator{parent=turbine,x=5,y=4,lu_colors=lu_col,label="",unit="mB/t",format="%10.0f",value=0,commas=true,width=16,fg_bg=text_fg_bg}
|
local flow_rate = DataIndicator{parent=turbine,x=5,y=4,lu_colors=lu_col,label="",unit="mB/t",format="%10.0f",value=0,commas=true,width=16,fg_bg=text_fg_bg}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
-- Reactor Unit SCADA Coordinator GUI
|
-- Reactor Unit SCADA Coordinator GUI
|
||||||
--
|
--
|
||||||
|
|
||||||
|
local types = require("scada-common.types")
|
||||||
|
|
||||||
local iocontrol = require("coordinator.iocontrol")
|
local iocontrol = require("coordinator.iocontrol")
|
||||||
|
|
||||||
local style = require("coordinator.ui.style")
|
local style = require("coordinator.ui.style")
|
||||||
@ -34,6 +36,9 @@ local border = core.border
|
|||||||
local bw_fg_bg = style.bw_fg_bg
|
local bw_fg_bg = style.bw_fg_bg
|
||||||
local lu_cpair = style.lu_colors
|
local lu_cpair = style.lu_colors
|
||||||
local hzd_fg_bg = style.hzd_fg_bg
|
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_grn = style.ind_grn
|
||||||
local ind_yel = style.ind_yel
|
local ind_yel = style.ind_yel
|
||||||
@ -93,7 +98,7 @@ local function init(parent, id)
|
|||||||
waste.register(u_ps, "waste_fill", waste.update)
|
waste.register(u_ps, "waste_fill", waste.update)
|
||||||
|
|
||||||
ccool.register(u_ps, "ccool_type", function (type)
|
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))
|
ccool.recolor(cpair(colors.lightBlue, colors.gray))
|
||||||
else
|
else
|
||||||
ccool.recolor(cpair(colors.blue, colors.gray))
|
ccool.recolor(cpair(colors.blue, colors.gray))
|
||||||
@ -101,7 +106,7 @@ local function init(parent, id)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
hcool.register(u_ps, "hcool_type", function (type)
|
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))
|
hcool.recolor(cpair(colors.orange, colors.gray))
|
||||||
else
|
else
|
||||||
hcool.recolor(cpair(colors.white, colors.gray))
|
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 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_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_1.register(u_ps, "U_StatusLine1", stat_line_1.set_value)
|
||||||
stat_line_2.register(u_ps, "U_StatusLine2", stat_line_2.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 --
|
-- 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=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}
|
||||||
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}
|
|
||||||
TextBox{parent=burn_control,x=9,y=2,text="mB/t"}
|
TextBox{parent=burn_control,x=9,y=2,text="mB/t"}
|
||||||
|
|
||||||
local set_burn = function () unit.set_burn(burn_rate.get_value()) end
|
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()
|
auto_div.line_break()
|
||||||
|
|
||||||
local function set_group() unit.set_group(group.get_value() - 1) end
|
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()
|
auto_div.line_break()
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
|||||||
|
|
||||||
local sprintf = util.sprintf
|
local sprintf = util.sprintf
|
||||||
|
|
||||||
local cpair = core.cpair
|
|
||||||
local border = core.border
|
local border = core.border
|
||||||
local pipe = core.pipe
|
local pipe = core.pipe
|
||||||
|
|
||||||
@ -31,6 +30,7 @@ local wh_gray = style.wh_gray
|
|||||||
local bw_fg_bg = style.bw_fg_bg
|
local bw_fg_bg = style.bw_fg_bg
|
||||||
local text_c = style.text_colors
|
local text_c = style.text_colors
|
||||||
local lu_c = style.lu_colors
|
local lu_c = style.lu_colors
|
||||||
|
local lg_gray = style.lg_gray
|
||||||
|
|
||||||
local ind_grn = style.ind_grn
|
local ind_grn = style.ind_grn
|
||||||
local ind_wht = style.ind_wht
|
local ind_wht = style.ind_wht
|
||||||
@ -64,8 +64,6 @@ local function make(parent, x, y, wide, unit)
|
|||||||
-- bounding box div
|
-- bounding box div
|
||||||
local root = Div{parent=parent,x=x,y=y,width=_wide(136, 114),height=height}
|
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 --
|
-- COOLING LOOP --
|
||||||
------------------
|
------------------
|
||||||
|
@ -261,7 +261,7 @@ local function init(main)
|
|||||||
if tank_defs[i] > 0 then
|
if tank_defs[i] > 0 then
|
||||||
local vy = 3 + y_ofs(i)
|
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 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}
|
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}
|
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}
|
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}
|
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}
|
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}
|
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}
|
local sps_box = Rectangle{parent=sps,border=border(1,colors.gray,true),width=24,height=10}
|
||||||
|
@ -28,6 +28,8 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
|||||||
|
|
||||||
local cpair = core.cpair
|
local cpair = core.cpair
|
||||||
|
|
||||||
|
local led_grn = style.led_grn
|
||||||
|
|
||||||
-- create new front panel view
|
-- create new front panel view
|
||||||
---@param panel graphics_element main displaybox
|
---@param panel graphics_element main displaybox
|
||||||
---@param num_units integer number of units (number of unit monitors)
|
---@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 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 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)
|
status.update(true)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
|
|
||||||
heartbeat.register(ps, "heartbeat", heartbeat.update)
|
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}}
|
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)
|
network.update(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
@ -61,25 +63,25 @@ local function init(panel, num_units)
|
|||||||
modem.register(ps, "has_modem", modem.update)
|
modem.register(ps, "has_modem", modem.update)
|
||||||
network.register(ps, "link_state", network.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)
|
speaker.register(ps, "has_speaker", speaker.update)
|
||||||
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
local comp_id = util.sprintf("(%d)", os.getComputerID())
|
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 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)
|
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)
|
flow_monitor.register(ps, "flow_monitor", flow_monitor.update)
|
||||||
|
|
||||||
monitors.line_break()
|
monitors.line_break()
|
||||||
|
|
||||||
for i = 1, num_units do
|
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)
|
unit_monitor.register(ps, "unit_monitor_" .. i, unit_monitor.update)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -87,7 +89,7 @@ local function init(panel, num_units)
|
|||||||
-- about footer
|
-- 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 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}
|
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
|
-- API page
|
||||||
|
|
||||||
local api_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
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
|
local _ = Div{parent=api_list,height=1,hidden=true} -- padding
|
||||||
|
|
||||||
-- assemble page panes
|
-- 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 page_pane = MultiPane{parent=page_div,x=1,y=1,panes=panes}
|
||||||
|
|
||||||
local tabs = {
|
local tabs = {
|
||||||
{ name = "CRD", color = cpair(colors.black, colors.ivory) },
|
{ name = "CRD", color = style.fp_text },
|
||||||
{ name = "API", color = cpair(colors.black, colors.ivory) },
|
{ 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
|
-- link pocket API list management to PGI
|
||||||
pgi.link_elements(api_list, pkt_entry)
|
pgi.link_elements(api_list, pkt_entry)
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
-- Main SCADA Coordinator GUI
|
-- Main SCADA Coordinator GUI
|
||||||
--
|
--
|
||||||
|
|
||||||
local util = require("scada-common.util")
|
|
||||||
|
|
||||||
local iocontrol = require("coordinator.iocontrol")
|
local iocontrol = require("coordinator.iocontrol")
|
||||||
|
|
||||||
local style = require("coordinator.ui.style")
|
local style = require("coordinator.ui.style")
|
||||||
@ -20,8 +18,6 @@ local DataIndicator = require("graphics.elements.indicators.data")
|
|||||||
|
|
||||||
local TEXT_ALIGN = core.TEXT_ALIGN
|
local TEXT_ALIGN = core.TEXT_ALIGN
|
||||||
|
|
||||||
local cpair = core.cpair
|
|
||||||
|
|
||||||
-- create new main view
|
-- create new main view
|
||||||
---@param main graphics_element main displaybox
|
---@param main graphics_element main displaybox
|
||||||
local function init(main)
|
local function init(main)
|
||||||
@ -30,7 +26,7 @@ local function init(main)
|
|||||||
|
|
||||||
-- window header message
|
-- 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 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"
|
-- 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}
|
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)")
|
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
|
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.hzd_fg_bg = style.wh_gray
|
||||||
style.dis_colors = cpair(colors.white, colors.lightGray)
|
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_grn = cpair(colors.green, colors.gray)
|
||||||
style.ind_yel = cpair(colors.yellow, colors.gray)
|
style.ind_yel = cpair(colors.yellow, colors.gray)
|
||||||
style.ind_red = cpair(colors.red, colors.gray)
|
style.ind_red = cpair(colors.red, colors.gray)
|
||||||
style.ind_wht = style.wh_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 --
|
-- UI COMPONENTS --
|
||||||
|
|
||||||
style.reactor = {
|
style.reactor = {
|
||||||
|
@ -7,7 +7,7 @@ local flasher = require("graphics.flasher")
|
|||||||
|
|
||||||
local core = {}
|
local core = {}
|
||||||
|
|
||||||
core.version = "1.1.1"
|
core.version = "1.1.2"
|
||||||
|
|
||||||
core.flasher = flasher
|
core.flasher = flasher
|
||||||
core.events = events
|
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
|
---@param even? boolean whether to pad width extra to account for rectangular pixels, defaults to false
|
||||||
---@return graphics_border
|
---@return graphics_border
|
||||||
function core.border(width, color, even)
|
function core.border(width, color, even)
|
||||||
return {
|
return { width = width, color = color, even = even or false }
|
||||||
width = width,
|
|
||||||
color = color,
|
|
||||||
even = even or false -- convert nil to false
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class graphics_frame
|
---@class graphics_frame
|
||||||
@ -56,12 +52,7 @@ end
|
|||||||
---@param h integer
|
---@param h integer
|
||||||
---@return graphics_frame
|
---@return graphics_frame
|
||||||
function core.gframe(x, y, w, h)
|
function core.gframe(x, y, w, h)
|
||||||
return {
|
return { x = x, y = y, w = w, h = h }
|
||||||
x = x,
|
|
||||||
y = y,
|
|
||||||
w = w,
|
|
||||||
h = h
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class cpair
|
---@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.x2 = self.position.x + f.w - 1
|
||||||
self.bounds.y1 = self.position.y
|
self.bounds.y1 = self.position.y
|
||||||
self.bounds.y2 = self.position.y + f.h - 1
|
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
|
end
|
||||||
|
|
||||||
-- check if a coordinate relative to the parent is within the bounds of this element
|
-- 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
|
if state >= 0 and state < 7 then
|
||||||
-- top
|
-- 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
|
if state % 2 == 0 then
|
||||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||||
else
|
else
|
||||||
e.window.blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
e.w_blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- bottom
|
-- 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
|
if state % 2 == 0 then
|
||||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||||
else
|
else
|
||||||
e.window.blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
e.w_blit("\x8a\x85", blit_fg_2x, blit_bg_2x)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local st = state - 7
|
local st = state - 7
|
||||||
|
|
||||||
-- right
|
-- right
|
||||||
if st % 3 == 0 then
|
if st % 3 == 0 then
|
||||||
e.window.setCursorPos(4, 1 + math.floor(st / 3))
|
e.w_set_cur(4, 1 + math.floor(st / 3))
|
||||||
e.window.blit("\x83", blit_bg, blit_fg)
|
e.w_blit("\x83", blit_bg, blit_fg)
|
||||||
elseif st % 3 == 1 then
|
elseif st % 3 == 1 then
|
||||||
e.window.setCursorPos(4, 1 + math.floor(st / 3))
|
e.w_set_cur(4, 1 + math.floor(st / 3))
|
||||||
e.window.blit("\x8f", blit_bg, blit_fg)
|
e.w_blit("\x8f", blit_bg, blit_fg)
|
||||||
e.window.setCursorPos(4, 2 + math.floor(st / 3))
|
e.w_set_cur(4, 2 + math.floor(st / 3))
|
||||||
e.window.blit("\x83", blit_fg, blit_bg)
|
e.w_blit("\x83", blit_fg, blit_bg)
|
||||||
else
|
else
|
||||||
e.window.setCursorPos(4, 2 + math.floor(st / 3))
|
e.w_set_cur(4, 2 + math.floor(st / 3))
|
||||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- left
|
-- left
|
||||||
if st % 3 == 0 then
|
if st % 3 == 0 then
|
||||||
e.window.setCursorPos(1, 3 - math.floor(st / 3))
|
e.w_set_cur(1, 3 - math.floor(st / 3))
|
||||||
e.window.blit("\x83", blit_fg, blit_bg)
|
e.w_blit("\x83", blit_fg, blit_bg)
|
||||||
e.window.setCursorPos(1, 2 - math.floor(st / 3))
|
e.w_set_cur(1, 2 - math.floor(st / 3))
|
||||||
e.window.blit("\x8f", blit_bg, blit_fg)
|
e.w_blit("\x8f", blit_bg, blit_fg)
|
||||||
elseif st % 3 == 1 then
|
elseif st % 3 == 1 then
|
||||||
e.window.setCursorPos(1, 2 - math.floor(st / 3))
|
e.w_set_cur(1, 2 - math.floor(st / 3))
|
||||||
e.window.blit("\x83", blit_bg, blit_fg)
|
e.w_blit("\x83", blit_bg, blit_fg)
|
||||||
else
|
else
|
||||||
e.window.setCursorPos(1, 2 - math.floor(st / 3))
|
e.w_set_cur(1, 2 - math.floor(st / 3))
|
||||||
e.window.blit("\x8f", blit_fg, blit_bg)
|
e.w_blit("\x8f", blit_fg, blit_bg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ local function colormap(args)
|
|||||||
local e = element.new(args)
|
local e = element.new(args)
|
||||||
|
|
||||||
-- draw color map
|
-- draw color map
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.blit(spaces, bkg, bkg)
|
e.w_blit(spaces, bkg, bkg)
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
end
|
end
|
||||||
|
@ -36,9 +36,8 @@ local function app_button(args)
|
|||||||
local e = element.new(args)
|
local e = element.new(args)
|
||||||
|
|
||||||
-- write app title, centered
|
-- write app title, centered
|
||||||
e.window.setCursorPos(1, 4)
|
e.w_set_cur(math.floor((e.frame.w - string.len(args.title)) / 2) + 1, 4)
|
||||||
e.window.setCursorPos(math.floor((e.frame.w - string.len(args.title)) / 2) + 1, 4)
|
e.w_write(args.title)
|
||||||
e.window.write(args.title)
|
|
||||||
|
|
||||||
-- draw the app button
|
-- draw the app button
|
||||||
local function draw()
|
local function draw()
|
||||||
@ -51,36 +50,36 @@ local function app_button(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- draw icon
|
-- draw icon
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.setTextColor(fgd)
|
e.w_set_fgd(fgd)
|
||||||
e.window.setBackgroundColor(bkg)
|
e.w_set_bkg(bkg)
|
||||||
e.window.write("\x9f\x83\x83\x83")
|
e.w_write("\x9f\x83\x83\x83")
|
||||||
e.window.setTextColor(bkg)
|
e.w_set_fgd(bkg)
|
||||||
e.window.setBackgroundColor(fgd)
|
e.w_set_bkg(fgd)
|
||||||
e.window.write("\x90")
|
e.w_write("\x90")
|
||||||
e.window.setTextColor(fgd)
|
e.w_set_fgd(fgd)
|
||||||
e.window.setBackgroundColor(bkg)
|
e.w_set_bkg(bkg)
|
||||||
e.window.setCursorPos(1, 2)
|
e.w_set_cur(1, 2)
|
||||||
e.window.write("\x95 ")
|
e.w_write("\x95 ")
|
||||||
e.window.setTextColor(bkg)
|
e.w_set_fgd(bkg)
|
||||||
e.window.setBackgroundColor(fgd)
|
e.w_set_bkg(fgd)
|
||||||
e.window.write("\x95")
|
e.w_write("\x95")
|
||||||
e.window.setCursorPos(1, 3)
|
e.w_set_cur(1, 3)
|
||||||
e.window.write("\x82\x8f\x8f\x8f\x81")
|
e.w_write("\x82\x8f\x8f\x8f\x81")
|
||||||
|
|
||||||
-- write the icon text
|
-- write the icon text
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.setTextColor(fgd)
|
e.w_set_fgd(fgd)
|
||||||
e.window.setBackgroundColor(bkg)
|
e.w_set_bkg(bkg)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw the app button as pressed (if active_fg_bg set)
|
-- draw the app button as pressed (if active_fg_bg set)
|
||||||
local function show_pressed()
|
local function show_pressed()
|
||||||
if e.enabled and args.active_fg_bg ~= nil then
|
if e.enabled and args.active_fg_bg ~= nil then
|
||||||
e.value = true
|
e.value = true
|
||||||
e.window.setTextColor(args.active_fg_bg.fgd)
|
e.w_set_fgd(args.active_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(args.active_fg_bg.bkg)
|
e.w_set_bkg(args.active_fg_bg.bkg)
|
||||||
draw()
|
draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -89,8 +88,8 @@ local function app_button(args)
|
|||||||
local function show_unpressed()
|
local function show_unpressed()
|
||||||
if e.enabled and args.active_fg_bg ~= nil then
|
if e.enabled and args.active_fg_bg ~= nil then
|
||||||
e.value = false
|
e.value = false
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
draw()
|
draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -32,24 +32,24 @@ local function checkbox(args)
|
|||||||
|
|
||||||
-- show the button state
|
-- show the button state
|
||||||
local function draw()
|
local function draw()
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if e.value then
|
if e.value then
|
||||||
-- show as selected
|
-- show as selected
|
||||||
e.window.setTextColor(args.box_fg_bg.bkg)
|
e.w_set_fgd(args.box_fg_bg.bkg)
|
||||||
e.window.setBackgroundColor(args.box_fg_bg.fgd)
|
e.w_set_bkg(args.box_fg_bg.fgd)
|
||||||
e.window.write("\x88")
|
e.w_write("\x88")
|
||||||
e.window.setTextColor(args.box_fg_bg.fgd)
|
e.w_set_fgd(args.box_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
e.window.write("\x95")
|
e.w_write("\x95")
|
||||||
else
|
else
|
||||||
-- show as unselected
|
-- show as unselected
|
||||||
e.window.setTextColor(e.fg_bg.bkg)
|
e.w_set_fgd(e.fg_bg.bkg)
|
||||||
e.window.setBackgroundColor(args.box_fg_bg.bkg)
|
e.w_set_bkg(args.box_fg_bg.bkg)
|
||||||
e.window.write("\x88")
|
e.w_write("\x88")
|
||||||
e.window.setTextColor(args.box_fg_bg.bkg)
|
e.w_set_fgd(args.box_fg_bg.bkg)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
e.window.write("\x95")
|
e.w_write("\x95")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -71,10 +71,10 @@ local function checkbox(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- write label text
|
-- write label text
|
||||||
e.window.setCursorPos(3, 1)
|
e.w_set_cur(3, 1)
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
-- initial draw
|
-- initial draw
|
||||||
draw()
|
draw()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
-- Hazard-bordered Button Graphics Element
|
-- Hazard-bordered Button Graphics Element
|
||||||
|
|
||||||
local tcd = require("scada-common.tcd")
|
local tcd = require("scada-common.tcd")
|
||||||
local util = require("scada-common.util")
|
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
local element = require("graphics.element")
|
local element = require("graphics.element")
|
||||||
@ -34,35 +33,35 @@ local function hazard_button(args)
|
|||||||
local e = element.new(args)
|
local e = element.new(args)
|
||||||
|
|
||||||
-- write the button text
|
-- write the button text
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
|
|
||||||
-- draw border
|
-- draw border
|
||||||
---@param accent color accent color
|
---@param accent color accent color
|
||||||
local function draw_border(accent)
|
local function draw_border(accent)
|
||||||
-- top
|
-- top
|
||||||
e.window.setTextColor(accent)
|
e.w_set_fgd(accent)
|
||||||
e.window.setBackgroundColor(args.fg_bg.bkg)
|
e.w_set_bkg(args.fg_bg.bkg)
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.write("\x99" .. util.strrep("\x89", args.width - 2) .. "\x99")
|
e.w_write("\x99" .. string.rep("\x89", args.width - 2) .. "\x99")
|
||||||
|
|
||||||
-- center left
|
-- center left
|
||||||
e.window.setCursorPos(1, 2)
|
e.w_set_cur(1, 2)
|
||||||
e.window.setTextColor(args.fg_bg.bkg)
|
e.w_set_fgd(args.fg_bg.bkg)
|
||||||
e.window.setBackgroundColor(accent)
|
e.w_set_bkg(accent)
|
||||||
e.window.write("\x99")
|
e.w_write("\x99")
|
||||||
|
|
||||||
-- center right
|
-- center right
|
||||||
e.window.setTextColor(args.fg_bg.bkg)
|
e.w_set_fgd(args.fg_bg.bkg)
|
||||||
e.window.setBackgroundColor(accent)
|
e.w_set_bkg(accent)
|
||||||
e.window.setCursorPos(args.width, 2)
|
e.w_set_cur(args.width, 2)
|
||||||
e.window.write("\x99")
|
e.w_write("\x99")
|
||||||
|
|
||||||
-- bottom
|
-- bottom
|
||||||
e.window.setTextColor(accent)
|
e.w_set_fgd(accent)
|
||||||
e.window.setBackgroundColor(args.fg_bg.bkg)
|
e.w_set_bkg(args.fg_bg.bkg)
|
||||||
e.window.setCursorPos(1, 3)
|
e.w_set_cur(1, 3)
|
||||||
e.window.write("\x99" .. util.strrep("\x98", args.width - 2) .. "\x99")
|
e.w_write("\x99" .. string.rep("\x98", args.width - 2) .. "\x99")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- on request timeout: recursively calls itself to double flash button text
|
-- on request timeout: recursively calls itself to double flash button text
|
||||||
@ -73,9 +72,9 @@ local function hazard_button(args)
|
|||||||
|
|
||||||
if n == 0 then
|
if n == 0 then
|
||||||
-- go back off
|
-- go back off
|
||||||
e.window.setTextColor(args.fg_bg.fgd)
|
e.w_set_fgd(args.fg_bg.fgd)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
if n >= 4 then
|
if n >= 4 then
|
||||||
@ -83,18 +82,18 @@ local function hazard_button(args)
|
|||||||
elseif n % 2 == 0 then
|
elseif n % 2 == 0 then
|
||||||
-- toggle text color on after 0.25 seconds
|
-- toggle text color on after 0.25 seconds
|
||||||
tcd.dispatch(0.25, function ()
|
tcd.dispatch(0.25, function ()
|
||||||
e.window.setTextColor(args.accent)
|
e.w_set_fgd(args.accent)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
on_timeout(n + 1)
|
on_timeout(n + 1)
|
||||||
on_timeout(n + 1)
|
on_timeout(n + 1)
|
||||||
end)
|
end)
|
||||||
elseif n % 1 then
|
elseif n % 1 then
|
||||||
-- toggle text color off after 0.25 seconds
|
-- toggle text color off after 0.25 seconds
|
||||||
tcd.dispatch(0.25, function ()
|
tcd.dispatch(0.25, function ()
|
||||||
e.window.setTextColor(args.fg_bg.fgd)
|
e.w_set_fgd(args.fg_bg.fgd)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
on_timeout(n + 1)
|
on_timeout(n + 1)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -102,9 +101,9 @@ local function hazard_button(args)
|
|||||||
|
|
||||||
-- blink routine for success indication
|
-- blink routine for success indication
|
||||||
local function on_success()
|
local function on_success()
|
||||||
e.window.setTextColor(args.fg_bg.fgd)
|
e.w_set_fgd(args.fg_bg.fgd)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- blink routine for failure indication
|
-- blink routine for failure indication
|
||||||
@ -115,9 +114,9 @@ local function hazard_button(args)
|
|||||||
|
|
||||||
if n == 0 then
|
if n == 0 then
|
||||||
-- go back off
|
-- go back off
|
||||||
e.window.setTextColor(args.fg_bg.fgd)
|
e.w_set_fgd(args.fg_bg.fgd)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
if n >= 2 then
|
if n >= 2 then
|
||||||
@ -125,17 +124,17 @@ local function hazard_button(args)
|
|||||||
elseif n % 2 == 0 then
|
elseif n % 2 == 0 then
|
||||||
-- toggle text color on after 0.5 seconds
|
-- toggle text color on after 0.5 seconds
|
||||||
tcd.dispatch(0.5, function ()
|
tcd.dispatch(0.5, function ()
|
||||||
e.window.setTextColor(args.accent)
|
e.w_set_fgd(args.accent)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
on_failure(n + 1)
|
on_failure(n + 1)
|
||||||
end)
|
end)
|
||||||
elseif n % 1 then
|
elseif n % 1 then
|
||||||
-- toggle text color off after 0.25 seconds
|
-- toggle text color off after 0.25 seconds
|
||||||
tcd.dispatch(0.25, function ()
|
tcd.dispatch(0.25, function ()
|
||||||
e.window.setTextColor(args.fg_bg.fgd)
|
e.w_set_fgd(args.fg_bg.fgd)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
on_failure(n + 1)
|
on_failure(n + 1)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -147,9 +146,9 @@ local function hazard_button(args)
|
|||||||
if e.enabled then
|
if e.enabled then
|
||||||
if core.events.was_clicked(event.type) then
|
if core.events.was_clicked(event.type) then
|
||||||
-- change text color to indicate clicked
|
-- change text color to indicate clicked
|
||||||
e.window.setTextColor(args.accent)
|
e.w_set_fgd(args.accent)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
|
|
||||||
-- abort any other callbacks
|
-- abort any other callbacks
|
||||||
tcd.abort(on_timeout)
|
tcd.abort(on_timeout)
|
||||||
@ -182,18 +181,18 @@ local function hazard_button(args)
|
|||||||
function e.disable()
|
function e.disable()
|
||||||
if args.dis_colors then
|
if args.dis_colors then
|
||||||
draw_border(args.dis_colors.color_a)
|
draw_border(args.dis_colors.color_a)
|
||||||
e.window.setTextColor(args.dis_colors.color_b)
|
e.w_set_fgd(args.dis_colors.color_b)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- show the button as enabled
|
-- show the button as enabled
|
||||||
function e.enable()
|
function e.enable()
|
||||||
draw_border(args.accent)
|
draw_border(args.accent)
|
||||||
e.window.setTextColor(args.fg_bg.fgd)
|
e.w_set_fgd(args.fg_bg.fgd)
|
||||||
e.window.setCursorPos(3, 2)
|
e.w_set_cur(3, 2)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- initial draw of border
|
-- initial draw of border
|
||||||
|
@ -75,19 +75,19 @@ local function multi_button(args)
|
|||||||
for i = 1, #args.options do
|
for i = 1, #args.options do
|
||||||
local opt = args.options[i] ---@type button_option
|
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
|
if e.value == i then
|
||||||
-- show as pressed
|
-- show as pressed
|
||||||
e.window.setTextColor(opt.active_fg_bg.fgd)
|
e.w_set_fgd(opt.active_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(opt.active_fg_bg.bkg)
|
e.w_set_bkg(opt.active_fg_bg.bkg)
|
||||||
else
|
else
|
||||||
-- show as unpressed
|
-- show as unpressed
|
||||||
e.window.setTextColor(opt.fg_bg.fgd)
|
e.w_set_fgd(opt.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(opt.fg_bg.bkg)
|
e.w_set_bkg(opt.fg_bg.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.write(util.pad(opt.text, button_width))
|
e.w_write(util.pad(opt.text, button_width))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,16 +48,16 @@ local function push_button(args)
|
|||||||
e.window.clear()
|
e.window.clear()
|
||||||
|
|
||||||
-- write the button text
|
-- write the button text
|
||||||
e.window.setCursorPos(h_pad, v_pad)
|
e.w_set_cur(h_pad, v_pad)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw the button as pressed (if active_fg_bg set)
|
-- draw the button as pressed (if active_fg_bg set)
|
||||||
local function show_pressed()
|
local function show_pressed()
|
||||||
if e.enabled and args.active_fg_bg ~= nil then
|
if e.enabled and args.active_fg_bg ~= nil then
|
||||||
e.value = true
|
e.value = true
|
||||||
e.window.setTextColor(args.active_fg_bg.fgd)
|
e.w_set_fgd(args.active_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(args.active_fg_bg.bkg)
|
e.w_set_bkg(args.active_fg_bg.bkg)
|
||||||
draw()
|
draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -66,8 +66,8 @@ local function push_button(args)
|
|||||||
local function show_unpressed()
|
local function show_unpressed()
|
||||||
if e.enabled and args.active_fg_bg ~= nil then
|
if e.enabled and args.active_fg_bg ~= nil then
|
||||||
e.value = false
|
e.value = false
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
draw()
|
draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -102,8 +102,8 @@ local function push_button(args)
|
|||||||
function e.enable()
|
function e.enable()
|
||||||
if args.dis_fg_bg ~= nil then
|
if args.dis_fg_bg ~= nil then
|
||||||
e.value = false
|
e.value = false
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
draw()
|
draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -112,8 +112,8 @@ local function push_button(args)
|
|||||||
function e.disable()
|
function e.disable()
|
||||||
if args.dis_fg_bg ~= nil then
|
if args.dis_fg_bg ~= nil then
|
||||||
e.value = false
|
e.value = false
|
||||||
e.window.setTextColor(args.dis_fg_bg.fgd)
|
e.w_set_fgd(args.dis_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(args.dis_fg_bg.bkg)
|
e.w_set_bkg(args.dis_fg_bg.bkg)
|
||||||
draw()
|
draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -56,28 +56,28 @@ local function radio_button(args)
|
|||||||
for i = 1, #args.options do
|
for i = 1, #args.options do
|
||||||
local opt = args.options[i] ---@type string
|
local opt = args.options[i] ---@type string
|
||||||
|
|
||||||
e.window.setCursorPos(1, i)
|
e.w_set_cur(1, i)
|
||||||
|
|
||||||
if e.value == i then
|
if e.value == i then
|
||||||
-- show as selected
|
-- show as selected
|
||||||
e.window.setTextColor(args.radio_colors.color_a)
|
e.w_set_fgd(args.radio_colors.color_a)
|
||||||
e.window.setBackgroundColor(args.radio_bg)
|
e.w_set_bkg(args.radio_bg)
|
||||||
else
|
else
|
||||||
-- show as unselected
|
-- show as unselected
|
||||||
e.window.setTextColor(args.radio_colors.color_b)
|
e.w_set_fgd(args.radio_colors.color_b)
|
||||||
e.window.setBackgroundColor(args.radio_bg)
|
e.w_set_bkg(args.radio_bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.write("\x88")
|
e.w_write("\x88")
|
||||||
|
|
||||||
e.window.setTextColor(args.radio_bg)
|
e.w_set_fgd(args.radio_bg)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
e.window.write("\x95")
|
e.w_write("\x95")
|
||||||
|
|
||||||
-- write button text
|
-- write button text
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
e.window.write(opt)
|
e.w_write(opt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,27 +52,27 @@ local function sidebar(args)
|
|||||||
|
|
||||||
local y = ((i - 1) * 3) + 1
|
local y = ((i - 1) * 3) + 1
|
||||||
|
|
||||||
e.window.setCursorPos(1, y)
|
e.w_set_cur(1, y)
|
||||||
|
|
||||||
if pressed and i == pressed_idx then
|
if pressed and i == pressed_idx then
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
else
|
else
|
||||||
e.window.setTextColor(tab.color.fgd)
|
e.w_set_fgd(tab.color.fgd)
|
||||||
e.window.setBackgroundColor(tab.color.bkg)
|
e.w_set_bkg(tab.color.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.write(" ")
|
e.w_write(" ")
|
||||||
e.window.setCursorPos(1, y + 1)
|
e.w_set_cur(1, y + 1)
|
||||||
if e.value == i then
|
if e.value == i then
|
||||||
-- show as selected
|
-- show as selected
|
||||||
e.window.write(" " .. tab.char .. "\x10")
|
e.w_write(" " .. tab.char .. "\x10")
|
||||||
else
|
else
|
||||||
-- show as unselected
|
-- show as unselected
|
||||||
e.window.write(" " .. tab.char .. " ")
|
e.w_write(" " .. tab.char .. " ")
|
||||||
end
|
end
|
||||||
e.window.setCursorPos(1, y + 2)
|
e.w_set_cur(1, y + 2)
|
||||||
e.window.write(" ")
|
e.w_write(" ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -58,17 +58,17 @@ local function spinbox(args)
|
|||||||
|
|
||||||
-- draw the arrows
|
-- draw the arrows
|
||||||
local function draw_arrows(color)
|
local function draw_arrows(color)
|
||||||
e.window.setBackgroundColor(args.arrow_fg_bg.bkg)
|
e.w_set_bkg(args.arrow_fg_bg.bkg)
|
||||||
e.window.setTextColor(color)
|
e.w_set_fgd(color)
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.write(util.strrep("\x1e", wn_prec))
|
e.w_write(string.rep("\x1e", wn_prec))
|
||||||
e.window.setCursorPos(1, 3)
|
e.w_set_cur(1, 3)
|
||||||
e.window.write(util.strrep("\x1f", wn_prec))
|
e.w_write(string.rep("\x1f", wn_prec))
|
||||||
if fr_prec > 0 then
|
if fr_prec > 0 then
|
||||||
e.window.setCursorPos(1 + wn_prec, 1)
|
e.w_set_cur(1 + wn_prec, 1)
|
||||||
e.window.write(" " .. util.strrep("\x1e", fr_prec))
|
e.w_write(" " .. string.rep("\x1e", fr_prec))
|
||||||
e.window.setCursorPos(1 + wn_prec, 3)
|
e.w_set_cur(1 + wn_prec, 3)
|
||||||
e.window.write(" " .. util.strrep("\x1f", fr_prec))
|
e.w_write(" " .. string.rep("\x1f", fr_prec))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -119,10 +119,10 @@ local function spinbox(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- draw
|
-- draw
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setCursorPos(1, 2)
|
e.w_set_cur(1, 2)
|
||||||
e.window.write(util.sprintf(fmt, e.value))
|
e.w_write(util.sprintf(fmt, e.value))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- init with the default value
|
-- init with the default value
|
||||||
|
@ -47,20 +47,20 @@ local function switch_button(args)
|
|||||||
local function draw_state()
|
local function draw_state()
|
||||||
if e.value then
|
if e.value then
|
||||||
-- show as pressed
|
-- show as pressed
|
||||||
e.window.setTextColor(args.active_fg_bg.fgd)
|
e.w_set_fgd(args.active_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(args.active_fg_bg.bkg)
|
e.w_set_bkg(args.active_fg_bg.bkg)
|
||||||
else
|
else
|
||||||
-- show as unpressed
|
-- show as unpressed
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- clear to redraw background
|
-- clear to redraw background
|
||||||
e.window.clear()
|
e.window.clear()
|
||||||
|
|
||||||
-- write the button text
|
-- write the button text
|
||||||
e.window.setCursorPos(h_pad, v_pad)
|
e.w_set_cur(h_pad, v_pad)
|
||||||
e.window.write(args.text)
|
e.w_write(args.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- initial draw
|
-- initial draw
|
||||||
|
@ -71,17 +71,17 @@ local function tabbar(args)
|
|||||||
for i = 1, #args.tabs do
|
for i = 1, #args.tabs do
|
||||||
local tab = args.tabs[i] ---@type tabbar_tab
|
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
|
if e.value == i then
|
||||||
e.window.setTextColor(tab.color.fgd)
|
e.w_set_fgd(tab.color.fgd)
|
||||||
e.window.setBackgroundColor(tab.color.bkg)
|
e.w_set_bkg(tab.color.bkg)
|
||||||
else
|
else
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.write(util.pad(tab.name, button_width))
|
e.w_write(util.pad(tab.name, button_width))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -53,17 +53,17 @@ local function alarm_indicator_light(args)
|
|||||||
|
|
||||||
-- called by flasher when enabled
|
-- called by flasher when enabled
|
||||||
local function flash_callback()
|
local function flash_callback()
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if flash_on then
|
if flash_on then
|
||||||
if e.value == 2 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
|
end
|
||||||
else
|
else
|
||||||
if e.value == 3 then
|
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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ local function alarm_indicator_light(args)
|
|||||||
local was_off = e.value ~= 2
|
local was_off = e.value ~= 2
|
||||||
|
|
||||||
e.value = new_state
|
e.value = new_state
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if args.flash then
|
if args.flash then
|
||||||
if was_off and (new_state == 2) then
|
if was_off and (new_state == 2) then
|
||||||
@ -87,17 +87,17 @@ local function alarm_indicator_light(args)
|
|||||||
flasher.stop(flash_callback)
|
flasher.stop(flash_callback)
|
||||||
|
|
||||||
if new_state == 3 then
|
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
|
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
|
||||||
end
|
end
|
||||||
elseif new_state == 2 then
|
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
|
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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ local function alarm_indicator_light(args)
|
|||||||
|
|
||||||
-- write label and initial indicator light
|
-- write label and initial indicator light
|
||||||
e.on_update(1)
|
e.on_update(1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
end
|
end
|
||||||
|
@ -47,25 +47,25 @@ local function core_map(args)
|
|||||||
|
|
||||||
-- create coordinate grid and frame
|
-- create coordinate grid and frame
|
||||||
local function draw_frame()
|
local function draw_frame()
|
||||||
e.window.setTextColor(colors.white)
|
e.w_set_fgd(colors.white)
|
||||||
|
|
||||||
for x = 0, (inner_width - 1) do
|
for x = 0, (inner_width - 1) do
|
||||||
e.window.setCursorPos(x + start_x, 1)
|
e.w_set_cur(x + start_x, 1)
|
||||||
e.window.write(util.sprintf("%X", x))
|
e.w_write(util.sprintf("%X", x))
|
||||||
end
|
end
|
||||||
|
|
||||||
for y = 0, (inner_height - 1) do
|
for y = 0, (inner_height - 1) do
|
||||||
e.window.setCursorPos(1, y + start_y)
|
e.w_set_cur(1, y + start_y)
|
||||||
e.window.write(util.sprintf("%X", y))
|
e.w_write(util.sprintf("%X", y))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- even out bottom edge
|
-- even out bottom edge
|
||||||
e.window.setTextColor(e.fg_bg.bkg)
|
e.w_set_fgd(e.fg_bg.bkg)
|
||||||
e.window.setBackgroundColor(args.parent.get_fg_bg().bkg)
|
e.w_set_bkg(args.parent.get_fg_bg().bkg)
|
||||||
e.window.setCursorPos(1, e.frame.h)
|
e.w_set_cur(1, e.frame.h)
|
||||||
e.window.write(util.strrep("\x8f", e.frame.w))
|
e.w_write(string.rep("\x8f", e.frame.w))
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw the core
|
-- draw the core
|
||||||
@ -102,13 +102,13 @@ local function core_map(args)
|
|||||||
|
|
||||||
-- draw pattern
|
-- draw pattern
|
||||||
for y = start_y, inner_height + (start_y - 1) do
|
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
|
for _ = 1, inner_width do
|
||||||
if alternator then
|
if alternator then
|
||||||
i = i + 1
|
i = i + 1
|
||||||
e.window.blit("\x07", text_c, back_c)
|
e.w_blit("\x07", text_c, back_c)
|
||||||
else
|
else
|
||||||
e.window.blit("\x07", "7", "8")
|
e.w_blit("\x07", "7", "8")
|
||||||
end
|
end
|
||||||
|
|
||||||
alternator = not alternator
|
alternator = not alternator
|
||||||
|
@ -37,12 +37,12 @@ local function data(args)
|
|||||||
|
|
||||||
-- label color
|
-- label color
|
||||||
if args.lu_colors ~= nil then
|
if args.lu_colors ~= nil then
|
||||||
e.window.setTextColor(args.lu_colors.color_a)
|
e.w_set_fgd(args.lu_colors.color_a)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write label
|
-- write label
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
local value_color = e.fg_bg.fgd
|
local value_color = e.fg_bg.fgd
|
||||||
local label_len = string.len(args.label)
|
local label_len = string.len(args.label)
|
||||||
@ -60,25 +60,25 @@ local function data(args)
|
|||||||
e.value = value
|
e.value = value
|
||||||
|
|
||||||
-- clear old data and label
|
-- clear old data and label
|
||||||
e.window.setCursorPos(data_start, 1)
|
e.w_set_cur(data_start, 1)
|
||||||
e.window.write(util.spaces(clear_width))
|
e.w_write(util.spaces(clear_width))
|
||||||
|
|
||||||
-- write data
|
-- write data
|
||||||
local data_str = util.sprintf(args.format, value)
|
local data_str = util.sprintf(args.format, value)
|
||||||
e.window.setCursorPos(data_start, 1)
|
e.w_set_cur(data_start, 1)
|
||||||
e.window.setTextColor(value_color)
|
e.w_set_fgd(value_color)
|
||||||
if args.commas then
|
if args.commas then
|
||||||
e.window.write(util.comma_format(data_str))
|
e.w_write(util.comma_format(data_str))
|
||||||
else
|
else
|
||||||
e.window.write(data_str)
|
e.w_write(data_str)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write label
|
-- write label
|
||||||
if args.unit ~= nil then
|
if args.unit ~= nil then
|
||||||
if args.lu_colors ~= 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
|
end
|
||||||
e.window.write(" " .. args.unit)
|
e.w_write(" " .. args.unit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -87,16 +87,16 @@ local function hbar(args)
|
|||||||
|
|
||||||
-- draw bar
|
-- draw bar
|
||||||
for y = 1, e.frame.h do
|
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
|
-- 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
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update percentage
|
-- update percentage
|
||||||
if args.show_percent then
|
if args.show_percent then
|
||||||
e.window.setCursorPos(bar_width + 2, math.max(1, math.ceil(e.frame.h / 2)))
|
e.w_set_cur(bar_width + 2, math.max(1, math.ceil(e.frame.h / 2)))
|
||||||
e.window.write(util.sprintf("%3.0f%%", fraction * 100))
|
e.w_write(util.sprintf("%3.0f%%", fraction * 100))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
-- Icon Indicator Graphics Element
|
-- Icon Indicator Graphics Element
|
||||||
|
|
||||||
local util = require("scada-common.util")
|
|
||||||
|
|
||||||
local element = require("graphics.element")
|
local element = require("graphics.element")
|
||||||
|
|
||||||
---@class icon_sym_color
|
---@class icon_sym_color
|
||||||
@ -44,22 +42,22 @@ local function icon(args)
|
|||||||
|
|
||||||
table.insert(state_blit_cmds, {
|
table.insert(state_blit_cmds, {
|
||||||
text = " " .. sym_color.symbol .. " ",
|
text = " " .. sym_color.symbol .. " ",
|
||||||
fgd = util.strrep(sym_color.color.blit_fgd, 3),
|
fgd = string.rep(sym_color.color.blit_fgd, 3),
|
||||||
bkg = util.strrep(sym_color.color.blit_bkg, 3)
|
bkg = string.rep(sym_color.color.blit_bkg, 3)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write label and initial indicator light
|
-- write label and initial indicator light
|
||||||
e.window.setCursorPos(5, 1)
|
e.w_set_cur(5, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
-- on state change
|
-- on state change
|
||||||
---@param new_state integer indicator state
|
---@param new_state integer indicator state
|
||||||
function e.on_update(new_state)
|
function e.on_update(new_state)
|
||||||
local blit_cmd = state_blit_cmds[new_state]
|
local blit_cmd = state_blit_cmds[new_state]
|
||||||
e.value = new_state
|
e.value = new_state
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
e.w_blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set indicator state
|
-- set indicator state
|
||||||
|
@ -44,12 +44,12 @@ local function indicator_led(args)
|
|||||||
|
|
||||||
-- called by flasher when enabled
|
-- called by flasher when enabled
|
||||||
local function flash_callback()
|
local function flash_callback()
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if flash_on then
|
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
|
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
|
end
|
||||||
|
|
||||||
flash_on = not flash_on
|
flash_on = not flash_on
|
||||||
@ -61,8 +61,8 @@ local function indicator_led(args)
|
|||||||
flash_on = true
|
flash_on = true
|
||||||
flasher.start(flash_callback, args.period)
|
flasher.start(flash_callback, args.period)
|
||||||
else
|
else
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
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)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -73,8 +73,8 @@ local function indicator_led(args)
|
|||||||
flasher.stop(flash_callback)
|
flasher.stop(flash_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
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
|
end
|
||||||
|
|
||||||
-- on state change
|
-- on state change
|
||||||
@ -91,8 +91,8 @@ local function indicator_led(args)
|
|||||||
-- write label and initial indicator light
|
-- write label and initial indicator light
|
||||||
e.on_update(false)
|
e.on_update(false)
|
||||||
if string.len(args.label) > 0 then
|
if string.len(args.label) > 0 then
|
||||||
e.window.setCursorPos(3, 1)
|
e.w_set_cur(3, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
end
|
end
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
|
@ -56,16 +56,16 @@ local function indicator_led_pair(args)
|
|||||||
|
|
||||||
-- called by flasher when enabled
|
-- called by flasher when enabled
|
||||||
local function flash_callback()
|
local function flash_callback()
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if flash_on then
|
if flash_on then
|
||||||
if e.value == 2 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
|
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
|
end
|
||||||
else
|
else
|
||||||
e.window.blit("\x8c", co, e.fg_bg.blit_bkg)
|
e.w_blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
flash_on = not flash_on
|
flash_on = not flash_on
|
||||||
@ -77,7 +77,7 @@ local function indicator_led_pair(args)
|
|||||||
local was_off = e.value <= 1
|
local was_off = e.value <= 1
|
||||||
|
|
||||||
e.value = new_state
|
e.value = new_state
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if args.flash then
|
if args.flash then
|
||||||
if was_off and (new_state > 1) then
|
if was_off and (new_state > 1) then
|
||||||
@ -87,14 +87,14 @@ local function indicator_led_pair(args)
|
|||||||
flash_on = false
|
flash_on = false
|
||||||
flasher.stop(flash_callback)
|
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
|
end
|
||||||
elseif new_state == 2 then
|
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
|
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
|
else
|
||||||
e.window.blit("\x8c", co, e.fg_bg.blit_bkg)
|
e.w_blit("\x8c", co, e.fg_bg.blit_bkg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -105,8 +105,8 @@ local function indicator_led_pair(args)
|
|||||||
-- write label and initial indicator light
|
-- write label and initial indicator light
|
||||||
e.on_update(1)
|
e.on_update(1)
|
||||||
if string.len(args.label) > 0 then
|
if string.len(args.label) > 0 then
|
||||||
e.window.setCursorPos(3, 1)
|
e.w_set_cur(3, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
end
|
end
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
|
@ -37,9 +37,9 @@ local function indicator_led_rgb(args)
|
|||||||
---@param new_state integer indicator state
|
---@param new_state integer indicator state
|
||||||
function e.on_update(new_state)
|
function e.on_update(new_state)
|
||||||
e.value = 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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -50,8 +50,8 @@ local function indicator_led_rgb(args)
|
|||||||
-- write label and initial indicator light
|
-- write label and initial indicator light
|
||||||
e.on_update(1)
|
e.on_update(1)
|
||||||
if string.len(args.label) > 0 then
|
if string.len(args.label) > 0 then
|
||||||
e.window.setCursorPos(3, 1)
|
e.w_set_cur(3, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
end
|
end
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
|
@ -44,12 +44,12 @@ local function indicator_light(args)
|
|||||||
|
|
||||||
-- called by flasher when enabled
|
-- called by flasher when enabled
|
||||||
local function flash_callback()
|
local function flash_callback()
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if flash_on then
|
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
|
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
|
end
|
||||||
|
|
||||||
flash_on = not flash_on
|
flash_on = not flash_on
|
||||||
@ -61,8 +61,8 @@ local function indicator_light(args)
|
|||||||
flash_on = true
|
flash_on = true
|
||||||
flasher.start(flash_callback, args.period)
|
flasher.start(flash_callback, args.period)
|
||||||
else
|
else
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
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)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -73,8 +73,8 @@ local function indicator_light(args)
|
|||||||
flasher.stop(flash_callback)
|
flasher.stop(flash_callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
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
|
end
|
||||||
|
|
||||||
-- on state change
|
-- on state change
|
||||||
@ -90,8 +90,8 @@ local function indicator_light(args)
|
|||||||
|
|
||||||
-- write label and initial indicator light
|
-- write label and initial indicator light
|
||||||
e.on_update(false)
|
e.on_update(false)
|
||||||
e.window.setCursorPos(3, 1)
|
e.w_set_cur(3, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
end
|
end
|
||||||
|
@ -34,12 +34,12 @@ local function power(args)
|
|||||||
|
|
||||||
-- label color
|
-- label color
|
||||||
if args.lu_colors ~= nil then
|
if args.lu_colors ~= nil then
|
||||||
e.window.setTextColor(args.lu_colors.color_a)
|
e.w_set_fgd(args.lu_colors.color_a)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write label
|
-- write label
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
local data_start = string.len(args.label) + 2
|
local data_start = string.len(args.label) + 2
|
||||||
if string.len(args.label) == 0 then data_start = 1 end
|
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)
|
local data_str, unit = util.power_format(value, false, args.format)
|
||||||
|
|
||||||
-- write data
|
-- write data
|
||||||
e.window.setCursorPos(data_start, 1)
|
e.w_set_cur(data_start, 1)
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.write(util.comma_format(data_str))
|
e.w_write(util.comma_format(data_str))
|
||||||
|
|
||||||
-- write unit
|
-- write unit
|
||||||
if args.lu_colors ~= 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
|
end
|
||||||
|
|
||||||
-- append per tick if rate is set
|
-- append per tick if rate is set
|
||||||
@ -70,7 +70,7 @@ local function power(args)
|
|||||||
if unit == "FE" then unit = "FE " end
|
if unit == "FE" then unit = "FE " end
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.write(" " .. unit)
|
e.w_write(" " .. unit)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set the value
|
-- set the value
|
||||||
|
@ -36,12 +36,12 @@ local function rad(args)
|
|||||||
|
|
||||||
-- label color
|
-- label color
|
||||||
if args.lu_colors ~= nil then
|
if args.lu_colors ~= nil then
|
||||||
e.window.setTextColor(args.lu_colors.color_a)
|
e.w_set_fgd(args.lu_colors.color_a)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write label
|
-- write label
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
local label_len = string.len(args.label)
|
local label_len = string.len(args.label)
|
||||||
local data_start = 1
|
local data_start = 1
|
||||||
@ -58,24 +58,24 @@ local function rad(args)
|
|||||||
e.value = value.radiation
|
e.value = value.radiation
|
||||||
|
|
||||||
-- clear old data and label
|
-- clear old data and label
|
||||||
e.window.setCursorPos(data_start, 1)
|
e.w_set_cur(data_start, 1)
|
||||||
e.window.write(util.spaces(clear_width))
|
e.w_write(util.spaces(clear_width))
|
||||||
|
|
||||||
-- write data
|
-- write data
|
||||||
local data_str = util.sprintf(args.format, e.value)
|
local data_str = util.sprintf(args.format, e.value)
|
||||||
e.window.setCursorPos(data_start, 1)
|
e.w_set_cur(data_start, 1)
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
if args.commas then
|
if args.commas then
|
||||||
e.window.write(util.comma_format(data_str))
|
e.w_write(util.comma_format(data_str))
|
||||||
else
|
else
|
||||||
e.window.write(data_str)
|
e.w_write(data_str)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- write unit
|
-- write unit
|
||||||
if args.lu_colors ~= 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
|
end
|
||||||
e.window.write(" " .. value.unit)
|
e.w_write(" " .. value.unit)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set the value
|
-- set the value
|
||||||
|
@ -51,8 +51,8 @@ local function state_indicator(args)
|
|||||||
|
|
||||||
table.insert(state_blit_cmds, {
|
table.insert(state_blit_cmds, {
|
||||||
text = text,
|
text = text,
|
||||||
fgd = util.strrep(state_def.color.blit_fgd, string.len(text)),
|
fgd = string.rep(state_def.color.blit_fgd, string.len(text)),
|
||||||
bkg = util.strrep(state_def.color.blit_bkg, string.len(text))
|
bkg = string.rep(state_def.color.blit_bkg, string.len(text))
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -64,8 +64,8 @@ local function state_indicator(args)
|
|||||||
function e.on_update(new_state)
|
function e.on_update(new_state)
|
||||||
local blit_cmd = state_blit_cmds[new_state]
|
local blit_cmd = state_blit_cmds[new_state]
|
||||||
e.value = new_state
|
e.value = new_state
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
e.window.blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
e.w_blit(blit_cmd.text, blit_cmd.fgd, blit_cmd.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set indicator state
|
-- set indicator state
|
||||||
|
@ -56,16 +56,16 @@ local function tristate_indicator_light(args)
|
|||||||
|
|
||||||
-- called by flasher when enabled
|
-- called by flasher when enabled
|
||||||
local function flash_callback()
|
local function flash_callback()
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if flash_on then
|
if flash_on then
|
||||||
if e.value == 2 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
|
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
|
end
|
||||||
else
|
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
|
||||||
|
|
||||||
flash_on = not flash_on
|
flash_on = not flash_on
|
||||||
@ -77,7 +77,7 @@ local function tristate_indicator_light(args)
|
|||||||
local was_off = e.value <= 1
|
local was_off = e.value <= 1
|
||||||
|
|
||||||
e.value = new_state
|
e.value = new_state
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
if args.flash then
|
if args.flash then
|
||||||
if was_off and (new_state > 1) then
|
if was_off and (new_state > 1) then
|
||||||
@ -87,14 +87,14 @@ local function tristate_indicator_light(args)
|
|||||||
flash_on = false
|
flash_on = false
|
||||||
flasher.stop(flash_callback)
|
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
|
end
|
||||||
elseif new_state == 2 then
|
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
|
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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ local function tristate_indicator_light(args)
|
|||||||
|
|
||||||
-- write label and initial indicator light
|
-- write label and initial indicator light
|
||||||
e.on_update(1)
|
e.on_update(1)
|
||||||
e.window.write(args.label)
|
e.w_write(args.label)
|
||||||
|
|
||||||
return e.complete()
|
return e.complete()
|
||||||
end
|
end
|
||||||
|
@ -27,11 +27,11 @@ local function vbar(args)
|
|||||||
local e = element.new(args)
|
local e = element.new(args)
|
||||||
|
|
||||||
-- blit strings
|
-- blit strings
|
||||||
local fgd = util.strrep(e.fg_bg.blit_fgd, e.frame.w)
|
local fgd = string.rep(e.fg_bg.blit_fgd, e.frame.w)
|
||||||
local bkg = util.strrep(e.fg_bg.blit_bkg, e.frame.w)
|
local bkg = string.rep(e.fg_bg.blit_bkg, e.frame.w)
|
||||||
local spaces = util.spaces(e.frame.w)
|
local spaces = util.spaces(e.frame.w)
|
||||||
local one_third = util.strrep("\x8f", e.frame.w)
|
local one_third = string.rep("\x8f", e.frame.w)
|
||||||
local two_thirds = util.strrep("\x83", e.frame.w)
|
local two_thirds = string.rep("\x83", e.frame.w)
|
||||||
|
|
||||||
-- handle data changes
|
-- handle data changes
|
||||||
---@param fraction number 0.0 to 1.0
|
---@param fraction number 0.0 to 1.0
|
||||||
@ -56,28 +56,28 @@ local function vbar(args)
|
|||||||
local y = e.frame.h
|
local y = e.frame.h
|
||||||
|
|
||||||
-- start at base of vertical bar
|
-- start at base of vertical bar
|
||||||
e.window.setCursorPos(1, y)
|
e.w_set_cur(1, y)
|
||||||
|
|
||||||
-- fill percentage
|
-- fill percentage
|
||||||
for _ = 1, num_bars / 3 do
|
for _ = 1, num_bars / 3 do
|
||||||
e.window.blit(spaces, bkg, fgd)
|
e.w_blit(spaces, bkg, fgd)
|
||||||
y = y - 1
|
y = y - 1
|
||||||
e.window.setCursorPos(1, y)
|
e.w_set_cur(1, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- add fractional bar if needed
|
-- add fractional bar if needed
|
||||||
if num_bars % 3 == 1 then
|
if num_bars % 3 == 1 then
|
||||||
e.window.blit(one_third, bkg, fgd)
|
e.w_blit(one_third, bkg, fgd)
|
||||||
y = y - 1
|
y = y - 1
|
||||||
elseif num_bars % 3 == 2 then
|
elseif num_bars % 3 == 2 then
|
||||||
e.window.blit(two_thirds, bkg, fgd)
|
e.w_blit(two_thirds, bkg, fgd)
|
||||||
y = y - 1
|
y = y - 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- fill the rest blank
|
-- fill the rest blank
|
||||||
while y > 0 do
|
while y > 0 do
|
||||||
e.window.setCursorPos(1, y)
|
e.w_set_cur(1, y)
|
||||||
e.window.blit(spaces, fgd, bkg)
|
e.w_blit(spaces, fgd, bkg)
|
||||||
y = y - 1
|
y = y - 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -86,8 +86,8 @@ local function vbar(args)
|
|||||||
-- change bar color
|
-- change bar color
|
||||||
---@param fg_bg cpair new bar colors
|
---@param fg_bg cpair new bar colors
|
||||||
function e.recolor(fg_bg)
|
function e.recolor(fg_bg)
|
||||||
fgd = util.strrep(fg_bg.blit_fgd, e.frame.w)
|
fgd = string.rep(fg_bg.blit_fgd, e.frame.w)
|
||||||
bkg = util.strrep(fg_bg.blit_bkg, e.frame.w)
|
bkg = string.rep(fg_bg.blit_bkg, e.frame.w)
|
||||||
|
|
||||||
-- re-draw
|
-- re-draw
|
||||||
last_num_bars = 0
|
last_num_bars = 0
|
||||||
|
@ -63,34 +63,34 @@ local function listbox(args)
|
|||||||
|
|
||||||
-- draw up/down arrows
|
-- draw up/down arrows
|
||||||
if pressed_arrow == 1 then
|
if pressed_arrow == 1 then
|
||||||
e.window.setTextColor(active_fg_bg.fgd)
|
e.w_set_fgd(active_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(active_fg_bg.bkg)
|
e.w_set_bkg(active_fg_bg.bkg)
|
||||||
e.window.setCursorPos(e.frame.w, 1)
|
e.w_set_cur(e.frame.w, 1)
|
||||||
e.window.write("\x1e")
|
e.w_write("\x1e")
|
||||||
e.window.setTextColor(nav_fg_bg.fgd)
|
e.w_set_fgd(nav_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(nav_fg_bg.bkg)
|
e.w_set_bkg(nav_fg_bg.bkg)
|
||||||
e.window.setCursorPos(e.frame.w, e.frame.h)
|
e.w_set_cur(e.frame.w, e.frame.h)
|
||||||
e.window.write("\x1f")
|
e.w_write("\x1f")
|
||||||
elseif pressed_arrow == -1 then
|
elseif pressed_arrow == -1 then
|
||||||
e.window.setTextColor(nav_fg_bg.fgd)
|
e.w_set_fgd(nav_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(nav_fg_bg.bkg)
|
e.w_set_bkg(nav_fg_bg.bkg)
|
||||||
e.window.setCursorPos(e.frame.w, 1)
|
e.w_set_cur(e.frame.w, 1)
|
||||||
e.window.write("\x1e")
|
e.w_write("\x1e")
|
||||||
e.window.setTextColor(active_fg_bg.fgd)
|
e.w_set_fgd(active_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(active_fg_bg.bkg)
|
e.w_set_bkg(active_fg_bg.bkg)
|
||||||
e.window.setCursorPos(e.frame.w, e.frame.h)
|
e.w_set_cur(e.frame.w, e.frame.h)
|
||||||
e.window.write("\x1f")
|
e.w_write("\x1f")
|
||||||
else
|
else
|
||||||
e.window.setTextColor(nav_fg_bg.fgd)
|
e.w_set_fgd(nav_fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(nav_fg_bg.bkg)
|
e.w_set_bkg(nav_fg_bg.bkg)
|
||||||
e.window.setCursorPos(e.frame.w, 1)
|
e.w_set_cur(e.frame.w, 1)
|
||||||
e.window.write("\x1e")
|
e.w_write("\x1e")
|
||||||
e.window.setCursorPos(e.frame.w, e.frame.h)
|
e.w_set_cur(e.frame.w, e.frame.h)
|
||||||
e.window.write("\x1f")
|
e.w_write("\x1f")
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.setTextColor(e.fg_bg.fgd)
|
e.w_set_fgd(e.fg_bg.fgd)
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- render the scroll bar and re-cacluate height & bounds
|
-- 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
|
for i = 2, e.frame.h - 1 do
|
||||||
if (i >= offset and i < (bar_height + offset)) and (bar_height ~= max_bar_height) then
|
if (i >= offset and i < (bar_height + offset)) and (bar_height ~= max_bar_height) then
|
||||||
if args.nav_fg_bg ~= nil 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
|
else
|
||||||
e.window.setBackgroundColor(e.fg_bg.fgd)
|
e.w_set_bkg(e.fg_bg.fgd)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if args.nav_fg_bg ~= nil then
|
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
|
else
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.setCursorPos(e.frame.w, i)
|
e.w_set_cur(e.frame.w, i)
|
||||||
e.window.write(" ")
|
e.w_write(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
e.w_set_bkg(e.fg_bg.bkg)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update item y positions and move elements
|
-- 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)
|
y_step = util.trinary(pipe.y1 == pipe.y2, 0, y_step)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.setCursorPos(x, y)
|
e.w_set_cur(x, y)
|
||||||
|
|
||||||
local c = core.cpair(pipe.color, e.fg_bg.bkg)
|
local c = core.cpair(pipe.color, e.fg_bg.bkg)
|
||||||
|
|
||||||
@ -84,24 +84,24 @@ local function pipenet(args)
|
|||||||
if i == pipe.w then
|
if i == pipe.w then
|
||||||
-- corner
|
-- corner
|
||||||
if y_step > 0 then
|
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
|
else
|
||||||
e.window.blit("\x8e", c.blit_fgd, c.blit_bkg)
|
e.w_blit("\x8e", c.blit_fgd, c.blit_bkg)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
e.w_blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if i == pipe.w and y_step > 0 then
|
if i == pipe.w and y_step > 0 then
|
||||||
-- corner
|
-- corner
|
||||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
e.w_blit(" ", c.blit_bkg, c.blit_fgd)
|
||||||
else
|
else
|
||||||
e.window.blit("\x8f", c.blit_fgd, c.blit_bkg)
|
e.w_blit("\x8f", c.blit_fgd, c.blit_bkg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
x = x + x_step
|
x = x + x_step
|
||||||
e.window.setCursorPos(x, y)
|
e.w_set_cur(x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- back up one
|
-- back up one
|
||||||
@ -109,12 +109,12 @@ local function pipenet(args)
|
|||||||
|
|
||||||
for _ = 1, pipe.h - 1 do
|
for _ = 1, pipe.h - 1 do
|
||||||
y = y + y_step
|
y = y + y_step
|
||||||
e.window.setCursorPos(x, y)
|
e.w_set_cur(x, y)
|
||||||
|
|
||||||
if pipe.thin then
|
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
|
else
|
||||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
e.w_blit(" ", c.blit_bkg, c.blit_fgd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -124,26 +124,26 @@ local function pipenet(args)
|
|||||||
if i == pipe.h then
|
if i == pipe.h then
|
||||||
-- corner
|
-- corner
|
||||||
if y_step < 0 then
|
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
|
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
|
else
|
||||||
e.window.blit("\x8c", c.blit_fgd, c.blit_bkg)
|
e.w_blit("\x8c", c.blit_fgd, c.blit_bkg)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
e.window.blit("\x95", c.blit_fgd, c.blit_bkg)
|
e.w_blit("\x95", c.blit_fgd, c.blit_bkg)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if i == pipe.h and y_step < 0 then
|
if i == pipe.h and y_step < 0 then
|
||||||
-- corner
|
-- corner
|
||||||
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
e.w_blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||||
else
|
else
|
||||||
e.window.blit(" ", c.blit_bkg, c.blit_fgd)
|
e.w_blit(" ", c.blit_bkg, c.blit_fgd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
y = y + y_step
|
y = y + y_step
|
||||||
e.window.setCursorPos(x, y)
|
e.w_set_cur(x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- back up one
|
-- back up one
|
||||||
@ -151,12 +151,12 @@ local function pipenet(args)
|
|||||||
|
|
||||||
for _ = 1, pipe.w - 1 do
|
for _ = 1, pipe.w - 1 do
|
||||||
x = x + x_step
|
x = x + x_step
|
||||||
e.window.setCursorPos(x, y)
|
e.w_set_cur(x, y)
|
||||||
|
|
||||||
if pipe.thin then
|
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
|
else
|
||||||
e.window.blit("\x83", c.blit_bkg, c.blit_fgd)
|
e.w_blit("\x83", c.blit_bkg, c.blit_fgd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -298,12 +298,12 @@ local function pipenet(args)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.setCursorPos(x, y)
|
e.w_set_cur(x, y)
|
||||||
|
|
||||||
if invert then
|
if invert then
|
||||||
e.window.blit(char, entry.bg, entry.fg)
|
e.w_blit(char, entry.bg, entry.fg)
|
||||||
else
|
else
|
||||||
e.window.blit(char, entry.fg, entry.bg)
|
e.w_blit(char, entry.fg, entry.bg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -56,7 +56,7 @@ local function rectangle(args)
|
|||||||
-- draw bordered box if requested
|
-- draw bordered box if requested
|
||||||
-- element constructor will have drawn basic colored rectangle regardless
|
-- element constructor will have drawn basic colored rectangle regardless
|
||||||
if args.border ~= nil then
|
if args.border ~= nil then
|
||||||
e.window.setCursorPos(1, 1)
|
e.w_set_cur(1, 1)
|
||||||
|
|
||||||
local border_width = offset_x
|
local border_width = offset_x
|
||||||
local border_height = offset_y
|
local border_height = offset_y
|
||||||
@ -70,45 +70,45 @@ local function rectangle(args)
|
|||||||
|
|
||||||
-- form the basic line strings and top/bottom blit strings
|
-- form the basic line strings and top/bottom blit strings
|
||||||
local spaces = util.spaces(e.frame.w)
|
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_fg_sides = blit_fg
|
||||||
local blit_bg_sides = ""
|
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
|
-- partial bars
|
||||||
local p_a, p_b, p_s
|
local p_a, p_b, p_s
|
||||||
if args.thin == true then
|
if args.thin == true then
|
||||||
if args.even_inner == true then
|
if args.even_inner == true then
|
||||||
p_a = "\x9c" .. util.strrep("\x8c", inner_width) .. "\x93"
|
p_a = "\x9c" .. string.rep("\x8c", inner_width) .. "\x93"
|
||||||
p_b = "\x8d" .. util.strrep("\x8c", inner_width) .. "\x8e"
|
p_b = "\x8d" .. string.rep("\x8c", inner_width) .. "\x8e"
|
||||||
else
|
else
|
||||||
p_a = "\x97" .. util.strrep("\x83", inner_width) .. "\x94"
|
p_a = "\x97" .. string.rep("\x83", inner_width) .. "\x94"
|
||||||
p_b = "\x8a" .. util.strrep("\x8f", inner_width) .. "\x85"
|
p_b = "\x8a" .. string.rep("\x8f", inner_width) .. "\x85"
|
||||||
end
|
end
|
||||||
|
|
||||||
p_s = "\x95" .. util.spaces(inner_width) .. "\x95"
|
p_s = "\x95" .. util.spaces(inner_width) .. "\x95"
|
||||||
else
|
else
|
||||||
if args.even_inner == true then
|
if args.even_inner == true then
|
||||||
p_a = util.strrep("\x83", inner_width + width_x2)
|
p_a = string.rep("\x83", inner_width + width_x2)
|
||||||
p_b = util.strrep("\x8f", inner_width + width_x2)
|
p_b = string.rep("\x8f", inner_width + width_x2)
|
||||||
else
|
else
|
||||||
p_a = util.spaces(border_width) .. util.strrep("\x8f", 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) .. util.strrep("\x83", inner_width) .. util.spaces(border_width)
|
p_b = util.spaces(border_width) .. string.rep("\x83", inner_width) .. util.spaces(border_width)
|
||||||
end
|
end
|
||||||
|
|
||||||
p_s = spaces
|
p_s = spaces
|
||||||
end
|
end
|
||||||
|
|
||||||
local p_inv_fg = util.strrep(border_blit, border_width) .. util.strrep(e.fg_bg.blit_bkg, inner_width) ..
|
local p_inv_fg = string.rep(border_blit, border_width) .. string.rep(e.fg_bg.blit_bkg, inner_width) ..
|
||||||
util.strrep(border_blit, border_width)
|
string.rep(border_blit, border_width)
|
||||||
local p_inv_bg = util.strrep(e.fg_bg.blit_bkg, border_width) .. util.strrep(border_blit, inner_width) ..
|
local p_inv_bg = string.rep(e.fg_bg.blit_bkg, border_width) .. string.rep(border_blit, inner_width) ..
|
||||||
util.strrep(e.fg_bg.blit_bkg, border_width)
|
string.rep(e.fg_bg.blit_bkg, border_width)
|
||||||
|
|
||||||
if args.thin == true then
|
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_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 .. util.strrep(border_blit, inner_width) .. util.strrep(e.fg_bg.blit_bkg, 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
|
end
|
||||||
|
|
||||||
-- form the body blit strings (sides are border, inside is normal)
|
-- form the body blit strings (sides are border, inside is normal)
|
||||||
@ -127,28 +127,28 @@ local function rectangle(args)
|
|||||||
|
|
||||||
-- draw rectangle with borders
|
-- draw rectangle with borders
|
||||||
for y = 1, e.frame.h do
|
for y = 1, e.frame.h do
|
||||||
e.window.setCursorPos(1, y)
|
e.w_set_cur(1, y)
|
||||||
-- top border
|
-- top border
|
||||||
if y <= border_height then
|
if y <= border_height then
|
||||||
-- partial pixel fill
|
-- partial pixel fill
|
||||||
if args.border.even and y == border_height then
|
if args.border.even and y == border_height then
|
||||||
if args.thin == true 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
|
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)
|
local _bg = util.trinary(args.even_inner == true, blit_bg_top_bot, p_inv_fg)
|
||||||
|
|
||||||
if width_x2 % 3 == 1 then
|
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
|
elseif width_x2 % 3 == 2 then
|
||||||
e.window.blit(p_a, _fg, _bg)
|
e.w_blit(p_a, _fg, _bg)
|
||||||
else
|
else
|
||||||
-- skip line
|
-- skip line
|
||||||
e.window.blit(spaces, blit_fg, blit_bg_sides)
|
e.w_blit(spaces, blit_fg, blit_bg_sides)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
e.window.blit(spaces, blit_fg, blit_bg_top_bot)
|
e.w_blit(spaces, blit_fg, blit_bg_top_bot)
|
||||||
end
|
end
|
||||||
-- bottom border
|
-- bottom border
|
||||||
elseif y > (e.frame.h - border_width) then
|
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.border.even and y == ((e.frame.h - border_width) + 1) then
|
||||||
if args.thin == true then
|
if args.thin == true then
|
||||||
if args.even_inner == 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
|
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
|
end
|
||||||
else
|
else
|
||||||
local _fg = util.trinary(args.even_inner == true, blit_bg_top_bot, p_inv_fg)
|
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
|
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
|
elseif width_x2 % 3 == 2 then
|
||||||
e.window.blit(p_b, _fg, _bg)
|
e.w_blit(p_b, _fg, _bg)
|
||||||
else
|
else
|
||||||
-- skip line
|
-- skip line
|
||||||
e.window.blit(spaces, blit_fg, blit_bg_sides)
|
e.w_blit(spaces, blit_fg, blit_bg_sides)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
e.window.blit(spaces, blit_fg, blit_bg_top_bot)
|
e.w_blit(spaces, blit_fg, blit_bg_top_bot)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if args.thin == true then
|
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
|
else
|
||||||
e.window.blit(p_s, blit_fg, blit_bg_sides)
|
e.w_blit(p_s, blit_fg, blit_bg_sides)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -45,14 +45,14 @@ local function textbox(args)
|
|||||||
|
|
||||||
-- use cursor position to align this line
|
-- use cursor position to align this line
|
||||||
if alignment == TEXT_ALIGN.CENTER then
|
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
|
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
|
else
|
||||||
e.window.setCursorPos(1, i)
|
e.w_set_cur(1, i)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.window.write(lines[i])
|
e.w_write(lines[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ local function tiling(args)
|
|||||||
|
|
||||||
-- border
|
-- border
|
||||||
if args.border_c ~= nil then
|
if args.border_c ~= nil then
|
||||||
e.window.setBackgroundColor(args.border_c)
|
e.w_set_bkg(args.border_c)
|
||||||
e.window.clear()
|
e.window.clear()
|
||||||
|
|
||||||
start_x = 1 + util.trinary(even, 2, 1)
|
start_x = 1 + util.trinary(even, 2, 1)
|
||||||
@ -60,19 +60,19 @@ local function tiling(args)
|
|||||||
|
|
||||||
-- create pattern
|
-- create pattern
|
||||||
for y = start_y, inner_height + (start_y - 1) do
|
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
|
for _ = 1, inner_width do
|
||||||
if alternator then
|
if alternator then
|
||||||
if even then
|
if even then
|
||||||
e.window.blit(" ", "00", fill_a .. fill_a)
|
e.w_blit(" ", "00", fill_a .. fill_a)
|
||||||
else
|
else
|
||||||
e.window.blit(" ", "0", fill_a)
|
e.w_blit(" ", "0", fill_a)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if even then
|
if even then
|
||||||
e.window.blit(" ", "00", fill_b .. fill_b)
|
e.w_blit(" ", "00", fill_b .. fill_b)
|
||||||
else
|
else
|
||||||
e.window.blit(" ", "0", fill_b)
|
e.w_blit(" ", "0", fill_b)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ local iocontrol = require("pocket.iocontrol")
|
|||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
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
|
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)
|
nic.open(pkt_channel)
|
||||||
|
|
||||||
-- send a management packet to the supervisor
|
-- send a management packet to the supervisor
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_sv(msg_type, msg)
|
local function _send_sv(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
@ -65,7 +65,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send a management packet to the coordinator
|
-- send a management packet to the coordinator
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_crd(msg_type, msg)
|
local function _send_crd(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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
|
-- attempt supervisor connection establishment
|
||||||
local function _send_sv_establish()
|
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
|
end
|
||||||
|
|
||||||
-- attempt coordinator API connection establishment
|
-- attempt coordinator API connection establishment
|
||||||
local function _send_api_establish()
|
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
|
end
|
||||||
|
|
||||||
-- keep alive ack to supervisor
|
-- keep alive ack to supervisor
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_sv_keep_alive_ack(srv_time)
|
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
|
end
|
||||||
|
|
||||||
-- keep alive ack to coordinator
|
-- keep alive ack to coordinator
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_api_keep_alive_ack(srv_time)
|
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
|
end
|
||||||
|
|
||||||
-- PUBLIC FUNCTIONS --
|
-- PUBLIC FUNCTIONS --
|
||||||
@ -111,7 +111,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
|||||||
self.sv.linked = false
|
self.sv.linked = false
|
||||||
self.sv.r_seq_num = nil
|
self.sv.r_seq_num = nil
|
||||||
self.sv.addr = comms.BROADCAST
|
self.sv.addr = comms.BROADCAST
|
||||||
_send_sv(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_sv(MGMT_TYPE.CLOSE, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- close connection to coordinator API server
|
-- 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.linked = false
|
||||||
self.api.r_seq_num = nil
|
self.api.r_seq_num = nil
|
||||||
self.api.addr = comms.BROADCAST
|
self.api.addr = comms.BROADCAST
|
||||||
_send_crd(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_crd(MGMT_TYPE.CLOSE, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- close the connections to the servers
|
-- 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
|
-- supervisor get active alarm tones
|
||||||
function public.diag__get_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
|
end
|
||||||
|
|
||||||
-- supervisor test alarm tones by tone
|
-- supervisor test alarm tones by tone
|
||||||
---@param id TONE|0 tone ID, or 0 to stop all
|
---@param id TONE|0 tone ID, or 0 to stop all
|
||||||
---@param state boolean tone state
|
---@param state boolean tone state
|
||||||
function public.diag__set_alarm_tone(id, 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
|
end
|
||||||
|
|
||||||
-- supervisor test alarm tones by alarm
|
-- supervisor test alarm tones by alarm
|
||||||
---@param id ALARM|0 alarm ID, 0 to stop all
|
---@param id ALARM|0 alarm ID, 0 to stop all
|
||||||
---@param state boolean alarm state
|
---@param state boolean alarm state
|
||||||
function public.diag__set_alarm(id, 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
|
end
|
||||||
|
|
||||||
-- parse a packet
|
-- parse a packet
|
||||||
@ -180,7 +180,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
|||||||
---@param reply_to integer
|
---@param reply_to integer
|
||||||
---@param message any
|
---@param message any
|
||||||
---@param distance integer
|
---@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)
|
function public.parse_packet(side, sender, reply_to, message, distance)
|
||||||
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
local s_pkt = nic.receive(side, sender, reply_to, message, distance)
|
||||||
local pkt = nil
|
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
|
if mgmt_pkt.decode(s_pkt) then
|
||||||
pkt = mgmt_pkt.get()
|
pkt = mgmt_pkt.get()
|
||||||
end
|
end
|
||||||
-- get as coordinator API packet
|
-- get as coordinator packet
|
||||||
elseif s_pkt.protocol() == PROTOCOL.COORD_API then
|
elseif s_pkt.protocol() == PROTOCOL.SCADA_CRDN then
|
||||||
local capi_pkt = comms.capi_packet()
|
local crdn_pkt = comms.crdn_packet()
|
||||||
if capi_pkt.decode(s_pkt) then
|
if crdn_pkt.decode(s_pkt) then
|
||||||
pkt = capi_pkt.get()
|
pkt = crdn_pkt.get()
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
log.debug("attempted parse of illegal packet type " .. s_pkt.protocol(), true)
|
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
|
end
|
||||||
|
|
||||||
-- handle a packet
|
-- handle a packet
|
||||||
---@param packet mgmt_frame|capi_frame|nil
|
---@param packet mgmt_frame|crdn_frame|nil
|
||||||
function public.handle_packet(packet)
|
function public.handle_packet(packet)
|
||||||
local diag = iocontrol.get_db().diag
|
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
|
if protocol == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast packet mgmt_frame
|
---@cast packet mgmt_frame
|
||||||
if self.api.linked then
|
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
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -256,7 +256,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
|||||||
else
|
else
|
||||||
log.debug("coordinator SCADA keep alive packet length mismatch")
|
log.debug("coordinator SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||||
-- handle session close
|
-- handle session close
|
||||||
api_watchdog.cancel()
|
api_watchdog.cancel()
|
||||||
self.api.linked = false
|
self.api.linked = false
|
||||||
@ -266,7 +266,7 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
|||||||
else
|
else
|
||||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from coordinator")
|
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from coordinator")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||||
-- connection with coordinator established
|
-- connection with coordinator established
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local est_ack = packet.data[1]
|
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
|
if protocol == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast packet mgmt_frame
|
---@cast packet mgmt_frame
|
||||||
if self.sv.linked then
|
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
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -346,14 +346,14 @@ function pocket.comms(version, nic, pkt_channel, svr_channel, crd_channel, range
|
|||||||
else
|
else
|
||||||
log.debug("supervisor SCADA keep alive packet length mismatch")
|
log.debug("supervisor SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||||
-- handle session close
|
-- handle session close
|
||||||
sv_watchdog.cancel()
|
sv_watchdog.cancel()
|
||||||
self.sv.linked = false
|
self.sv.linked = false
|
||||||
self.sv.r_seq_num = nil
|
self.sv.r_seq_num = nil
|
||||||
self.sv.addr = comms.BROADCAST
|
self.sv.addr = comms.BROADCAST
|
||||||
log.info("supervisor server connection closed by remote host")
|
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
|
if packet.length == 8 then
|
||||||
for i = 1, #packet.data do
|
for i = 1, #packet.data do
|
||||||
diag.tone_test.tone_indicators[i].update(packet.data[i] == true)
|
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
|
else
|
||||||
log.debug("supervisor SCADA diag alarm states packet length mismatch")
|
log.debug("supervisor SCADA diag alarm states packet length mismatch")
|
||||||
end
|
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
|
if packet.length == 1 and packet.data[1] == false then
|
||||||
diag.tone_test.ready_warn.set_value("testing denied")
|
diag.tone_test.ready_warn.set_value("testing denied")
|
||||||
log.debug("supervisor SCADA diag tone set failed")
|
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
|
else
|
||||||
log.debug("supervisor SCADA diag tone set packet length/type mismatch")
|
log.debug("supervisor SCADA diag tone set packet length/type mismatch")
|
||||||
end
|
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
|
if packet.length == 1 and packet.data[1] == false then
|
||||||
diag.tone_test.ready_warn.set_value("testing denied")
|
diag.tone_test.ready_warn.set_value("testing denied")
|
||||||
log.debug("supervisor SCADA diag alarm set failed")
|
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
|
else
|
||||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from supervisor")
|
log.debug("received unknown SCADA_MGMT packet type " .. packet.type .. " from supervisor")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||||
-- connection with supervisor established
|
-- connection with supervisor established
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local est_ack = packet.data[1]
|
local est_ack = packet.data[1]
|
||||||
|
@ -18,7 +18,7 @@ local iocontrol = require("pocket.iocontrol")
|
|||||||
local pocket = require("pocket.pocket")
|
local pocket = require("pocket.pocket")
|
||||||
local renderer = require("pocket.renderer")
|
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 = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
@ -28,6 +28,9 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
|||||||
local cpair = core.cpair
|
local cpair = core.cpair
|
||||||
local border = core.border
|
local border = core.border
|
||||||
|
|
||||||
|
local ind_grn = style.ind_grn
|
||||||
|
local ind_red = style.ind_red
|
||||||
|
|
||||||
-- create new front panel view
|
-- create new front panel view
|
||||||
---@param panel graphics_element main displaybox
|
---@param panel graphics_element main displaybox
|
||||||
local function init(panel)
|
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 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 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()
|
system.line_break()
|
||||||
|
|
||||||
init_ok.register(databus.ps, "init_ok", init_ok.update)
|
init_ok.register(databus.ps, "init_ok", init_ok.update)
|
||||||
heartbeat.register(databus.ps, "heartbeat", heartbeat.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 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}}
|
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)
|
network.update(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
@ -57,11 +60,11 @@ local function init(panel)
|
|||||||
modem.register(databus.ps, "has_modem", modem.update)
|
modem.register(databus.ps, "has_modem", modem.update)
|
||||||
network.register(databus.ps, "link_state", network.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_main = LED{parent=system,label="RT MAIN",colors=ind_grn}
|
||||||
local rt_rps = LED{parent=system,label="RT RPS",colors=cpair(colors.green,colors.green_off)}
|
local rt_rps = LED{parent=system,label="RT RPS",colors=ind_grn}
|
||||||
local rt_cmtx = LED{parent=system,label="RT COMMS TX",colors=cpair(colors.green,colors.green_off)}
|
local rt_cmtx = LED{parent=system,label="RT COMMS TX",colors=ind_grn}
|
||||||
local rt_cmrx = LED{parent=system,label="RT COMMS RX",colors=cpair(colors.green,colors.green_off)}
|
local rt_cmrx = LED{parent=system,label="RT COMMS RX",colors=ind_grn}
|
||||||
local rt_sctl = LED{parent=system,label="RT SPCTL",colors=cpair(colors.green,colors.green_off)}
|
local rt_sctl = LED{parent=system,label="RT SPCTL",colors=ind_grn}
|
||||||
system.line_break()
|
system.line_break()
|
||||||
|
|
||||||
rt_main.register(databus.ps, "routine__main", rt_main.update)
|
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 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
|
-- only show emergency coolant LED if emergency coolant is configured for this device
|
||||||
if type(config.EMERGENCY_COOL) == "table" then
|
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_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 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_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)}
|
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 = 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_man = LED{parent=rps,label="MANUAL",colors=ind_red}
|
||||||
local rps_auto = LED{parent=rps,label="AUTOMATIC",colors=cpair(colors.red,colors.red_off)}
|
local rps_auto = LED{parent=rps,label="AUTOMATIC",colors=ind_red}
|
||||||
local rps_tmo = LED{parent=rps,label="TIMEOUT",colors=cpair(colors.red,colors.red_off)}
|
local rps_tmo = LED{parent=rps,label="TIMEOUT",colors=ind_red}
|
||||||
local rps_flt = LED{parent=rps,label="PLC FAULT",colors=cpair(colors.red,colors.red_off)}
|
local rps_flt = LED{parent=rps,label="PLC FAULT",colors=ind_red}
|
||||||
local rps_fail = LED{parent=rps,label="RCT FAULT",colors=cpair(colors.red,colors.red_off)}
|
local rps_fail = LED{parent=rps,label="RCT FAULT",colors=ind_red}
|
||||||
rps.line_break()
|
rps.line_break()
|
||||||
local rps_dmg = LED{parent=rps,label="HI DAMAGE",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=cpair(colors.red,colors.red_off)}
|
local rps_tmp = LED{parent=rps,label="HI TEMP",colors=ind_red}
|
||||||
rps.line_break()
|
rps.line_break()
|
||||||
local rps_nof = LED{parent=rps,label="LO FUEL",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=cpair(colors.red,colors.red_off)}
|
local rps_wst = LED{parent=rps,label="HI WASTE",colors=ind_red}
|
||||||
rps.line_break()
|
rps.line_break()
|
||||||
local rps_ccl = LED{parent=rps,label="LO CCOOLANT",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=cpair(colors.red,colors.red_off)}
|
local rps_hcl = LED{parent=rps,label="HI HCOOLANT",colors=ind_red}
|
||||||
|
|
||||||
rps_man.register(databus.ps, "rps_manual", rps_man.update)
|
rps_man.register(databus.ps, "rps_manual", rps_man.update)
|
||||||
rps_auto.register(databus.ps, "rps_automatic", rps_auto.update)
|
rps_auto.register(databus.ps, "rps_automatic", rps_auto.update)
|
||||||
|
@ -39,4 +39,9 @@ style.colors = {
|
|||||||
{ c = colors.brown, hex = 0x672223 } -- RED OFF
|
{ 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
|
return style
|
||||||
|
@ -16,7 +16,7 @@ local PROTOCOL = comms.PROTOCOL
|
|||||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||||
local RPLC_TYPE = comms.RPLC_TYPE
|
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 AUTO_ACK = comms.PLC_AUTO_ACK
|
||||||
|
|
||||||
local RPS_LIMITS = const.RPS_LIMITS
|
local RPS_LIMITS = const.RPS_LIMITS
|
||||||
@ -489,7 +489,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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
|
-- keep alive ack
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_keep_alive_ack(srv_time)
|
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
|
end
|
||||||
|
|
||||||
-- general ack
|
-- general ack
|
||||||
@ -668,12 +668,12 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
|||||||
function public.close()
|
function public.close()
|
||||||
conn_watchdog.cancel()
|
conn_watchdog.cancel()
|
||||||
public.unlink()
|
public.unlink()
|
||||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- attempt to establish link with supervisor
|
-- attempt to establish link with supervisor
|
||||||
function public.send_link_req()
|
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
|
end
|
||||||
|
|
||||||
-- send live status information
|
-- 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
|
---@cast packet mgmt_frame
|
||||||
-- if linked, only accept packets from configured supervisor
|
-- if linked, only accept packets from configured supervisor
|
||||||
if self.linked then
|
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
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -945,7 +945,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
|||||||
else
|
else
|
||||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||||
-- handle session close
|
-- handle session close
|
||||||
conn_watchdog.cancel()
|
conn_watchdog.cancel()
|
||||||
public.unlink()
|
public.unlink()
|
||||||
@ -954,7 +954,7 @@ function plc.comms(id, version, nic, plc_channel, svr_channel, range, reactor, r
|
|||||||
else
|
else
|
||||||
log.debug("received unsupported SCADA_MGMT packet type " .. packet.type)
|
log.debug("received unsupported SCADA_MGMT packet type " .. packet.type)
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||||
-- link request confirmation
|
-- link request confirmation
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local est_ack = packet.data[1]
|
local est_ack = packet.data[1]
|
||||||
|
@ -19,7 +19,7 @@ local plc = require("reactor-plc.plc")
|
|||||||
local renderer = require("reactor-plc.renderer")
|
local renderer = require("reactor-plc.renderer")
|
||||||
local threads = require("reactor-plc.threads")
|
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 = util.println
|
||||||
local println_ts = util.println_ts
|
local println_ts = util.println_ts
|
||||||
|
@ -22,8 +22,11 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
|||||||
|
|
||||||
local cpair = core.cpair
|
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
|
-- create new front panel view
|
||||||
---@param panel graphics_element main displaybox
|
---@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 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 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)
|
on.update(true)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
|
|
||||||
heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
|
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}}
|
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)
|
network.update(types.PANEL_LINK_STATE.DISCONNECTED)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
@ -52,8 +55,8 @@ local function init(panel, units)
|
|||||||
modem.register(databus.ps, "has_modem", modem.update)
|
modem.register(databus.ps, "has_modem", modem.update)
|
||||||
network.register(databus.ps, "link_state", network.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_main = LED{parent=system,label="RT MAIN",colors=ind_grn}
|
||||||
local rt_comm = LED{parent=system,label="RT COMMS",colors=cpair(colors.green,colors.green_off)}
|
local rt_comm = LED{parent=system,label="RT COMMS",colors=ind_grn}
|
||||||
system.line_break()
|
system.line_break()
|
||||||
|
|
||||||
rt_main.register(databus.ps, "routine__main", rt_main.update)
|
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
|
---@diagnostic disable-next-line: undefined-field
|
||||||
local comp_id = util.sprintf("(%d)", os.getComputerID())
|
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}
|
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)}
|
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
|
-- 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 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}
|
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
|
-- show routine statuses
|
||||||
for i = 1, list_length do
|
for i = 1, list_length do
|
||||||
TextBox{parent=threads,x=1,y=i,text=util.sprintf("%02d",i),height=1}
|
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)
|
rt_unit.register(databus.ps, "routine__unit_" .. i, rt_unit.update)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -115,7 +118,7 @@ local function init(panel, units)
|
|||||||
|
|
||||||
-- assignment (unit # or facility)
|
-- assignment (unit # or facility)
|
||||||
local for_unit = util.trinary(unit.reactor == 0, "\x1a FACIL ", "\x1a UNIT " .. unit.reactor)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -39,4 +39,10 @@ style.colors = {
|
|||||||
{ c = colors.brown, hex = 0x672223 } -- RED OFF
|
{ 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
|
return style
|
||||||
|
24
rtu/rtu.lua
24
rtu/rtu.lua
@ -14,7 +14,7 @@ local rtu = {}
|
|||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
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
|
local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||||
|
|
||||||
-- create a new RTU unit
|
-- 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)
|
nic.open(rtu_channel)
|
||||||
|
|
||||||
-- send a scada management packet
|
-- send a scada management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send(msg_type, msg)
|
local function _send(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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
|
-- keep alive ack
|
||||||
---@param srv_time integer
|
---@param srv_time integer
|
||||||
local function _send_keep_alive_ack(srv_time)
|
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
|
end
|
||||||
|
|
||||||
-- generate device advertisement table
|
-- 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)
|
function public.close(rtu_state)
|
||||||
conn_watchdog.cancel()
|
conn_watchdog.cancel()
|
||||||
public.unlink(rtu_state)
|
public.unlink(rtu_state)
|
||||||
_send(SCADA_MGMT_TYPE.CLOSE, {})
|
_send(MGMT_TYPE.CLOSE, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send establish request (includes advertisement)
|
-- send establish request (includes advertisement)
|
||||||
---@param units table
|
---@param units table
|
||||||
function public.send_establish(units)
|
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
|
end
|
||||||
|
|
||||||
-- send capability advertisement
|
-- send capability advertisement
|
||||||
---@param units table
|
---@param units table
|
||||||
function public.send_advertisement(units)
|
function public.send_advertisement(units)
|
||||||
_send(SCADA_MGMT_TYPE.RTU_ADVERT, _generate_advertisement(units))
|
_send(MGMT_TYPE.RTU_ADVERT, _generate_advertisement(units))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- notify that a peripheral was remounted
|
-- notify that a peripheral was remounted
|
||||||
---@param unit_index integer RTU unit ID
|
---@param unit_index integer RTU unit ID
|
||||||
function public.send_remounted(unit_index)
|
function public.send_remounted(unit_index)
|
||||||
_send(SCADA_MGMT_TYPE.RTU_DEV_REMOUNT, { unit_index })
|
_send(MGMT_TYPE.RTU_DEV_REMOUNT, { unit_index })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- parse a MODBUS/SCADA packet
|
-- 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
|
---@cast packet mgmt_frame
|
||||||
-- SCADA management packet
|
-- SCADA management packet
|
||||||
if rtu_state.linked then
|
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
|
-- keep alive request received, echo back
|
||||||
if packet.length == 1 and type(packet.data[1]) == "number" then
|
if packet.length == 1 and type(packet.data[1]) == "number" then
|
||||||
local timestamp = packet.data[1]
|
local timestamp = packet.data[1]
|
||||||
@ -449,16 +449,16 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
|||||||
else
|
else
|
||||||
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
log.debug("SCADA_MGMT keep alive packet length/type mismatch")
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif packet.type == MGMT_TYPE.CLOSE then
|
||||||
-- close connection
|
-- close connection
|
||||||
conn_watchdog.cancel()
|
conn_watchdog.cancel()
|
||||||
public.unlink(rtu_state)
|
public.unlink(rtu_state)
|
||||||
println_ts("server connection closed by remote host")
|
println_ts("server connection closed by remote host")
|
||||||
log.warning("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
|
-- request for capabilities again
|
||||||
public.send_advertisement(units)
|
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
|
-- alarm tone update from supervisor
|
||||||
if (packet.length == 1) and type(packet.data[1] == "table") and (#packet.data[1] == 8) then
|
if (packet.length == 1) and type(packet.data[1] == "table") and (#packet.data[1] == 8) then
|
||||||
local states = packet.data[1]
|
local states = packet.data[1]
|
||||||
@ -474,7 +474,7 @@ function rtu.comms(version, nic, rtu_channel, svr_channel, range, conn_watchdog)
|
|||||||
-- not supported
|
-- not supported
|
||||||
log.debug("received unsupported SCADA_MGMT message type " .. packet.type)
|
log.debug("received unsupported SCADA_MGMT message type " .. packet.type)
|
||||||
end
|
end
|
||||||
elseif packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
elseif packet.type == MGMT_TYPE.ESTABLISH then
|
||||||
if packet.length == 1 then
|
if packet.length == 1 then
|
||||||
local est_ack = packet.data[1]
|
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 sps_rtu = require("rtu.dev.sps_rtu")
|
||||||
local turbinev_rtu = require("rtu.dev.turbinev_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_TYPE = types.RTU_UNIT_TYPE
|
||||||
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE
|
||||||
|
@ -6,23 +6,25 @@ local log = require("scada-common.log")
|
|||||||
|
|
||||||
local insert = table.insert
|
local insert = table.insert
|
||||||
|
|
||||||
|
---@type integer computer ID
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@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
|
---@class comms
|
||||||
local 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
|
---@enum PROTOCOL
|
||||||
local PROTOCOL = {
|
local PROTOCOL = {
|
||||||
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
MODBUS_TCP = 0, -- the "MODBUS TCP"-esque protocol
|
||||||
RPLC = 1, -- reactor PLC protocol
|
RPLC = 1, -- reactor PLC protocol
|
||||||
SCADA_MGMT = 2, -- SCADA supervisor management, device advertisements, etc
|
SCADA_MGMT = 2, -- SCADA supervisor management, device advertisements, etc
|
||||||
SCADA_CRDN = 3, -- data/control packets for coordinators to/from supervisory controllers
|
SCADA_CRDN = 3 -- data/control packets for coordinators to/from supervisory controllers
|
||||||
COORD_API = 4 -- data/control packets for pocket computers to/from coordinators
|
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum RPLC_TYPE
|
---@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
|
AUTO_BURN_RATE = 10 -- set an automatic burn rate, PLC will respond with status, enable toggle speed limited
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum SCADA_MGMT_TYPE
|
---@enum MGMT_TYPE
|
||||||
local SCADA_MGMT_TYPE = {
|
local MGMT_TYPE = {
|
||||||
ESTABLISH = 0, -- establish new connection
|
ESTABLISH = 0, -- establish new connection
|
||||||
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
|
||||||
CLOSE = 2, -- close a connection
|
CLOSE = 2, -- close a connection
|
||||||
@ -53,8 +55,8 @@ local SCADA_MGMT_TYPE = {
|
|||||||
DIAG_ALARM_SET = 8 -- diagnostic: set alarm to simulate audio for
|
DIAG_ALARM_SET = 8 -- diagnostic: set alarm to simulate audio for
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum SCADA_CRDN_TYPE
|
---@enum CRDN_TYPE
|
||||||
local SCADA_CRDN_TYPE = {
|
local CRDN_TYPE = {
|
||||||
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
INITIAL_BUILDS = 0, -- initial, complete builds packet to the coordinator
|
||||||
FAC_BUILDS = 1, -- facility RTU builds
|
FAC_BUILDS = 1, -- facility RTU builds
|
||||||
FAC_STATUS = 2, -- state of facility and facility devices
|
FAC_STATUS = 2, -- state of facility and facility devices
|
||||||
@ -64,10 +66,6 @@ local SCADA_CRDN_TYPE = {
|
|||||||
UNIT_CMD = 6 -- command a reactor unit
|
UNIT_CMD = 6 -- command a reactor unit
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum CAPI_TYPE
|
|
||||||
local CAPI_TYPE = {
|
|
||||||
}
|
|
||||||
|
|
||||||
---@enum ESTABLISH_ACK
|
---@enum ESTABLISH_ACK
|
||||||
local ESTABLISH_ACK = {
|
local ESTABLISH_ACK = {
|
||||||
ALLOW = 0, -- link approved
|
ALLOW = 0, -- link approved
|
||||||
@ -76,14 +74,8 @@ local ESTABLISH_ACK = {
|
|||||||
BAD_VERSION = 3 -- link denied due to comms version mismatch
|
BAD_VERSION = 3 -- link denied due to comms version mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
---@enum DEVICE_TYPE
|
---@enum DEVICE_TYPE device types for establish messages
|
||||||
local DEVICE_TYPE = {
|
local DEVICE_TYPE = { PLC = 0, RTU = 1, SVR = 2, CRD = 3, PKT = 4 }
|
||||||
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 PLC_AUTO_ACK
|
---@enum PLC_AUTO_ACK
|
||||||
local PLC_AUTO_ACK = {
|
local PLC_AUTO_ACK = {
|
||||||
@ -119,9 +111,8 @@ local UNIT_COMMAND = {
|
|||||||
comms.PROTOCOL = PROTOCOL
|
comms.PROTOCOL = PROTOCOL
|
||||||
|
|
||||||
comms.RPLC_TYPE = RPLC_TYPE
|
comms.RPLC_TYPE = RPLC_TYPE
|
||||||
comms.SCADA_MGMT_TYPE = SCADA_MGMT_TYPE
|
comms.MGMT_TYPE = MGMT_TYPE
|
||||||
comms.SCADA_CRDN_TYPE = SCADA_CRDN_TYPE
|
comms.CRDN_TYPE = CRDN_TYPE
|
||||||
comms.CAPI_TYPE = CAPI_TYPE
|
|
||||||
|
|
||||||
comms.ESTABLISH_ACK = ESTABLISH_ACK
|
comms.ESTABLISH_ACK = ESTABLISH_ACK
|
||||||
comms.DEVICE_TYPE = DEVICE_TYPE
|
comms.DEVICE_TYPE = DEVICE_TYPE
|
||||||
@ -134,8 +125,8 @@ comms.FAC_COMMAND = FAC_COMMAND
|
|||||||
-- destination broadcast address (to all devices)
|
-- destination broadcast address (to all devices)
|
||||||
comms.BROADCAST = -1
|
comms.BROADCAST = -1
|
||||||
|
|
||||||
---@alias packet scada_packet|modbus_packet|rplc_packet|mgmt_packet|crdn_packet|capi_packet
|
---@alias packet scada_packet|modbus_packet|rplc_packet|mgmt_packet|crdn_packet
|
||||||
---@alias frame modbus_frame|rplc_frame|mgmt_frame|crdn_frame|capi_frame
|
---@alias frame modbus_frame|rplc_frame|mgmt_frame|crdn_frame
|
||||||
|
|
||||||
-- configure the maximum allowable message receive distance<br>
|
-- configure the maximum allowable message receive distance<br>
|
||||||
-- packets received with distances greater than this will be silently discarded
|
-- 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
|
if distance == 0 then max_distance = nil else max_distance = distance end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generic SCADA packet object
|
-- generic SCADA packet
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function comms.scada_packet()
|
function comms.scada_packet()
|
||||||
local self = {
|
local self = {
|
||||||
@ -199,9 +190,9 @@ function comms.scada_packet()
|
|||||||
self.valid = false
|
self.valid = false
|
||||||
self.raw = self.modem_msg_in.msg
|
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
|
-- 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
|
else
|
||||||
if type(self.raw) == "table" then
|
if type(self.raw) == "table" then
|
||||||
if #self.raw == 5 then
|
if #self.raw == 5 then
|
||||||
@ -227,12 +218,8 @@ function comms.scada_packet()
|
|||||||
-- check if this packet is destined for this device
|
-- check if this packet is destined for this device
|
||||||
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
||||||
|
|
||||||
self.valid = is_destination and
|
self.valid = is_destination and type(self.src_addr) == "number" and type(self.dest_addr) == "number" and
|
||||||
type(self.src_addr) == "number" and
|
type(self.seq_num) == "number" and type(self.protocol) == "number" and type(self.payload) == "table"
|
||||||
type(self.dest_addr) == "number" and
|
|
||||||
type(self.seq_num) == "number" and
|
|
||||||
type(self.protocol) == "number" and
|
|
||||||
type(self.payload) == "table"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -275,7 +262,7 @@ function comms.scada_packet()
|
|||||||
return public
|
return public
|
||||||
end
|
end
|
||||||
|
|
||||||
-- authenticated SCADA packet object
|
-- authenticated SCADA packet
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function comms.authd_packet()
|
function comms.authd_packet()
|
||||||
local self = {
|
local self = {
|
||||||
@ -325,7 +312,7 @@ function comms.authd_packet()
|
|||||||
|
|
||||||
if (type(max_distance) == "number") and (type(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
|
-- 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
|
else
|
||||||
if type(self.raw) == "table" then
|
if type(self.raw) == "table" then
|
||||||
if #self.raw == 4 then
|
if #self.raw == 4 then
|
||||||
@ -343,11 +330,8 @@ function comms.authd_packet()
|
|||||||
-- check if this packet is destined for this device
|
-- check if this packet is destined for this device
|
||||||
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
local is_destination = (self.dest_addr == comms.BROADCAST) or (self.dest_addr == COMPUTER_ID)
|
||||||
|
|
||||||
self.valid = is_destination and
|
self.valid = is_destination and type(self.src_addr) == "number" and type(self.dest_addr) == "number" and
|
||||||
type(self.src_addr) == "number" and
|
type(self.mac) == "string" and type(self.payload) == "string"
|
||||||
type(self.dest_addr) == "number" and
|
|
||||||
type(self.mac) == "string" and
|
|
||||||
type(self.payload) == "string"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -381,8 +365,7 @@ function comms.authd_packet()
|
|||||||
return public
|
return public
|
||||||
end
|
end
|
||||||
|
|
||||||
-- MODBUS packet<br>
|
-- MODBUS packet, modeled after MODBUS TCP
|
||||||
-- modeled after MODBUS TCP packet
|
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function comms.modbus_packet()
|
function comms.modbus_packet()
|
||||||
local self = {
|
local self = {
|
||||||
@ -436,9 +419,7 @@ function comms.modbus_packet()
|
|||||||
public.make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
|
public.make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
|
||||||
end
|
end
|
||||||
|
|
||||||
local valid = type(self.txn_id) == "number" and
|
local valid = type(self.txn_id) == "number" and type(self.unit_id) == "number" and type(self.func_code) == "number"
|
||||||
type(self.unit_id) == "number" and
|
|
||||||
type(self.func_code) == "number"
|
|
||||||
|
|
||||||
return size_ok and valid
|
return size_ok and valid
|
||||||
else
|
else
|
||||||
@ -489,21 +470,6 @@ function comms.rplc_packet()
|
|||||||
---@class rplc_packet
|
---@class rplc_packet
|
||||||
local public = {}
|
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
|
-- make an RPLC packet
|
||||||
---@param id integer
|
---@param id integer
|
||||||
---@param packet_type RPLC_TYPE
|
---@param packet_type RPLC_TYPE
|
||||||
@ -539,7 +505,6 @@ function comms.rplc_packet()
|
|||||||
if ok then
|
if ok then
|
||||||
local data = frame.data()
|
local data = frame.data()
|
||||||
public.make(data[1], data[2], { table.unpack(data, 3, #data) })
|
public.make(data[1], data[2], { table.unpack(data, 3, #data) })
|
||||||
ok = _rplc_type_valid()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ok = ok and type(self.id) == "number"
|
ok = ok and type(self.id) == "number"
|
||||||
@ -583,7 +548,7 @@ function comms.mgmt_packet()
|
|||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
raw = {},
|
raw = {},
|
||||||
type = 0, ---@type SCADA_MGMT_TYPE
|
type = 0, ---@type MGMT_TYPE
|
||||||
length = 0,
|
length = 0,
|
||||||
data = {}
|
data = {}
|
||||||
}
|
}
|
||||||
@ -591,22 +556,8 @@ function comms.mgmt_packet()
|
|||||||
---@class mgmt_packet
|
---@class mgmt_packet
|
||||||
local public = {}
|
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
|
-- make a SCADA management packet
|
||||||
---@param packet_type SCADA_MGMT_TYPE
|
---@param packet_type MGMT_TYPE
|
||||||
---@param data table
|
---@param data table
|
||||||
function public.make(packet_type, data)
|
function public.make(packet_type, data)
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
@ -638,7 +589,6 @@ function comms.mgmt_packet()
|
|||||||
if ok then
|
if ok then
|
||||||
local data = frame.data()
|
local data = frame.data()
|
||||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||||
ok = _scada_type_valid()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
@ -679,7 +629,7 @@ function comms.crdn_packet()
|
|||||||
local self = {
|
local self = {
|
||||||
frame = nil,
|
frame = nil,
|
||||||
raw = {},
|
raw = {},
|
||||||
type = 0, ---@type SCADA_CRDN_TYPE
|
type = 0, ---@type CRDN_TYPE
|
||||||
length = 0,
|
length = 0,
|
||||||
data = {}
|
data = {}
|
||||||
}
|
}
|
||||||
@ -687,20 +637,8 @@ function comms.crdn_packet()
|
|||||||
---@class crdn_packet
|
---@class crdn_packet
|
||||||
local public = {}
|
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
|
-- make a coordinator packet
|
||||||
---@param packet_type SCADA_CRDN_TYPE
|
---@param packet_type CRDN_TYPE
|
||||||
---@param data table
|
---@param data table
|
||||||
function public.make(packet_type, data)
|
function public.make(packet_type, data)
|
||||||
if type(data) == "table" then
|
if type(data) == "table" then
|
||||||
@ -732,7 +670,6 @@ function comms.crdn_packet()
|
|||||||
if ok then
|
if ok then
|
||||||
local data = frame.data()
|
local data = frame.data()
|
||||||
public.make(data[1], { table.unpack(data, 2, #data) })
|
public.make(data[1], { table.unpack(data, 2, #data) })
|
||||||
ok = _crdn_type_valid()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
@ -767,92 +704,4 @@ function comms.crdn_packet()
|
|||||||
return public
|
return public
|
||||||
end
|
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
|
return comms
|
||||||
|
@ -8,7 +8,7 @@ local cc_strings = require("cc.strings")
|
|||||||
local util = {}
|
local util = {}
|
||||||
|
|
||||||
-- scada-common version
|
-- scada-common version
|
||||||
util.version = "1.0.2"
|
util.version = "1.1.0"
|
||||||
|
|
||||||
-- ENVIRONMENT CONSTANTS --
|
-- ENVIRONMENT CONSTANTS --
|
||||||
|
|
||||||
@ -76,25 +76,12 @@ function util.strval(val)
|
|||||||
end
|
end
|
||||||
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
|
-- repeat a space n times
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@param n integer
|
---@param n integer
|
||||||
---@return string
|
---@return string
|
||||||
function util.spaces(n)
|
function util.spaces(n)
|
||||||
return util.strrep(" ", n)
|
return string.rep(" ", n)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- pad text to a minimum width
|
-- pad text to a minimum width
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
local databus = require("supervisor.databus")
|
local databus = require("supervisor.databus")
|
||||||
|
|
||||||
|
local style = require("supervisor.panel.style")
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
|
|
||||||
local Div = require("graphics.elements.div")
|
local Div = require("graphics.elements.div")
|
||||||
@ -15,28 +17,31 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
|||||||
|
|
||||||
local cpair = core.cpair
|
local cpair = core.cpair
|
||||||
|
|
||||||
|
local black_lg = style.black_lg
|
||||||
|
local lg_white = style.lg_white
|
||||||
|
|
||||||
-- create a pocket diagnostics list entry
|
-- create a pocket diagnostics list entry
|
||||||
---@param parent graphics_element parent
|
---@param parent graphics_element parent
|
||||||
---@param id integer PDG session ID
|
---@param id integer PDG session ID
|
||||||
local function init(parent, id)
|
local function init(parent, id)
|
||||||
-- root div
|
-- root div
|
||||||
local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true}
|
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 .. "_"
|
local ps_prefix = "pdg_" .. id .. "_"
|
||||||
|
|
||||||
TextBox{parent=entry,x=1,y=1,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=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)}
|
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=cpair(colors.black,colors.lightGray)}
|
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)
|
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}
|
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)
|
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}
|
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)}
|
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=cpair(colors.lightGray,colors.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", pdg_rtt.update)
|
||||||
pdg_rtt.register(databus.ps, ps_prefix .. "rtt_color", pdg_rtt.recolor)
|
pdg_rtt.register(databus.ps, ps_prefix .. "rtt_color", pdg_rtt.recolor)
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
local databus = require("supervisor.databus")
|
local databus = require("supervisor.databus")
|
||||||
|
|
||||||
|
local style = require("supervisor.panel.style")
|
||||||
|
|
||||||
local core = require("graphics.core")
|
local core = require("graphics.core")
|
||||||
|
|
||||||
local Div = require("graphics.elements.div")
|
local Div = require("graphics.elements.div")
|
||||||
@ -15,32 +17,35 @@ local TEXT_ALIGN = core.TEXT_ALIGN
|
|||||||
|
|
||||||
local cpair = core.cpair
|
local cpair = core.cpair
|
||||||
|
|
||||||
|
local black_lg = style.black_lg
|
||||||
|
local lg_white = style.lg_white
|
||||||
|
|
||||||
-- create an RTU list entry
|
-- create an RTU list entry
|
||||||
---@param parent graphics_element parent
|
---@param parent graphics_element parent
|
||||||
---@param id integer RTU session ID
|
---@param id integer RTU session ID
|
||||||
local function init(parent, id)
|
local function init(parent, id)
|
||||||
-- root div
|
-- root div
|
||||||
local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true}
|
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 .. "_"
|
local ps_prefix = "rtu_" .. id .. "_"
|
||||||
|
|
||||||
TextBox{parent=entry,x=1,y=1,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=cpair(colors.black,colors.lightGray),nav_active=cpair(colors.gray,colors.black)}
|
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=cpair(colors.black,colors.lightGray)}
|
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)
|
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}
|
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)
|
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}
|
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)
|
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}
|
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)}
|
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=cpair(colors.lightGray,colors.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", rtu_rtt.update)
|
||||||
rtu_rtt.register(databus.ps, ps_prefix .. "rtt_color", rtu_rtt.recolor)
|
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 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
|
-- create new front panel view
|
||||||
---@param panel graphics_element main displaybox
|
---@param panel graphics_element main displaybox
|
||||||
local function init(panel)
|
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 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 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)
|
on.update(true)
|
||||||
system.line_break()
|
system.line_break()
|
||||||
|
|
||||||
heartbeat.register(databus.ps, "heartbeat", heartbeat.update)
|
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()
|
system.line_break()
|
||||||
|
|
||||||
modem.register(databus.ps, "has_modem", modem.update)
|
modem.register(databus.ps, "has_modem", modem.update)
|
||||||
|
|
||||||
---@diagnostic disable-next-line: undefined-field
|
---@diagnostic disable-next-line: undefined-field
|
||||||
local comp_id = util.sprintf("(%d)", os.getComputerID())
|
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
|
-- 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 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}
|
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
|
for i = 1, config.NUM_REACTORS do
|
||||||
local ps_prefix = "plc_" .. i .. "_"
|
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=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=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=black_lg}
|
||||||
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=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)
|
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)
|
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}
|
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)
|
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}
|
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)}
|
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=cpair(colors.lightGray,colors.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", plc_rtt.update)
|
||||||
plc_rtt.register(databus.ps, ps_prefix .. "rtt_color", plc_rtt.recolor)
|
plc_rtt.register(databus.ps, ps_prefix .. "rtt_color", plc_rtt.recolor)
|
||||||
|
|
||||||
@ -116,22 +124,22 @@ local function init(panel)
|
|||||||
-- coordinator page
|
-- coordinator page
|
||||||
|
|
||||||
local crd_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
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)
|
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)}
|
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=cpair(colors.gray,colors.white)}
|
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)
|
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}
|
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)
|
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}
|
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)}
|
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=cpair(colors.lightGray,colors.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", crd_rtt.update)
|
||||||
crd_rtt.register(databus.ps, "crd_rtt_color", crd_rtt.recolor)
|
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) },
|
{ 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
|
-- link RTU/PDG list management to PGI
|
||||||
pgi.link_elements(rtu_list, rtu_entry, pdg_list, pdg_entry)
|
pgi.link_elements(rtu_list, rtu_entry, pdg_list, pdg_entry)
|
||||||
|
@ -39,4 +39,16 @@ style.colors = {
|
|||||||
{ c = colors.brown, hex = 0x672223 } -- RED OFF
|
{ 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
|
return style
|
||||||
|
@ -10,8 +10,8 @@ local svqtypes = require("supervisor.session.svqtypes")
|
|||||||
local coordinator = {}
|
local coordinator = {}
|
||||||
|
|
||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
local MGMT_TYPE = comms.MGMT_TYPE
|
||||||
local SCADA_CRDN_TYPE = comms.SCADA_CRDN_TYPE
|
local CRDN_TYPE = comms.CRDN_TYPE
|
||||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
local UNIT_COMMAND = comms.UNIT_COMMAND
|
||||||
local FAC_COMMAND = comms.FAC_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
|
end
|
||||||
|
|
||||||
-- send a CRDN packet
|
-- send a CRDN packet
|
||||||
---@param msg_type SCADA_CRDN_TYPE
|
---@param msg_type CRDN_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send(msg_type, msg)
|
local function _send(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
@ -108,7 +108,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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()
|
unit_builds[unit.get_id()] = unit.get_build()
|
||||||
end
|
end
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPE.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
_send(CRDN_TYPE.INITIAL_BUILDS, { facility.get_build(), unit_builds })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send facility builds
|
-- send facility builds
|
||||||
local function _send_fac_builds()
|
local function _send_fac_builds()
|
||||||
_send(SCADA_CRDN_TYPE.FAC_BUILDS, { facility.get_build() })
|
_send(CRDN_TYPE.FAC_BUILDS, { facility.get_build() })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send unit builds
|
-- 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()
|
builds[unit.get_id()] = unit.get_build()
|
||||||
end
|
end
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send facility status
|
-- send facility status
|
||||||
@ -158,7 +158,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
facility.get_alarm_tones()
|
facility.get_alarm_tones()
|
||||||
}
|
}
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPE.FAC_STATUS, status)
|
_send(CRDN_TYPE.FAC_STATUS, status)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- send unit statuses
|
-- send unit statuses
|
||||||
@ -178,7 +178,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPE.UNIT_STATUSES, status)
|
_send(CRDN_TYPE.UNIT_STATUSES, status)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- handle a packet
|
-- handle a packet
|
||||||
@ -200,7 +200,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
-- process packet
|
-- process packet
|
||||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast pkt mgmt_frame
|
---@cast pkt mgmt_frame
|
||||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
@ -219,7 +219,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_close()
|
||||||
else
|
else
|
||||||
@ -227,22 +227,22 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
end
|
end
|
||||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then
|
||||||
---@cast pkt crdn_frame
|
---@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
|
-- acknowledgement to coordinator receiving builds
|
||||||
self.acks.builds = true
|
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
|
-- acknowledgement to coordinator receiving builds
|
||||||
self.acks.fac_builds = true
|
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
|
if pkt.length >= 1 then
|
||||||
local cmd = pkt.data[1]
|
local cmd = pkt.data[1]
|
||||||
|
|
||||||
if cmd == FAC_COMMAND.SCRAM_ALL then
|
if cmd == FAC_COMMAND.SCRAM_ALL then
|
||||||
facility.scram_all()
|
facility.scram_all()
|
||||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||||
elseif cmd == FAC_COMMAND.STOP then
|
elseif cmd == FAC_COMMAND.STOP then
|
||||||
facility.auto_stop()
|
facility.auto_stop()
|
||||||
_send(SCADA_CRDN_TYPE.FAC_CMD, { cmd, true })
|
_send(CRDN_TYPE.FAC_CMD, { cmd, true })
|
||||||
elseif cmd == FAC_COMMAND.START then
|
elseif cmd == FAC_COMMAND.START then
|
||||||
if pkt.length == 6 then
|
if pkt.length == 6 then
|
||||||
---@type coord_auto_config
|
---@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]
|
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
|
else
|
||||||
log.debug(log_header .. "CRDN auto start (with configuration) packet length mismatch")
|
log.debug(log_header .. "CRDN auto start (with configuration) packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then
|
||||||
facility.ack_all()
|
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
|
elseif cmd == FAC_COMMAND.SET_WASTE_MODE then
|
||||||
if pkt.length == 2 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
|
else
|
||||||
log.debug(log_header .. "CRDN set waste mode packet length mismatch")
|
log.debug(log_header .. "CRDN set waste mode packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
elseif cmd == FAC_COMMAND.SET_PU_FB then
|
||||||
if pkt.length == 2 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
|
else
|
||||||
log.debug(log_header .. "CRDN set pu fallback packet length mismatch")
|
log.debug(log_header .. "CRDN set pu fallback packet length mismatch")
|
||||||
end
|
end
|
||||||
@ -279,10 +279,10 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "CRDN facility command packet length mismatch")
|
log.debug(log_header .. "CRDN facility command packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_CRDN_TYPE.UNIT_BUILDS then
|
elseif pkt.type == CRDN_TYPE.UNIT_BUILDS then
|
||||||
-- acknowledgement to coordinator receiving builds
|
-- acknowledgement to coordinator receiving builds
|
||||||
self.acks.unit_builds = true
|
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
|
if pkt.length >= 2 then
|
||||||
-- get command and unit id
|
-- get command and unit id
|
||||||
local cmd = pkt.data[1]
|
local cmd = pkt.data[1]
|
||||||
@ -315,7 +315,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
end
|
end
|
||||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||||
unit.ack_all()
|
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
|
elseif cmd == UNIT_COMMAND.ACK_ALARM then
|
||||||
if pkt.length == 3 then
|
if pkt.length == 3 then
|
||||||
unit.ack_alarm(pkt.data[3])
|
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
|
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
|
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])
|
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
|
else
|
||||||
log.debug(log_header .. "CRDN unit command set group missing group id")
|
log.debug(log_header .. "CRDN unit command set group missing group id")
|
||||||
end
|
end
|
||||||
@ -374,7 +374,7 @@ function coordinator.new_session(id, s_addr, in_queue, out_queue, timeout, facil
|
|||||||
-- close the connection
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||||
println("connection to coordinator " .. id .. " closed by server")
|
println("connection to coordinator " .. id .. " closed by server")
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
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
|
if cmd.key == CRD_S_DATA.CMD_ACK then
|
||||||
local ack = cmd.val ---@type coord_ack
|
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
|
elseif cmd.key == CRD_S_DATA.RESEND_PLC_BUILD then
|
||||||
-- re-send PLC build
|
-- 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
|
-- 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
|
local unit = self.units[unit_id] ---@type reactor_unit
|
||||||
builds[unit_id] = unit.get_build(-1)
|
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
|
elseif cmd.key == CRD_S_DATA.RESEND_RTU_BUILD then
|
||||||
local unit_id = cmd.val.unit
|
local unit_id = cmd.val.unit
|
||||||
if unit_id > 0 then
|
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
|
local unit = self.units[unit_id] ---@type reactor_unit
|
||||||
builds[unit_id] = unit.get_build(cmd.val.type)
|
builds[unit_id] = unit.get_build(cmd.val.type)
|
||||||
|
|
||||||
_send(SCADA_CRDN_TYPE.UNIT_BUILDS, { builds })
|
_send(CRDN_TYPE.UNIT_BUILDS, { builds })
|
||||||
else
|
else
|
||||||
-- re-send facility RTU builds
|
-- 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
|
-- 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.retry_times.f_builds_packet = util.time() + PARTIAL_RETRY_PERIOD
|
||||||
self.acks.fac_builds = false
|
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
|
end
|
||||||
else
|
else
|
||||||
log.error(log_header .. "unsupported data command received in in_queue (this is a bug)", true)
|
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
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
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
|
periodics.keep_alive = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ local plc = {}
|
|||||||
|
|
||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local RPLC_TYPE = comms.RPLC_TYPE
|
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 PLC_AUTO_ACK = comms.PLC_AUTO_ACK
|
||||||
local UNIT_COMMAND = comms.UNIT_COMMAND
|
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
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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
|
end
|
||||||
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast pkt mgmt_frame
|
---@cast pkt mgmt_frame
|
||||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
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
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_close()
|
||||||
else
|
else
|
||||||
@ -595,7 +595,7 @@ function plc.new_session(id, s_addr, reactor_id, in_queue, out_queue, timeout, f
|
|||||||
-- close the connection
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||||
println("connection to reactor " .. reactor_id .. " PLC closed by server")
|
println("connection to reactor " .. reactor_id .. " PLC closed by server")
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
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
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
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
|
periodics.keep_alive = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ local databus = require("supervisor.databus")
|
|||||||
local pocket = {}
|
local pocket = {}
|
||||||
|
|
||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
local MGMT_TYPE = comms.MGMT_TYPE
|
||||||
|
|
||||||
-- retry time constants in ms
|
-- retry time constants in ms
|
||||||
-- local INITIAL_WAIT = 1500
|
-- local INITIAL_WAIT = 1500
|
||||||
@ -76,7 +76,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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
|
-- process packet
|
||||||
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
if pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast pkt mgmt_frame
|
---@cast pkt mgmt_frame
|
||||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
@ -127,13 +127,13 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_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
|
-- get the state of alarm tones
|
||||||
_send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_GET, facility.get_alarm_tones())
|
_send_mgmt(MGMT_TYPE.DIAG_TONE_GET, facility.get_alarm_tones())
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_TONE_SET then
|
elseif pkt.type == MGMT_TYPE.DIAG_TONE_SET then
|
||||||
local valid = false
|
local valid = false
|
||||||
|
|
||||||
-- attempt to set a tone state
|
-- 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
|
-- 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])
|
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
|
else
|
||||||
log.debug(log_header .. "SCADA diag tone set packet data type mismatch")
|
log.debug(log_header .. "SCADA diag tone set packet data type mismatch")
|
||||||
end
|
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")
|
log.debug(log_header .. "DIAG_TONE_SET is blocked without HMAC for security")
|
||||||
end
|
end
|
||||||
|
|
||||||
if not valid then _send_mgmt(SCADA_MGMT_TYPE.DIAG_TONE_SET, { false }) end
|
if not valid then _send_mgmt(MGMT_TYPE.DIAG_TONE_SET, { false }) end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.DIAG_ALARM_SET then
|
elseif pkt.type == MGMT_TYPE.DIAG_ALARM_SET then
|
||||||
local valid = false
|
local valid = false
|
||||||
|
|
||||||
-- attempt to set an alarm state
|
-- 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
|
-- 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])
|
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
|
else
|
||||||
log.debug(log_header .. "SCADA diag alarm set packet data type mismatch")
|
log.debug(log_header .. "SCADA diag alarm set packet data type mismatch")
|
||||||
end
|
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")
|
log.debug(log_header .. "DIAG_ALARM_SET is blocked without HMAC for security")
|
||||||
end
|
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
|
else
|
||||||
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type)
|
||||||
end
|
end
|
||||||
@ -204,7 +204,7 @@ function pocket.new_session(id, s_addr, in_queue, out_queue, timeout, facility,
|
|||||||
-- close the connection
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||||
println("connection to pocket diag session " .. id .. " closed by server")
|
println("connection to pocket diag session " .. id .. " closed by server")
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
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
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
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
|
periodics.keep_alive = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ local svrs_turbinev = require("supervisor.session.rtu.turbinev")
|
|||||||
local rtu = {}
|
local rtu = {}
|
||||||
|
|
||||||
local PROTOCOL = comms.PROTOCOL
|
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 RTU_UNIT_TYPE = types.RTU_UNIT_TYPE
|
||||||
|
|
||||||
local PERIODICS = {
|
local PERIODICS = {
|
||||||
@ -223,7 +223,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- send a SCADA management packet
|
-- send a SCADA management packet
|
||||||
---@param msg_type SCADA_MGMT_TYPE
|
---@param msg_type MGMT_TYPE
|
||||||
---@param msg table
|
---@param msg table
|
||||||
local function _send_mgmt(msg_type, msg)
|
local function _send_mgmt(msg_type, msg)
|
||||||
local s_pkt = comms.scada_packet()
|
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
|
elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then
|
||||||
---@cast pkt mgmt_frame
|
---@cast pkt mgmt_frame
|
||||||
-- handle management packet
|
-- handle management packet
|
||||||
if pkt.type == SCADA_MGMT_TYPE.KEEP_ALIVE then
|
if pkt.type == MGMT_TYPE.KEEP_ALIVE then
|
||||||
-- keep alive reply
|
-- keep alive reply
|
||||||
if pkt.length == 2 then
|
if pkt.length == 2 then
|
||||||
local srv_start = pkt.data[1]
|
local srv_start = pkt.data[1]
|
||||||
@ -281,17 +281,17 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
|
|||||||
else
|
else
|
||||||
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
log.debug(log_header .. "SCADA keep alive packet length mismatch")
|
||||||
end
|
end
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.CLOSE then
|
elseif pkt.type == MGMT_TYPE.CLOSE then
|
||||||
-- close the session
|
-- close the session
|
||||||
_close()
|
_close()
|
||||||
elseif pkt.type == SCADA_MGMT_TYPE.RTU_ADVERT then
|
elseif pkt.type == MGMT_TYPE.RTU_ADVERT then
|
||||||
-- RTU unit advertisement
|
-- RTU unit advertisement
|
||||||
log.debug(log_header .. "received updated advertisement")
|
log.debug(log_header .. "received updated advertisement")
|
||||||
self.advert = pkt.data
|
self.advert = pkt.data
|
||||||
|
|
||||||
-- handle advertisement; this will re-create all unit sub-sessions
|
-- handle advertisement; this will re-create all unit sub-sessions
|
||||||
_handle_advertisement()
|
_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
|
if pkt.length == 1 then
|
||||||
local unit_id = pkt.data[1]
|
local unit_id = pkt.data[1]
|
||||||
if self.units[unit_id] ~= nil then
|
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
|
-- close the connection
|
||||||
function public.close()
|
function public.close()
|
||||||
_close()
|
_close()
|
||||||
_send_mgmt(SCADA_MGMT_TYPE.CLOSE, {})
|
_send_mgmt(MGMT_TYPE.CLOSE, {})
|
||||||
println(log_header .. "connection to RTU closed by server")
|
println(log_header .. "connection to RTU closed by server")
|
||||||
log.info(log_header .. "session closed by server")
|
log.info(log_header .. "session closed by server")
|
||||||
end
|
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
|
periodics.keep_alive = periodics.keep_alive + elapsed
|
||||||
if periodics.keep_alive >= PERIODICS.KEEP_ALIVE then
|
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
|
periodics.keep_alive = 0
|
||||||
end
|
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
|
periodics.alarm_tones = periodics.alarm_tones + elapsed
|
||||||
if periodics.alarm_tones >= PERIODICS.ALARM_TONES then
|
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
|
periodics.alarm_tones = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ local supervisor = {}
|
|||||||
local PROTOCOL = comms.PROTOCOL
|
local PROTOCOL = comms.PROTOCOL
|
||||||
local DEVICE_TYPE = comms.DEVICE_TYPE
|
local DEVICE_TYPE = comms.DEVICE_TYPE
|
||||||
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
local ESTABLISH_ACK = comms.ESTABLISH_ACK
|
||||||
local SCADA_MGMT_TYPE = comms.SCADA_MGMT_TYPE
|
local MGMT_TYPE = comms.MGMT_TYPE
|
||||||
|
|
||||||
-- supervisory controller communications
|
-- supervisory controller communications
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
@ -58,7 +58,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
|||||||
local s_pkt = comms.scada_packet()
|
local s_pkt = comms.scada_packet()
|
||||||
local m_pkt = comms.mgmt_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())
|
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)
|
nic.transmit(packet.remote_channel(), svr_channel, s_pkt)
|
||||||
@ -147,7 +147,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
|||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
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
|
-- establish a new session
|
||||||
local last_ack = self.last_est_acks[src_addr]
|
local last_ack = self.last_est_acks[src_addr]
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
|||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
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
|
-- establish a new session
|
||||||
local last_ack = self.last_est_acks[src_addr]
|
local last_ack = self.last_est_acks[src_addr]
|
||||||
|
|
||||||
@ -275,7 +275,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
|||||||
if session ~= nil then
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
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
|
-- establish a new session
|
||||||
local last_ack = self.last_est_acks[src_addr]
|
local last_ack = self.last_est_acks[src_addr]
|
||||||
|
|
||||||
@ -291,7 +291,7 @@ function supervisor.comms(_version, nic, fp_ok)
|
|||||||
end
|
end
|
||||||
|
|
||||||
_send_establish(packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
|
_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
|
-- this is an attempt to establish a new coordinator session
|
||||||
local s_id = svsessions.establish_crd_session(src_addr, firmware_v)
|
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
|
if session ~= nil then
|
||||||
-- pass the packet onto the session handler
|
-- pass the packet onto the session handler
|
||||||
session.in_queue.push_packet(packet)
|
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
|
-- establish a new session
|
||||||
local last_ack = self.last_est_acks[src_addr]
|
local last_ack = self.last_est_acks[src_addr]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user