mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#118 coordinator code cleanup
This commit is contained in:
parent
79494f0587
commit
4340518ecf
@ -4,13 +4,17 @@ local apisessions = {}
|
||||
function apisessions.handle_packet(packet)
|
||||
end
|
||||
|
||||
function apisessions.check_all_watchdogs()
|
||||
end
|
||||
|
||||
function apisessions.close_all()
|
||||
-- attempt to identify which session's watchdog timer fired
|
||||
---@param timer_event number
|
||||
function apisessions.check_all_watchdogs(timer_event)
|
||||
end
|
||||
|
||||
-- delete all closed sessions
|
||||
function apisessions.free_all_closed()
|
||||
end
|
||||
|
||||
-- close all open connections
|
||||
function apisessions.close_all()
|
||||
end
|
||||
|
||||
return apisessions
|
||||
|
@ -25,6 +25,7 @@ local FAC_COMMAND = comms.FAC_COMMAND
|
||||
local coordinator = {}
|
||||
|
||||
-- request the user to select a monitor
|
||||
---@nodiscard
|
||||
---@param names table available monitors
|
||||
---@return boolean|string|nil
|
||||
local function ask_monitor(names)
|
||||
@ -64,9 +65,11 @@ function coordinator.configure_monitors(num_units)
|
||||
end
|
||||
|
||||
-- we need a certain number of monitors (1 per unit + 1 primary display)
|
||||
if #names < num_units + 1 then
|
||||
println("not enough monitors connected (need " .. num_units + 1 .. ")")
|
||||
log.warning("insufficient monitors present (need " .. num_units + 1 .. ")")
|
||||
local num_displays_needed = num_units + 1
|
||||
if #names < num_displays_needed then
|
||||
local message = "not enough monitors connected (need " .. num_displays_needed .. ")"
|
||||
println(message)
|
||||
log.warning(message)
|
||||
return false
|
||||
end
|
||||
|
||||
@ -125,7 +128,6 @@ function coordinator.configure_monitors(num_units)
|
||||
else
|
||||
-- make sure all displays are connected
|
||||
for i = 1, num_units do
|
||||
---@diagnostic disable-next-line: need-check-nil
|
||||
local display = unit_displays[i]
|
||||
|
||||
if not util.table_contains(names, display) then
|
||||
@ -183,14 +185,19 @@ function coordinator.log_sys(message) log_dmesg(message, "SYSTEM") end
|
||||
function coordinator.log_boot(message) log_dmesg(message, "BOOT") end
|
||||
function coordinator.log_comms(message) log_dmesg(message, "COMMS") end
|
||||
|
||||
-- log a message for communications connecting, providing access to progress indication control functions
|
||||
---@nodiscard
|
||||
---@param message string
|
||||
---@return function update, function done
|
||||
function coordinator.log_comms_connecting(message)
|
||||
---@diagnostic disable-next-line: return-type-mismatch
|
||||
return log_dmesg(message, "COMMS", true)
|
||||
local update, done = log_dmesg(message, "COMMS", true)
|
||||
---@cast update function
|
||||
---@cast done function
|
||||
return update, done
|
||||
end
|
||||
|
||||
-- coordinator communications
|
||||
---@nodiscard
|
||||
---@param version string coordinator version
|
||||
---@param modem table modem device
|
||||
---@param sv_port integer port of configured supervisor
|
||||
@ -203,23 +210,19 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
sv_linked = false,
|
||||
sv_seq_num = 0,
|
||||
sv_r_seq_num = nil,
|
||||
modem = modem,
|
||||
connected = false,
|
||||
last_est_ack = ESTABLISH_ACK.ALLOW
|
||||
}
|
||||
|
||||
---@class coord_comms
|
||||
local public = {}
|
||||
|
||||
comms.set_trusted_range(range)
|
||||
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- configure modem channels
|
||||
local function _conf_channels()
|
||||
self.modem.closeAll()
|
||||
self.modem.open(sv_listen)
|
||||
self.modem.open(api_listen)
|
||||
modem.closeAll()
|
||||
modem.open(sv_listen)
|
||||
modem.open(api_listen)
|
||||
end
|
||||
|
||||
_conf_channels()
|
||||
@ -242,7 +245,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
pkt.make(msg_type, msg)
|
||||
s_pkt.make(self.sv_seq_num, protocol, pkt.raw_sendable())
|
||||
|
||||
self.modem.transmit(sv_port, sv_listen, s_pkt.raw_sendable())
|
||||
modem.transmit(sv_port, sv_listen, s_pkt.raw_sendable())
|
||||
self.sv_seq_num = self.sv_seq_num + 1
|
||||
end
|
||||
|
||||
@ -259,11 +262,13 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
---@class coord_comms
|
||||
local public = {}
|
||||
|
||||
-- reconnect a newly connected modem
|
||||
---@param modem table
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
function public.reconnect_modem(modem)
|
||||
self.modem = modem
|
||||
---@param new_modem table
|
||||
function public.reconnect_modem(new_modem)
|
||||
modem = new_modem
|
||||
_conf_channels()
|
||||
end
|
||||
|
||||
@ -275,6 +280,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
end
|
||||
|
||||
-- attempt to connect to the subervisor
|
||||
---@nodiscard
|
||||
---@param timeout_s number timeout in seconds
|
||||
---@param tick_dmesg_waiting function callback to tick dmesg waiting
|
||||
---@param task_done function callback to show done on dmesg
|
||||
@ -400,7 +406,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
|
||||
if l_port == api_listen then
|
||||
if protocol == PROTOCOL.COORD_API then
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
---@cast packet capi_frame
|
||||
apisessions.handle_packet(packet)
|
||||
else
|
||||
log.debug("illegal packet type " .. protocol .. " on api listening channel", true)
|
||||
@ -421,6 +427,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
|
||||
-- handle packet
|
||||
if protocol == PROTOCOL.SCADA_CRDN then
|
||||
---@cast packet crdn_frame
|
||||
if self.sv_linked then
|
||||
if packet.type == SCADA_CRDN_TYPE.INITIAL_BUILDS then
|
||||
if packet.length == 2 then
|
||||
@ -432,7 +439,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.INITIAL_BUILDS, {})
|
||||
else
|
||||
log.error("received invalid INITIAL_BUILDS packet")
|
||||
log.debug("received invalid INITIAL_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("INITIAL_BUILDS packet length mismatch")
|
||||
@ -444,7 +451,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.FAC_BUILDS, {})
|
||||
else
|
||||
log.error("received invalid FAC_BUILDS packet")
|
||||
log.debug("received invalid FAC_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("FAC_BUILDS packet length mismatch")
|
||||
@ -452,7 +459,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_STATUS then
|
||||
-- update facility status
|
||||
if not iocontrol.update_facility_status(packet.data) then
|
||||
log.error("received invalid FAC_STATUS packet")
|
||||
log.debug("received invalid FAC_STATUS packet")
|
||||
end
|
||||
elseif packet.type == SCADA_CRDN_TYPE.FAC_CMD then
|
||||
-- facility command acknowledgement
|
||||
@ -485,7 +492,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
-- acknowledge receipt of builds
|
||||
_send_sv(PROTOCOL.SCADA_CRDN, SCADA_CRDN_TYPE.UNIT_BUILDS, {})
|
||||
else
|
||||
log.error("received invalid UNIT_BUILDS packet")
|
||||
log.debug("received invalid UNIT_BUILDS packet")
|
||||
end
|
||||
else
|
||||
log.debug("UNIT_BUILDS packet length mismatch")
|
||||
@ -518,7 +525,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then
|
||||
unit.ack_alarms_ack(ack)
|
||||
elseif cmd == UNIT_COMMAND.SET_GROUP then
|
||||
---@todo how is this going to be handled?
|
||||
-- UI will be updated to display current group if changed successfully
|
||||
else
|
||||
log.debug(util.c("received unit command ack with unknown command ", cmd))
|
||||
end
|
||||
@ -535,6 +542,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
log.debug("discarding SCADA_CRDN packet before linked")
|
||||
end
|
||||
elseif protocol == PROTOCOL.SCADA_MGMT then
|
||||
---@cast packet mgmt_frame
|
||||
if packet.type == SCADA_MGMT_TYPE.ESTABLISH then
|
||||
-- connection with supervisor established
|
||||
if packet.length == 2 then
|
||||
@ -562,10 +570,10 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
|
||||
self.sv_linked = true
|
||||
else
|
||||
log.error("invalid supervisor configuration definitions received, establish failed")
|
||||
log.debug("invalid supervisor configuration definitions received, establish failed")
|
||||
end
|
||||
else
|
||||
log.error("invalid supervisor configuration table received, establish failed")
|
||||
log.debug("invalid supervisor configuration table received, establish failed")
|
||||
end
|
||||
else
|
||||
log.debug("SCADA_MGMT establish packet reply (len = 2) unsupported")
|
||||
@ -577,11 +585,11 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
|
||||
if est_ack == ESTABLISH_ACK.DENY then
|
||||
if self.last_est_ack ~= est_ack then
|
||||
log.debug("supervisor connection denied")
|
||||
log.info("supervisor connection denied")
|
||||
end
|
||||
elseif est_ack == ESTABLISH_ACK.COLLISION then
|
||||
if self.last_est_ack ~= est_ack then
|
||||
log.debug("supervisor connection denied due to collision")
|
||||
log.info("supervisor connection denied due to collision")
|
||||
end
|
||||
elseif est_ack == ESTABLISH_ACK.BAD_VERSION then
|
||||
if self.last_est_ack ~= est_ack then
|
||||
@ -619,9 +627,9 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
sv_watchdog.cancel()
|
||||
self.sv_linked = false
|
||||
println_ts("server connection closed by remote host")
|
||||
log.warning("server connection closed by remote host")
|
||||
log.info("server connection closed by remote host")
|
||||
else
|
||||
log.warning("received unknown SCADA_MGMT packet type " .. packet.type)
|
||||
log.debug("received unknown SCADA_MGMT packet type " .. packet.type)
|
||||
end
|
||||
else
|
||||
log.debug("discarding non-link SCADA_MGMT packet before linked")
|
||||
@ -636,6 +644,7 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, range
|
||||
end
|
||||
|
||||
-- check if the coordinator is still linked to the supervisor
|
||||
---@nodiscard
|
||||
function public.is_linked() return self.sv_linked end
|
||||
|
||||
return public
|
||||
|
@ -1,3 +1,7 @@
|
||||
--
|
||||
-- I/O Control for Supervisor/Coordinator Integration
|
||||
--
|
||||
|
||||
local log = require("scada-common.log")
|
||||
local psil = require("scada-common.psil")
|
||||
local types = require("scada-common.types")
|
||||
@ -16,7 +20,6 @@ local io = {}
|
||||
-- initialize the coordinator IO controller
|
||||
---@param conf facility_conf configuration
|
||||
---@param comms coord_comms comms reference
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
function iocontrol.init(conf, comms)
|
||||
---@class ioctl_facility
|
||||
io.facility = {
|
||||
@ -56,7 +59,7 @@ function iocontrol.init(conf, comms)
|
||||
env_d_data = {}
|
||||
}
|
||||
|
||||
-- create induction tables (max 1 per unit, preferably 1 total)
|
||||
-- create induction tables (currently only 1 is supported)
|
||||
for _ = 1, conf.num_units do
|
||||
local data = {} ---@type imatrix_session_db
|
||||
table.insert(io.facility.induction_ps_tbl, psil.create())
|
||||
@ -170,6 +173,8 @@ end
|
||||
---@param build table
|
||||
---@return boolean valid
|
||||
function iocontrol.record_facility_builds(build)
|
||||
local valid = true
|
||||
|
||||
if type(build) == "table" then
|
||||
local fac = io.facility
|
||||
|
||||
@ -187,35 +192,37 @@ function iocontrol.record_facility_builds(build)
|
||||
end
|
||||
else
|
||||
log.debug(util.c("iocontrol.record_facility_builds: invalid induction matrix id ", id))
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
log.error("facility builds not a table")
|
||||
return false
|
||||
log.debug("facility builds not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
return true
|
||||
return valid
|
||||
end
|
||||
|
||||
-- populate unit structure builds
|
||||
---@param builds table
|
||||
---@return boolean valid
|
||||
function iocontrol.record_unit_builds(builds)
|
||||
local valid = true
|
||||
|
||||
-- note: if not all units and RTUs are connected, some will be nil
|
||||
for id, build in pairs(builds) do
|
||||
local unit = io.units[id] ---@type ioctl_unit
|
||||
|
||||
local log_header = util.c("iocontrol.record_unit_builds[UNIT ", id, "]: ")
|
||||
|
||||
if type(build) ~= "table" then
|
||||
log.error(util.c("corrupted unit builds provided, unit ", id, " not a table"))
|
||||
return false
|
||||
log.debug(log_header .. "build not a table")
|
||||
valid = false
|
||||
elseif type(unit) ~= "table" then
|
||||
log.error(util.c("corrupted unit builds provided, invalid unit ", id))
|
||||
return false
|
||||
end
|
||||
|
||||
local log_header = util.c("iocontrol.record_unit_builds[unit ", id, "]: ")
|
||||
|
||||
log.debug(log_header .. "invalid unit id")
|
||||
valid = false
|
||||
else
|
||||
-- reactor build
|
||||
if type(build.reactor) == "table" then
|
||||
unit.reactor_data.mek_struct = build.reactor ---@type mek_struct
|
||||
@ -243,6 +250,7 @@ function iocontrol.record_unit_builds(builds)
|
||||
end
|
||||
else
|
||||
log.debug(util.c(log_header, "invalid boiler id ", b_id))
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -261,22 +269,26 @@ function iocontrol.record_unit_builds(builds)
|
||||
end
|
||||
else
|
||||
log.debug(util.c(log_header, "invalid turbine id ", t_id))
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
return valid
|
||||
end
|
||||
|
||||
-- update facility status
|
||||
---@param status table
|
||||
---@return boolean valid
|
||||
function iocontrol.update_facility_status(status)
|
||||
local valid = true
|
||||
local log_header = util.c("iocontrol.update_facility_status: ")
|
||||
|
||||
if type(status) ~= "table" then
|
||||
log.debug(log_header .. "status not a table")
|
||||
return false
|
||||
log.debug(util.c(log_header, "status not a table"))
|
||||
valid = false
|
||||
else
|
||||
local fac = io.facility
|
||||
|
||||
@ -284,10 +296,17 @@ function iocontrol.update_facility_status(status)
|
||||
|
||||
local ctl_status = status[1]
|
||||
|
||||
if type(ctl_status) == "table" and (#ctl_status == 14) then
|
||||
if type(ctl_status) == "table" and #ctl_status == 14 then
|
||||
fac.all_sys_ok = ctl_status[1]
|
||||
fac.auto_ready = ctl_status[2]
|
||||
fac.auto_active = ctl_status[3] > 0
|
||||
|
||||
if type(ctl_status[3]) == "number" then
|
||||
fac.auto_active = ctl_status[3] > 1
|
||||
else
|
||||
fac.auto_active = false
|
||||
valid = false
|
||||
end
|
||||
|
||||
fac.auto_ramping = ctl_status[4]
|
||||
fac.auto_saturated = ctl_status[5]
|
||||
|
||||
@ -327,6 +346,7 @@ function iocontrol.update_facility_status(status)
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "control status not a table or length mismatch")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- RTU statuses
|
||||
@ -334,10 +354,10 @@ function iocontrol.update_facility_status(status)
|
||||
local rtu_statuses = status[2]
|
||||
|
||||
fac.rtu_count = 0
|
||||
|
||||
if type(rtu_statuses) == "table" then
|
||||
-- connected RTU count
|
||||
fac.rtu_count = rtu_statuses.count
|
||||
fac.ps.publish("rtu_count", fac.rtu_count)
|
||||
|
||||
-- power statistics
|
||||
if type(rtu_statuses.power) == "table" then
|
||||
@ -346,6 +366,7 @@ function iocontrol.update_facility_status(status)
|
||||
fac.induction_ps_tbl[1].publish("avg_outflow", rtu_statuses.power[3])
|
||||
else
|
||||
log.debug(log_header .. "power statistics list not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- induction matricies statuses
|
||||
@ -396,6 +417,7 @@ function iocontrol.update_facility_status(status)
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "induction matrix list not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- environment detector status
|
||||
@ -413,42 +435,46 @@ function iocontrol.update_facility_status(status)
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "radiation monitor list not a table")
|
||||
return false
|
||||
valid = false
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "rtu statuses not a table")
|
||||
end
|
||||
valid = false
|
||||
end
|
||||
|
||||
return true
|
||||
fac.ps.publish("rtu_count", fac.rtu_count)
|
||||
end
|
||||
|
||||
return valid
|
||||
end
|
||||
|
||||
-- update unit statuses
|
||||
---@param statuses table
|
||||
---@return boolean valid
|
||||
function iocontrol.update_unit_statuses(statuses)
|
||||
local valid = true
|
||||
|
||||
if type(statuses) ~= "table" then
|
||||
log.debug("iocontrol.update_unit_statuses: unit statuses not a table")
|
||||
return false
|
||||
valid = false
|
||||
elseif #statuses ~= #io.units then
|
||||
log.debug("iocontrol.update_unit_statuses: number of provided unit statuses does not match expected number of units")
|
||||
return false
|
||||
valid = false
|
||||
else
|
||||
local burn_rate_sum = 0.0
|
||||
|
||||
-- get all unit statuses
|
||||
for i = 1, #statuses do
|
||||
local log_header = util.c("iocontrol.update_unit_statuses[unit ", i, "]: ")
|
||||
|
||||
local unit = io.units[i] ---@type ioctl_unit
|
||||
local status = statuses[i]
|
||||
|
||||
if type(status) ~= "table" or #status ~= 5 then
|
||||
log.debug(log_header .. "invalid status entry in unit statuses (not a table or invalid length)")
|
||||
return false
|
||||
end
|
||||
|
||||
valid = false
|
||||
else
|
||||
-- reactor PLC status
|
||||
|
||||
local reactor_status = status[1]
|
||||
|
||||
if type(reactor_status) ~= "table" then
|
||||
@ -517,10 +543,10 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "reactor status length mismatch")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- RTU statuses
|
||||
|
||||
local rtu_statuses = status[2]
|
||||
|
||||
if type(rtu_statuses) == "table" then
|
||||
@ -566,10 +592,12 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
else
|
||||
log.debug(util.c(log_header, "invalid boiler id ", id))
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "boiler list not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- turbine statuses
|
||||
@ -616,11 +644,12 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
else
|
||||
log.debug(util.c(log_header, "invalid turbine id ", id))
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "turbine list not a table")
|
||||
return false
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- environment detector status
|
||||
@ -636,19 +665,20 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "radiation monitor list not a table")
|
||||
return false
|
||||
valid = false
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "rtu list not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- annunciator
|
||||
|
||||
unit.annunciator = status[3]
|
||||
|
||||
if type(unit.annunciator) ~= "table" then
|
||||
unit.annunciator = {}
|
||||
log.debug(log_header .. "annunciator state not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
for key, val in pairs(unit.annunciator) do
|
||||
@ -675,7 +705,8 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
elseif type(val) == "table" then
|
||||
-- we missed one of the tables?
|
||||
log.error(log_header .. "unrecognized table found in annunciator list, this is a bug", true)
|
||||
log.debug(log_header .. "unrecognized table found in annunciator list, this is a bug")
|
||||
valid = false
|
||||
else
|
||||
-- non-table fields
|
||||
unit.unit_ps.publish(key, val)
|
||||
@ -683,7 +714,6 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
|
||||
-- alarms
|
||||
|
||||
local alarm_states = status[4]
|
||||
|
||||
if type(alarm_states) == "table" then
|
||||
@ -702,10 +732,10 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "alarm states not a table")
|
||||
valid = false
|
||||
end
|
||||
|
||||
-- unit state fields
|
||||
|
||||
local unit_state = status[5]
|
||||
|
||||
if type(unit_state) == "table" then
|
||||
@ -717,9 +747,12 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
unit.unit_ps.publish("U_AutoDegraded", unit_state[5])
|
||||
else
|
||||
log.debug(log_header .. "unit state length mismatch")
|
||||
valid = false
|
||||
end
|
||||
else
|
||||
log.debug(log_header .. "unit state not a table")
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -729,7 +762,7 @@ function iocontrol.update_unit_statuses(statuses)
|
||||
sounder.eval(io.units)
|
||||
end
|
||||
|
||||
return true
|
||||
return valid
|
||||
end
|
||||
|
||||
-- get the IO controller database
|
||||
|
@ -1,3 +1,6 @@
|
||||
--
|
||||
-- Process Control Management
|
||||
--
|
||||
|
||||
local comms = require("scada-common.comms")
|
||||
local log = require("scada-common.log")
|
||||
@ -30,11 +33,11 @@ local self = {
|
||||
--------------------------
|
||||
|
||||
-- initialize the process controller
|
||||
---@param iocontrol ioctl
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
function process.init(iocontrol, comms)
|
||||
---@param iocontrol ioctl iocontrl system
|
||||
---@param coord_comms coord_comms coordinator communications
|
||||
function process.init(iocontrol, coord_comms)
|
||||
self.io = iocontrol
|
||||
self.comms = comms
|
||||
self.comms = coord_comms
|
||||
|
||||
for i = 1, self.io.facility.num_units do
|
||||
self.config.limits[i] = 0.1
|
||||
@ -91,13 +94,13 @@ end
|
||||
-- facility SCRAM command
|
||||
function process.fac_scram()
|
||||
self.comms.send_fac_command(FAC_COMMAND.SCRAM_ALL)
|
||||
log.debug("FAC: SCRAM ALL")
|
||||
log.debug("PROCESS: FAC SCRAM ALL")
|
||||
end
|
||||
|
||||
-- facility alarm acknowledge command
|
||||
function process.fac_ack_alarms()
|
||||
self.comms.send_fac_command(FAC_COMMAND.ACK_ALL_ALARMS)
|
||||
log.debug("FAC: ACK ALL ALARMS")
|
||||
log.debug("PROCESS: FAC ACK ALL ALARMS")
|
||||
end
|
||||
|
||||
-- start reactor
|
||||
@ -105,7 +108,7 @@ end
|
||||
function process.start(id)
|
||||
self.io.units[id].control_state = true
|
||||
self.comms.send_unit_command(UNIT_COMMAND.START, id)
|
||||
log.debug(util.c("UNIT[", id, "]: START"))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] START"))
|
||||
end
|
||||
|
||||
-- SCRAM reactor
|
||||
@ -113,14 +116,14 @@ end
|
||||
function process.scram(id)
|
||||
self.io.units[id].control_state = false
|
||||
self.comms.send_unit_command(UNIT_COMMAND.SCRAM, id)
|
||||
log.debug(util.c("UNIT[", id, "]: SCRAM"))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] SCRAM"))
|
||||
end
|
||||
|
||||
-- reset reactor protection system
|
||||
---@param id integer unit ID
|
||||
function process.reset_rps(id)
|
||||
self.comms.send_unit_command(UNIT_COMMAND.RESET_RPS, id)
|
||||
log.debug(util.c("UNIT[", id, "]: RESET RPS"))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] RESET RPS"))
|
||||
end
|
||||
|
||||
-- set burn rate
|
||||
@ -128,7 +131,7 @@ end
|
||||
---@param rate number burn rate
|
||||
function process.set_rate(id, rate)
|
||||
self.comms.send_unit_command(UNIT_COMMAND.SET_BURN, id, rate)
|
||||
log.debug(util.c("UNIT[", id, "]: SET BURN = ", rate))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] SET BURN ", rate))
|
||||
end
|
||||
|
||||
-- set waste mode
|
||||
@ -139,13 +142,11 @@ function process.set_waste(id, mode)
|
||||
self.io.units[id].unit_ps.publish("U_WasteMode", mode)
|
||||
|
||||
self.comms.send_unit_command(UNIT_COMMAND.SET_WASTE, id, mode)
|
||||
log.debug(util.c("UNIT[", id, "]: SET WASTE = ", mode))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] SET WASTE ", mode))
|
||||
|
||||
local waste_mode = settings.get("WASTE_MODES") ---@type table|nil
|
||||
|
||||
if type(waste_mode) ~= "table" then
|
||||
waste_mode = {}
|
||||
end
|
||||
if type(waste_mode) ~= "table" then waste_mode = {} end
|
||||
|
||||
waste_mode[id] = mode
|
||||
|
||||
@ -160,7 +161,7 @@ end
|
||||
---@param id integer unit ID
|
||||
function process.ack_all_alarms(id)
|
||||
self.comms.send_unit_command(UNIT_COMMAND.ACK_ALL_ALARMS, id)
|
||||
log.debug(util.c("UNIT[", id, "]: ACK ALL ALARMS"))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALL ALARMS"))
|
||||
end
|
||||
|
||||
-- acknowledge an alarm
|
||||
@ -168,7 +169,7 @@ end
|
||||
---@param alarm integer alarm ID
|
||||
function process.ack_alarm(id, alarm)
|
||||
self.comms.send_unit_command(UNIT_COMMAND.ACK_ALARM, id, alarm)
|
||||
log.debug(util.c("UNIT[", id, "]: ACK ALARM ", alarm))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] ACK ALARM ", alarm))
|
||||
end
|
||||
|
||||
-- reset an alarm
|
||||
@ -176,7 +177,7 @@ end
|
||||
---@param alarm integer alarm ID
|
||||
function process.reset_alarm(id, alarm)
|
||||
self.comms.send_unit_command(UNIT_COMMAND.RESET_ALARM, id, alarm)
|
||||
log.debug(util.c("UNIT[", id, "]: RESET ALARM ", alarm))
|
||||
log.debug(util.c("PROCESS: UNIT[", id, "] RESET ALARM ", alarm))
|
||||
end
|
||||
|
||||
-- assign a unit to a group
|
||||
@ -184,13 +185,11 @@ end
|
||||
---@param group_id integer|0 group ID or 0 for independent
|
||||
function process.set_group(unit_id, group_id)
|
||||
self.comms.send_unit_command(UNIT_COMMAND.SET_GROUP, unit_id, group_id)
|
||||
log.debug(util.c("UNIT[", unit_id, "]: SET GROUP ", group_id))
|
||||
log.debug(util.c("PROCESS: UNIT[", unit_id, "] SET GROUP ", group_id))
|
||||
|
||||
local prio_groups = settings.get("PRIORITY_GROUPS") ---@type table|nil
|
||||
|
||||
if type(prio_groups) ~= "table" then
|
||||
prio_groups = {}
|
||||
end
|
||||
if type(prio_groups) ~= "table" then prio_groups = {} end
|
||||
|
||||
prio_groups[unit_id] = group_id
|
||||
|
||||
@ -208,13 +207,13 @@ end
|
||||
-- stop automatic process control
|
||||
function process.stop_auto()
|
||||
self.comms.send_fac_command(FAC_COMMAND.STOP)
|
||||
log.debug("FAC: STOP AUTO")
|
||||
log.debug("PROCESS: STOP AUTO CTL")
|
||||
end
|
||||
|
||||
-- start automatic process control
|
||||
function process.start_auto()
|
||||
self.comms.send_auto_start(self.config)
|
||||
log.debug("FAC: START AUTO")
|
||||
log.debug("PROCESS: START AUTO CTL")
|
||||
end
|
||||
|
||||
-- save process control settings
|
||||
@ -246,8 +245,6 @@ function process.save(mode, burn_target, charge_target, gen_target, limits)
|
||||
log.warning("process.save(): failed to save coordinator settings file")
|
||||
end
|
||||
|
||||
log.debug("saved = " .. util.strval(saved))
|
||||
|
||||
self.io.facility.save_cfg_ack(saved)
|
||||
end
|
||||
|
||||
@ -273,18 +270,4 @@ function process.start_ack_handle(response)
|
||||
self.io.facility.start_ack(ack)
|
||||
end
|
||||
|
||||
--------------------------
|
||||
-- SUPERVISOR RESPONSES --
|
||||
--------------------------
|
||||
|
||||
-- acknowledgement from the supervisor to assign a unit to a group
|
||||
function process.sv_assign(unit_id, group_id)
|
||||
self.io.units[unit_id].group = group_id
|
||||
end
|
||||
|
||||
-- acknowledgement from the supervisor to assign a unit a burn rate limit
|
||||
function process.sv_limit(unit_id, limit)
|
||||
self.io.units[unit_id].limit = limit
|
||||
end
|
||||
|
||||
return process
|
||||
|
@ -1,3 +1,7 @@
|
||||
--
|
||||
-- Graphics Rendering Control
|
||||
--
|
||||
|
||||
local log = require("scada-common.log")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
@ -56,6 +60,7 @@ function renderer.set_displays(monitors)
|
||||
end
|
||||
|
||||
-- check if the renderer is configured to use a given monitor peripheral
|
||||
---@nodiscard
|
||||
---@param periph table peripheral
|
||||
---@return boolean is_used
|
||||
function renderer.is_monitor_used(periph)
|
||||
@ -87,6 +92,7 @@ function renderer.reset(recolor)
|
||||
end
|
||||
|
||||
-- check main display width
|
||||
---@nodiscard
|
||||
---@return boolean width_okay
|
||||
function renderer.validate_main_display_width()
|
||||
local w, _ = engine.monitors.primary.getSize()
|
||||
@ -94,6 +100,7 @@ function renderer.validate_main_display_width()
|
||||
end
|
||||
|
||||
-- check display sizes
|
||||
---@nodiscard
|
||||
---@return boolean valid all unit display dimensions OK
|
||||
function renderer.validate_unit_display_sizes()
|
||||
local valid = true
|
||||
@ -101,7 +108,7 @@ function renderer.validate_unit_display_sizes()
|
||||
for id, monitor in pairs(engine.monitors.unit_displays) do
|
||||
local w, h = monitor.getSize()
|
||||
if w ~= 79 or h ~= 52 then
|
||||
log.warning(util.c("unit ", id, " display resolution not 79 wide by 52 tall: ", w, ", ", h))
|
||||
log.warning(util.c("RENDERER: unit ", id, " display resolution not 79 wide by 52 tall: ", w, ", ", h))
|
||||
valid = false
|
||||
end
|
||||
end
|
||||
@ -171,6 +178,7 @@ function renderer.close_ui()
|
||||
end
|
||||
|
||||
-- is the UI ready?
|
||||
---@nodiscard
|
||||
---@return boolean ready
|
||||
function renderer.ui_ready() return engine.ui_ready end
|
||||
|
||||
|
@ -26,7 +26,8 @@ local alarm_ctl = {
|
||||
playing = false,
|
||||
num_active = 0,
|
||||
next_block = 1,
|
||||
quad_buffer = { {}, {}, {}, {} } -- split audio up into 0.5s samples so specific components can be ended quicker
|
||||
-- split audio up into 0.5s samples so specific components can be ended quicker
|
||||
quad_buffer = { {}, {}, {}, {} }
|
||||
}
|
||||
|
||||
-- sounds modeled after https://www.e2s.com/references-and-guidelines/listen-and-download-alarm-tones
|
||||
@ -52,6 +53,7 @@ local TONES = {
|
||||
}
|
||||
|
||||
-- calculate how many samples are in the given number of milliseconds
|
||||
---@nodiscard
|
||||
---@param ms integer milliseconds
|
||||
---@return integer samples
|
||||
local function ms_to_samples(ms) return math.floor(ms * 48) end
|
||||
@ -224,6 +226,7 @@ end
|
||||
--#endregion
|
||||
|
||||
-- hard audio limiter
|
||||
---@nodiscard
|
||||
---@param output number output level
|
||||
---@return number limited -128.0 to 127.0
|
||||
local function limit(output)
|
||||
@ -454,7 +457,7 @@ function sounder.test_power_scale()
|
||||
end
|
||||
end
|
||||
|
||||
log.debug("power rescale test took " .. (util.time_ms() - start) .. "ms")
|
||||
log.debug("SOUNDER: power rescale test took " .. (util.time_ms() - start) .. "ms")
|
||||
end
|
||||
|
||||
--#endregion
|
||||
|
@ -19,7 +19,7 @@ local iocontrol = require("coordinator.iocontrol")
|
||||
local renderer = require("coordinator.renderer")
|
||||
local sounder = require("coordinator.sounder")
|
||||
|
||||
local COORDINATOR_VERSION = "beta-v0.10.1"
|
||||
local COORDINATOR_VERSION = "v0.11.0"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
@ -81,7 +81,7 @@ local function main()
|
||||
-- setup monitors
|
||||
local configured, monitors = coordinator.configure_monitors(config.NUM_UNITS)
|
||||
if not configured or monitors == nil then
|
||||
println("boot> monitor setup failed")
|
||||
println("startup> monitor setup failed")
|
||||
log.fatal("monitor configuration failed")
|
||||
return
|
||||
end
|
||||
@ -91,11 +91,11 @@ local function main()
|
||||
renderer.reset(config.RECOLOR)
|
||||
|
||||
if not renderer.validate_main_display_width() then
|
||||
println("boot> main display must be 8 blocks wide")
|
||||
println("startup> main display must be 8 blocks wide")
|
||||
log.fatal("main display not wide enough")
|
||||
return
|
||||
elseif not renderer.validate_unit_display_sizes() then
|
||||
println("boot> one or more unit display dimensions incorrect; they must be 4x4 blocks")
|
||||
println("startup> one or more unit display dimensions incorrect; they must be 4x4 blocks")
|
||||
log.fatal("unit display dimensions incorrect")
|
||||
return
|
||||
end
|
||||
@ -116,7 +116,7 @@ local function main()
|
||||
local speaker = ppm.get_device("speaker")
|
||||
if speaker == nil then
|
||||
log_boot("annunciator alarm speaker not found")
|
||||
println("boot> speaker not found")
|
||||
println("startup> speaker not found")
|
||||
log.fatal("no annunciator alarm speaker found")
|
||||
return
|
||||
else
|
||||
@ -135,7 +135,7 @@ local function main()
|
||||
local modem = ppm.get_wireless_modem()
|
||||
if modem == nil then
|
||||
log_comms("wireless modem not found")
|
||||
println("boot> wireless modem not found")
|
||||
println("startup> wireless modem not found")
|
||||
log.fatal("no wireless modem on startup")
|
||||
return
|
||||
else
|
||||
@ -145,12 +145,12 @@ local function main()
|
||||
-- create connection watchdog
|
||||
local conn_watchdog = util.new_watchdog(config.COMMS_TIMEOUT)
|
||||
conn_watchdog.cancel()
|
||||
log.debug("boot> conn watchdog created")
|
||||
log.debug("startup> conn watchdog created")
|
||||
|
||||
-- start comms, open all channels
|
||||
local coord_comms = coordinator.comms(COORDINATOR_VERSION, modem, config.SCADA_SV_PORT, config.SCADA_SV_LISTEN,
|
||||
config.SCADA_API_LISTEN, config.TRUSTED_RANGE, conn_watchdog)
|
||||
log.debug("boot> comms init")
|
||||
log.debug("startup> comms init")
|
||||
log_comms("comms initialized")
|
||||
|
||||
-- base loop clock (2Hz, 10 ticks)
|
||||
@ -176,7 +176,7 @@ local function main()
|
||||
end
|
||||
|
||||
if not init_connect_sv() then
|
||||
println("boot> failed to connect to supervisor")
|
||||
println("startup> failed to connect to supervisor")
|
||||
log_sys("system shutdown")
|
||||
return
|
||||
else
|
||||
@ -199,7 +199,7 @@ local function main()
|
||||
renderer.close_ui()
|
||||
log_graphics(util.c("UI crashed: ", message))
|
||||
println_ts("UI crashed")
|
||||
log.fatal(util.c("ui crashed with error ", message))
|
||||
log.fatal(util.c("GUI crashed with error ", message))
|
||||
else
|
||||
log_graphics("first UI draw took " .. (util.time_ms() - draw_start) .. "ms")
|
||||
|
||||
@ -223,7 +223,7 @@ local function main()
|
||||
if ui_ok then
|
||||
-- start connection watchdog
|
||||
conn_watchdog.feed()
|
||||
log.debug("boot> conn watchdog started")
|
||||
log.debug("startup> conn watchdog started")
|
||||
|
||||
log_sys("system started successfully")
|
||||
end
|
||||
@ -243,7 +243,6 @@ local function main()
|
||||
no_modem = true
|
||||
log_sys("comms modem disconnected")
|
||||
println_ts("wireless modem disconnected!")
|
||||
log.error("comms modem disconnected!")
|
||||
|
||||
-- close out UI
|
||||
renderer.close_ui()
|
||||
@ -252,20 +251,21 @@ local function main()
|
||||
log_sys("awaiting comms modem reconnect...")
|
||||
else
|
||||
log_sys("non-comms modem disconnected")
|
||||
log.warning("non-comms modem disconnected")
|
||||
end
|
||||
elseif type == "monitor" then
|
||||
if renderer.is_monitor_used(device) then
|
||||
-- "halt and catch fire" style handling
|
||||
println_ts("lost a configured monitor, system will now exit")
|
||||
log_sys("lost a configured monitor, system will now exit")
|
||||
local msg = "lost a configured monitor, system will now exit"
|
||||
println_ts(msg)
|
||||
log_sys(msg)
|
||||
break
|
||||
else
|
||||
log_sys("lost unused monitor, ignoring")
|
||||
end
|
||||
elseif type == "speaker" then
|
||||
println_ts("lost alarm sounder speaker")
|
||||
log_sys("lost alarm sounder speaker")
|
||||
local msg = "lost alarm sounder speaker"
|
||||
println_ts(msg)
|
||||
log_sys(msg)
|
||||
end
|
||||
end
|
||||
elseif event == "peripheral" then
|
||||
@ -291,8 +291,9 @@ local function main()
|
||||
elseif type == "monitor" then
|
||||
-- not supported, system will exit on loss of in-use monitors
|
||||
elseif type == "speaker" then
|
||||
println_ts("alarm sounder speaker reconnected")
|
||||
log_sys("alarm sounder speaker reconnected")
|
||||
local msg = "alarm sounder speaker reconnected"
|
||||
println_ts(msg)
|
||||
log_sys(msg)
|
||||
sounder.reconnect(device)
|
||||
end
|
||||
end
|
||||
@ -301,7 +302,7 @@ local function main()
|
||||
-- main loop tick
|
||||
|
||||
-- free any closed sessions
|
||||
--apisessions.free_all_closed()
|
||||
apisessions.free_all_closed()
|
||||
|
||||
-- update date and time string for main display
|
||||
iocontrol.get_db().facility.ps.publish("date_time", os.date(date_format))
|
||||
@ -326,7 +327,7 @@ local function main()
|
||||
-- a non-clock/main watchdog timer event
|
||||
|
||||
--check API watchdogs
|
||||
--apisessions.check_all_watchdogs(param1)
|
||||
apisessions.check_all_watchdogs(param1)
|
||||
|
||||
-- notify timer callback dispatcher
|
||||
tcallbackdsp.handle(param1)
|
||||
|
@ -13,6 +13,7 @@ local cpair = core.graphics.cpair
|
||||
local border = core.graphics.border
|
||||
|
||||
-- new boiler view
|
||||
---@nodiscard
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
|
@ -19,6 +19,7 @@ local border = core.graphics.border
|
||||
local TEXT_ALIGN = core.graphics.TEXT_ALIGN
|
||||
|
||||
-- new induction matrix view
|
||||
---@nodiscard
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
|
@ -16,11 +16,8 @@ local DataIndicator = require("graphics.elements.indicators.data")
|
||||
local IndicatorLight = require("graphics.elements.indicators.light")
|
||||
local RadIndicator = require("graphics.elements.indicators.rad")
|
||||
local TriIndicatorLight = require("graphics.elements.indicators.trilight")
|
||||
local VerticalBar = require("graphics.elements.indicators.vbar")
|
||||
|
||||
local HazardButton = require("graphics.elements.controls.hazard_button")
|
||||
local MultiButton = require("graphics.elements.controls.multi_button")
|
||||
local PushButton = require("graphics.elements.controls.push_button")
|
||||
local RadioButton = require("graphics.elements.controls.radio_button")
|
||||
local SpinboxNumeric = require("graphics.elements.controls.spinbox_numeric")
|
||||
|
||||
@ -32,6 +29,7 @@ local border = core.graphics.border
|
||||
local period = core.flasher.PERIOD
|
||||
|
||||
-- new process control view
|
||||
---@nodiscard
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
|
@ -1,3 +1,5 @@
|
||||
local types = require("scada-common.types")
|
||||
|
||||
local style = require("coordinator.ui.style")
|
||||
|
||||
local core = require("graphics.core")
|
||||
@ -13,6 +15,7 @@ local cpair = core.graphics.cpair
|
||||
local border = core.graphics.border
|
||||
|
||||
-- create new reactor view
|
||||
---@nodiscard
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
@ -47,7 +50,7 @@ local function new_view(root, x, y, data, ps)
|
||||
local waste = HorizontalBar{parent=reactor_fills,x=8,y=5,show_percent=true,bar_fg_bg=cpair(colors.brown,colors.gray),height=1,width=14}
|
||||
|
||||
ps.subscribe("ccool_type", function (type)
|
||||
if type == "mekanism:sodium" then
|
||||
if type == types.FLUID.SODIUM then
|
||||
ccool.recolor(cpair(colors.lightBlue, colors.gray))
|
||||
else
|
||||
ccool.recolor(cpair(colors.blue, colors.gray))
|
||||
@ -55,7 +58,7 @@ local function new_view(root, x, y, data, ps)
|
||||
end)
|
||||
|
||||
ps.subscribe("hcool_type", function (type)
|
||||
if type == "mekanism:superheated_sodium" then
|
||||
if type == types.FLUID.SUPERHEATED_SODIUM then
|
||||
hcool.recolor(cpair(colors.orange, colors.gray))
|
||||
else
|
||||
hcool.recolor(cpair(colors.white, colors.gray))
|
||||
|
@ -15,6 +15,7 @@ local cpair = core.graphics.cpair
|
||||
local border = core.graphics.border
|
||||
|
||||
-- new turbine view
|
||||
---@nodiscard
|
||||
---@param root graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
|
@ -57,6 +57,7 @@ local waste_opts = {
|
||||
}
|
||||
|
||||
-- create a unit view
|
||||
---@nodiscard
|
||||
---@param parent graphics_element parent
|
||||
---@param id integer
|
||||
local function init(parent, id)
|
||||
|
@ -19,6 +19,7 @@ local TEXT_ALIGN = core.graphics.TEXT_ALIGN
|
||||
local pipe = core.graphics.pipe
|
||||
|
||||
-- make a new unit overview window
|
||||
---@nodiscard
|
||||
---@param parent graphics_element parent
|
||||
---@param x integer top left x
|
||||
---@param y integer top left y
|
||||
@ -51,7 +52,7 @@ local function make(parent, x, y, unit)
|
||||
-- REACTOR --
|
||||
-------------
|
||||
|
||||
reactor_view(root, 1, 3, unit.reactor_data, unit.unit_ps)
|
||||
local _ = reactor_view(root, 1, 3, unit.reactor_data, unit.unit_ps)
|
||||
|
||||
if num_boilers > 0 then
|
||||
local coolant_pipes = {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
--
|
||||
-- Reactor Unit SCADA Coordinator GUI
|
||||
-- Reactor Unit Waiting Spinner
|
||||
--
|
||||
|
||||
local style = require("coordinator.ui.style")
|
||||
@ -16,6 +16,7 @@ local TEXT_ALIGN = core.graphics.TEXT_ALIGN
|
||||
local cpair = core.graphics.cpair
|
||||
|
||||
-- create a unit waiting view
|
||||
---@nodiscard
|
||||
---@param parent graphics_element parent
|
||||
---@param y integer y offset
|
||||
local function init(parent, y)
|
||||
|
@ -3,13 +3,11 @@ local completion = require("cc.completion")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
local print_ts = util.print_ts
|
||||
local println_ts = util.println_ts
|
||||
|
||||
local dialog = {}
|
||||
|
||||
-- ask the user yes or no
|
||||
---@nodiscard
|
||||
---@param question string
|
||||
---@param default boolean
|
||||
---@return boolean|nil
|
||||
@ -36,6 +34,7 @@ function dialog.ask_y_n(question, default)
|
||||
end
|
||||
|
||||
-- ask the user for an input within a set of options
|
||||
---@nodiscard
|
||||
---@param options table
|
||||
---@param cancel string
|
||||
---@return boolean|string|nil
|
||||
|
@ -30,6 +30,7 @@ local TEXT_ALIGN = core.graphics.TEXT_ALIGN
|
||||
local cpair = core.graphics.cpair
|
||||
|
||||
-- create new main view
|
||||
---@nodiscard
|
||||
---@param monitor table main viewscreen
|
||||
local function init(monitor)
|
||||
local facility = iocontrol.get_db().facility
|
||||
@ -90,7 +91,7 @@ local function init(monitor)
|
||||
|
||||
cnc_bottom_align_start = cnc_bottom_align_start + 2
|
||||
|
||||
local process = process_ctl(main, 2, cnc_bottom_align_start)
|
||||
local _ = process_ctl(main, 2, cnc_bottom_align_start)
|
||||
|
||||
-- testing
|
||||
---@fixme remove test code
|
||||
@ -123,7 +124,7 @@ local function init(monitor)
|
||||
SwitchButton{parent=audio,x=1,text="RCS TRANSIENT",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_rcs}
|
||||
SwitchButton{parent=audio,x=1,text="TURBINE TRIP",min_width=23,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=cpair(colors.white,colors.gray),callback=sounder.test_turbinet}
|
||||
|
||||
local imatrix_1 = imatrix(main, 131, cnc_bottom_align_start, facility.induction_data_tbl[1], facility.induction_ps_tbl[1])
|
||||
local _ = imatrix(main, 131, cnc_bottom_align_start, facility.induction_data_tbl[1], facility.induction_ps_tbl[1])
|
||||
|
||||
return main
|
||||
end
|
||||
|
@ -9,12 +9,13 @@ local unit_detail = require("coordinator.ui.components.unit_detail")
|
||||
local DisplayBox = require("graphics.elements.displaybox")
|
||||
|
||||
-- create a unit view
|
||||
---@nodiscard
|
||||
---@param monitor table
|
||||
---@param id integer
|
||||
local function init(monitor, id)
|
||||
local main = DisplayBox{window=monitor,fg_bg=style.root}
|
||||
|
||||
unit_detail(main, id)
|
||||
local _ = unit_detail(main, id)
|
||||
|
||||
return main
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user