2022-01-13 15:23:56 +00:00
|
|
|
--
|
2023-04-12 16:40:13 +00:00
|
|
|
-- SCADA System Access on a Pocket Computer
|
2022-05-14 17:32:42 +00:00
|
|
|
--
|
|
|
|
|
|
|
|
require("/initenv").init_env()
|
2023-02-19 17:54:02 +00:00
|
|
|
|
2023-07-29 22:16:59 +00:00
|
|
|
local crash = require("scada-common.crash")
|
|
|
|
local log = require("scada-common.log")
|
|
|
|
local network = require("scada-common.network")
|
|
|
|
local ppm = require("scada-common.ppm")
|
|
|
|
local tcd = require("scada-common.tcd")
|
|
|
|
local util = require("scada-common.util")
|
2023-02-19 17:54:02 +00:00
|
|
|
|
2023-07-29 22:16:59 +00:00
|
|
|
local core = require("graphics.core")
|
2023-04-12 16:40:13 +00:00
|
|
|
|
2024-02-19 19:07:26 +00:00
|
|
|
local configure = require("pocket.configure")
|
2023-07-29 22:16:59 +00:00
|
|
|
local iocontrol = require("pocket.iocontrol")
|
|
|
|
local pocket = require("pocket.pocket")
|
|
|
|
local renderer = require("pocket.renderer")
|
2023-04-12 16:40:13 +00:00
|
|
|
|
2024-05-17 02:06:53 +00:00
|
|
|
local POCKET_VERSION = "v0.9.1-alpha"
|
2023-02-19 17:54:02 +00:00
|
|
|
|
|
|
|
local println = util.println
|
|
|
|
local println_ts = util.println_ts
|
|
|
|
|
2023-04-12 16:40:13 +00:00
|
|
|
----------------------------------------
|
2024-02-19 19:07:26 +00:00
|
|
|
-- get configuration
|
2023-04-12 16:40:13 +00:00
|
|
|
----------------------------------------
|
|
|
|
|
2024-02-19 19:07:26 +00:00
|
|
|
if not pocket.load_config() then
|
|
|
|
-- try to reconfigure (user action)
|
|
|
|
local success, error = configure.configure(true)
|
|
|
|
if success then
|
2024-03-06 01:17:52 +00:00
|
|
|
if not pocket.load_config() then
|
|
|
|
println("failed to load a valid configuration, please reconfigure")
|
|
|
|
return
|
|
|
|
end
|
2024-02-19 19:07:26 +00:00
|
|
|
else
|
2024-03-06 01:17:52 +00:00
|
|
|
println("configuration error: " .. error)
|
|
|
|
return
|
2024-02-19 19:07:26 +00:00
|
|
|
end
|
|
|
|
end
|
2023-04-12 16:40:13 +00:00
|
|
|
|
2024-02-19 19:07:26 +00:00
|
|
|
local config = pocket.config
|
2023-04-12 16:40:13 +00:00
|
|
|
|
|
|
|
----------------------------------------
|
|
|
|
-- log init
|
|
|
|
----------------------------------------
|
|
|
|
|
2024-02-19 19:07:26 +00:00
|
|
|
log.init(config.LogPath, config.LogMode, config.LogDebug)
|
2023-04-12 16:40:13 +00:00
|
|
|
|
|
|
|
log.info("========================================")
|
|
|
|
log.info("BOOTING pocket.startup " .. POCKET_VERSION)
|
|
|
|
log.info("========================================")
|
|
|
|
|
|
|
|
crash.set_env("pocket", POCKET_VERSION)
|
2024-03-23 04:49:19 +00:00
|
|
|
crash.dbg_log_env()
|
2023-04-12 16:40:13 +00:00
|
|
|
|
|
|
|
----------------------------------------
|
|
|
|
-- main application
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
local function main()
|
|
|
|
----------------------------------------
|
|
|
|
-- system startup
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
-- mount connected devices
|
|
|
|
ppm.mount_all()
|
|
|
|
|
2024-04-13 20:18:27 +00:00
|
|
|
-- record version for GUI
|
|
|
|
iocontrol.get_db().version = POCKET_VERSION
|
|
|
|
|
2023-04-12 16:40:13 +00:00
|
|
|
----------------------------------------
|
2023-04-18 17:47:06 +00:00
|
|
|
-- setup communications & clocks
|
2023-04-12 16:40:13 +00:00
|
|
|
----------------------------------------
|
|
|
|
|
2023-06-25 18:00:18 +00:00
|
|
|
-- message authentication init
|
2024-02-19 19:07:26 +00:00
|
|
|
if type(config.AuthKey) == "string" and string.len(config.AuthKey) > 0 then
|
|
|
|
network.init_mac(config.AuthKey)
|
2023-06-25 18:00:18 +00:00
|
|
|
end
|
|
|
|
|
2023-07-29 22:16:59 +00:00
|
|
|
iocontrol.report_link_state(iocontrol.LINK_STATE.UNLINKED)
|
2023-04-18 17:47:06 +00:00
|
|
|
|
2023-04-12 16:40:13 +00:00
|
|
|
-- get the communications modem
|
|
|
|
local modem = ppm.get_wireless_modem()
|
|
|
|
if modem == nil then
|
|
|
|
println("startup> wireless modem not found: please craft the pocket computer with a wireless modem")
|
2023-04-16 23:50:16 +00:00
|
|
|
log.fatal("startup> no wireless modem on startup")
|
2023-04-12 16:40:13 +00:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2023-04-16 23:50:16 +00:00
|
|
|
-- create connection watchdogs
|
|
|
|
local conn_wd = {
|
2024-02-19 19:07:26 +00:00
|
|
|
sv = util.new_watchdog(config.ConnTimeout),
|
|
|
|
api = util.new_watchdog(config.ConnTimeout)
|
2023-04-16 23:50:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
conn_wd.sv.cancel()
|
|
|
|
conn_wd.api.cancel()
|
|
|
|
|
|
|
|
log.debug("startup> conn watchdogs created")
|
2023-04-12 16:40:13 +00:00
|
|
|
|
2023-06-25 16:59:38 +00:00
|
|
|
-- create network interface then setup comms
|
2023-06-21 23:04:39 +00:00
|
|
|
local nic = network.nic(modem)
|
2024-02-19 19:07:26 +00:00
|
|
|
local pocket_comms = pocket.comms(POCKET_VERSION, nic, conn_wd.sv, conn_wd.api)
|
2023-04-16 23:50:16 +00:00
|
|
|
log.debug("startup> comms init")
|
2023-04-12 16:40:13 +00:00
|
|
|
|
|
|
|
-- base loop clock (2Hz, 10 ticks)
|
|
|
|
local MAIN_CLOCK = 0.5
|
|
|
|
local loop_clock = util.new_clock(MAIN_CLOCK)
|
|
|
|
|
2023-07-29 22:16:59 +00:00
|
|
|
-- init I/O control
|
|
|
|
iocontrol.init_core(pocket_comms)
|
|
|
|
|
2023-04-12 16:40:13 +00:00
|
|
|
----------------------------------------
|
|
|
|
-- start the UI
|
|
|
|
----------------------------------------
|
|
|
|
|
2023-09-30 17:31:41 +00:00
|
|
|
local ui_ok, message = renderer.try_start_ui()
|
2023-04-12 16:40:13 +00:00
|
|
|
if not ui_ok then
|
2023-04-22 03:43:28 +00:00
|
|
|
println(util.c("UI error: ", message))
|
2023-07-11 19:15:44 +00:00
|
|
|
log.error(util.c("startup> GUI render failed with error ", message))
|
2023-04-12 16:40:13 +00:00
|
|
|
else
|
|
|
|
-- start clock
|
|
|
|
loop_clock.start()
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------
|
|
|
|
-- main event loop
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
if ui_ok then
|
2023-04-16 23:50:16 +00:00
|
|
|
-- start connection watchdogs
|
|
|
|
conn_wd.sv.feed()
|
|
|
|
conn_wd.api.feed()
|
2023-12-22 16:12:47 +00:00
|
|
|
log.debug("startup> conn watchdogs started")
|
2023-04-12 16:40:13 +00:00
|
|
|
|
2023-07-29 22:16:59 +00:00
|
|
|
local io_db = iocontrol.get_db()
|
|
|
|
local nav = io_db.nav
|
|
|
|
|
2023-04-30 03:48:50 +00:00
|
|
|
-- main event loop
|
|
|
|
while true do
|
|
|
|
local event, param1, param2, param3, param4, param5 = util.pull_event()
|
|
|
|
|
|
|
|
-- handle event
|
|
|
|
if event == "timer" then
|
|
|
|
if loop_clock.is_clock(param1) then
|
|
|
|
-- main loop tick
|
|
|
|
|
|
|
|
-- relink if necessary
|
|
|
|
pocket_comms.link_update()
|
|
|
|
|
2023-07-29 22:16:59 +00:00
|
|
|
-- update any tasks for the active page
|
2023-12-22 16:12:47 +00:00
|
|
|
local page_tasks = nav.get_current_page().tasks
|
|
|
|
for i = 1, #page_tasks do page_tasks[i]() end
|
2023-07-29 22:16:59 +00:00
|
|
|
|
2023-04-30 03:48:50 +00:00
|
|
|
loop_clock.start()
|
|
|
|
elseif conn_wd.sv.is_timer(param1) then
|
|
|
|
-- supervisor watchdog timeout
|
|
|
|
log.info("supervisor server timeout")
|
|
|
|
pocket_comms.close_sv()
|
|
|
|
elseif conn_wd.api.is_timer(param1) then
|
|
|
|
-- coordinator watchdog timeout
|
|
|
|
log.info("coordinator api server timeout")
|
|
|
|
pocket_comms.close_api()
|
|
|
|
else
|
|
|
|
-- a non-clock/main watchdog timer event
|
|
|
|
-- notify timer callback dispatcher
|
2023-06-03 21:40:57 +00:00
|
|
|
tcd.handle(param1)
|
2023-04-30 03:48:50 +00:00
|
|
|
end
|
|
|
|
elseif event == "modem_message" then
|
|
|
|
-- got a packet
|
|
|
|
local packet = pocket_comms.parse_packet(param1, param2, param3, param4, param5)
|
|
|
|
pocket_comms.handle_packet(packet)
|
2023-10-04 02:52:13 +00:00
|
|
|
elseif event == "mouse_click" or event == "mouse_up" or event == "mouse_drag" or event == "mouse_scroll" or
|
2023-09-23 16:58:09 +00:00
|
|
|
event == "double_click" then
|
2023-04-30 03:48:50 +00:00
|
|
|
-- handle a monitor touch event
|
2023-05-12 00:02:42 +00:00
|
|
|
renderer.handle_mouse(core.events.new_mouse_event(event, param1, param2, param3))
|
2023-04-12 16:40:13 +00:00
|
|
|
end
|
|
|
|
|
2023-04-30 03:48:50 +00:00
|
|
|
-- check for termination request
|
|
|
|
if event == "terminate" or ppm.should_terminate() then
|
|
|
|
log.info("terminate requested, closing server connections...")
|
|
|
|
pocket_comms.close()
|
|
|
|
log.info("connections closed")
|
|
|
|
break
|
|
|
|
end
|
2023-04-12 16:40:13 +00:00
|
|
|
end
|
|
|
|
|
2023-04-30 03:48:50 +00:00
|
|
|
renderer.close_ui()
|
|
|
|
end
|
2023-04-12 16:40:13 +00:00
|
|
|
|
|
|
|
println_ts("exited")
|
|
|
|
log.info("exited")
|
|
|
|
end
|
|
|
|
|
|
|
|
if not xpcall(main, crash.handler) then
|
|
|
|
pcall(renderer.close_ui)
|
|
|
|
crash.exit()
|
2023-04-21 01:01:41 +00:00
|
|
|
else
|
|
|
|
log.close()
|
2023-04-12 16:40:13 +00:00
|
|
|
end
|