Merge branch 'devel' into 51-hmac-message-authentication

This commit is contained in:
Mikayla 2023-06-18 19:23:56 +00:00
commit 282c7db3eb
8 changed files with 167 additions and 160 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
_notes/
program.sh
/*program.sh

297
ccmsi.lua
View File

@ -20,7 +20,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local function println(message) print(tostring(message)) end
local function print(message) term.write(tostring(message)) end
local CCMSI_VERSION = "v1.2"
local CCMSI_VERSION = "v1.4f"
local install_dir = "/.install-cache"
local manifest_path = "https://mikaylafischler.github.io/cc-mek-scada/manifests/"
@ -29,6 +29,7 @@ local repo_path = "http://raw.githubusercontent.com/MikaylaFischler/cc-mek-scada
local opts = { ... }
local mode = nil
local app = nil
local target
-- record the local installation manifest
---@param manifest table
@ -38,7 +39,7 @@ local function write_install_manifest(manifest, dependencies)
for key, value in pairs(manifest.versions) do
local is_dependency = false
for _, dependency in pairs(dependencies) do
if key == "bootloader" and dependency == "system" then
if (key == "bootloader" and dependency == "system") or key == dependency then
is_dependency = true
break
end
@ -54,6 +55,68 @@ local function write_install_manifest(manifest, dependencies)
imfile.close()
end
-- ask the user yes or no
---@nodiscard
---@param question string
---@param default boolean
---@return boolean|nil
local function ask_y_n(question, default)
print(question)
if default == true then
print(" (Y/n)? ")
else
print(" (y/N)? ")
end
local response = read(nil, nil)
if response == "" then
return default
elseif response == "Y" or response == "y" then
return true
elseif response == "N" or response == "n" then
return false
else
return nil
end
end
-- print out a white + blue text message<br>
-- automatically adds a space
---@param message string message
---@param package string dependency/package/version
local function pkg_message(message, package)
term.setTextColor(colors.white)
print(message .. " ")
term.setTextColor(colors.blue)
println(package)
term.setTextColor(colors.white)
end
-- indicate actions to be taken based on package differences for installs/updates
---@param name string package name
---@param v_local string|nil local version
---@param v_remote string remote version
local function show_pkg_change(name, v_local, v_remote)
if v_local ~= nil then
if v_local ~= v_remote then
print("[" .. name .. "] updating ")
term.setTextColor(colors.blue)
print(v_local)
term.setTextColor(colors.white)
print(" \xbb ")
term.setTextColor(colors.blue)
println(v_local)
term.setTextColor(colors.white)
elseif mode == "install" then
pkg_message("[" .. name .. "] reinstalling", v_local)
end
else
pkg_message("[" .. name .. "] new install of", v_remote)
end
end
--
-- get and validate command line options
--
@ -61,12 +124,12 @@ end
println("-- CC Mekanism SCADA Installer " .. CCMSI_VERSION .. " --")
if #opts == 0 or opts[1] == "help" then
println("usage: ccmsi <mode> <app> <tag/branch>")
println("usage: ccmsi <mode> <app> <branch>")
println("<mode>")
term.setTextColor(colors.lightGray)
println(" check - check latest versions avilable")
term.setTextColor(colors.yellow)
println(" ccmsi check <tag/branch> for target")
println(" ccmsi check <branch> for target")
term.setTextColor(colors.lightGray)
println(" install - fresh install, overwrites config")
println(" update - update files EXCEPT for config/logs")
@ -81,12 +144,11 @@ if #opts == 0 or opts[1] == "help" then
println(" coordinator - coordinator application")
println(" pocket - pocket application")
term.setTextColor(colors.white)
println("<tag/branch>")
println("<branch>")
term.setTextColor(colors.yellow)
println(" second parameter when used with check")
term.setTextColor(colors.lightGray)
println(" note: defaults to main")
println(" target GitHub tag or branch name")
println(" main (default) | latest | devel")
return
else
for _, v in pairs({ "check", "install", "update", "remove", "purge" }) do
@ -112,6 +174,13 @@ else
println("unrecognized application")
return
end
-- determine target
if mode == "check" then target = opts[2] else target = opts[3] end
if (target ~= "main") and (target ~= "latest") and (target ~= "devel") then
target = "main"
println("unknown target, defaulting to 'main'")
end
end
--
@ -123,7 +192,7 @@ if mode == "check" then
-- GET REMOTE MANIFEST --
-------------------------
if opts[2] then manifest_path = manifest_path .. opts[2] .. "/" else manifest_path = manifest_path .. "main/" end
manifest_path = manifest_path .. target .. "/"
local install_manifest = manifest_path .. "install_manifest.json"
local response, error = http.get(install_manifest)
@ -203,8 +272,8 @@ elseif mode == "install" or mode == "update" then
-- GET REMOTE MANIFEST --
-------------------------
if opts[3] then repo_path = repo_path .. opts[3] .. "/" else repo_path = repo_path .. "main/" end
if opts[3] then manifest_path = manifest_path .. opts[3] .. "/" else manifest_path = manifest_path .. "main/" end
repo_path = repo_path .. target .. "/"
manifest_path = manifest_path .. target .. "/"
local install_manifest = manifest_path .. "install_manifest.json"
local response, error = http.get(install_manifest)
@ -230,6 +299,13 @@ elseif mode == "install" or mode == "update" then
-- GET LOCAL MANIFEST --
------------------------
local ver = {
app = { v_local = nil, v_remote = nil, changed = false },
boot = { v_local = nil, v_remote = nil, changed = false },
comms = { v_local = nil, v_remote = nil, changed = false },
graphics = { v_local = nil, v_remote = nil, changed = false }
}
local imfile = fs.open("install_manifest.json", "r")
local local_ok = false
local local_manifest = {}
@ -239,10 +315,6 @@ elseif mode == "install" or mode == "update" then
imfile.close()
end
local local_app_version = nil
local local_comms_version = nil
local local_boot_version = nil
-- try to find local versions
if not local_ok then
if mode == "update" then
@ -252,9 +324,10 @@ elseif mode == "install" or mode == "update" then
return
end
else
local_app_version = local_manifest.versions[app]
local_comms_version = local_manifest.versions.comms
local_boot_version = local_manifest.versions.bootloader
ver.boot.v_local = local_manifest.versions.bootloader
ver.app.v_local = local_manifest.versions[app]
ver.comms.v_local = local_manifest.versions.comms
ver.graphics.v_local = local_manifest.versions.graphics
if local_manifest.versions[app] == nil then
term.setTextColor(colors.red)
@ -271,93 +344,43 @@ elseif mode == "install" or mode == "update" then
end
end
local remote_app_version = manifest.versions[app]
local remote_comms_version = manifest.versions.comms
local remote_boot_version = manifest.versions.bootloader
ver.boot.v_remote = manifest.versions.bootloader
ver.app.v_remote = manifest.versions[app]
ver.comms.v_remote = manifest.versions.comms
ver.graphics.v_remote = manifest.versions.graphics
term.setTextColor(colors.green)
if mode == "install" then
println("installing " .. app .. " files...")
println("Installing " .. app .. " files...")
elseif mode == "update" then
println("updating " .. app .. " files... (keeping old config.lua)")
println("Updating " .. app .. " files... (keeping old config.lua)")
end
term.setTextColor(colors.white)
-- display bootloader version change information
if local_boot_version ~= nil then
if local_boot_version ~= remote_boot_version then
print("[bootldr] updating ")
term.setTextColor(colors.blue)
print(local_boot_version)
term.setTextColor(colors.white)
print(" \xbb ")
term.setTextColor(colors.blue)
println(remote_boot_version)
term.setTextColor(colors.white)
elseif mode == "install" then
print("[bootldr] reinstalling ")
term.setTextColor(colors.blue)
println(local_boot_version)
term.setTextColor(colors.white)
end
else
print("[bootldr] new install of ")
term.setTextColor(colors.blue)
println(remote_boot_version)
term.setTextColor(colors.white)
end
show_pkg_change("bootldr", ver.boot.v_local, ver.boot.v_remote)
ver.boot.changed = ver.boot.v_local ~= ver.boot.v_remote
-- display app version change information
if local_app_version ~= nil then
if local_app_version ~= remote_app_version then
print("[" .. app .. "] updating ")
term.setTextColor(colors.blue)
print(local_app_version)
term.setTextColor(colors.white)
print(" \xbb ")
term.setTextColor(colors.blue)
println(remote_app_version)
term.setTextColor(colors.white)
elseif mode == "install" then
print("[" .. app .. "] reinstalling ")
term.setTextColor(colors.blue)
println(local_app_version)
term.setTextColor(colors.white)
end
else
print("[" .. app .. "] new install of ")
term.setTextColor(colors.blue)
println(remote_app_version)
show_pkg_change(app, ver.app.v_local, ver.app.v_remote)
ver.app.changed = ver.app.v_local ~= ver.app.v_remote
-- display comms version change information
show_pkg_change("comms", ver.comms.v_local, ver.comms.v_remote)
ver.comms.changed = ver.comms.v_local ~= ver.comms.v_remote
if ver.comms.changed and ver.comms.v_local ~= nil then
print("[comms] ")
term.setTextColor(colors.yellow)
println("other devices on the network will require an update")
term.setTextColor(colors.white)
end
-- display comms version change information
if local_comms_version ~= nil then
if local_comms_version ~= remote_comms_version then
print("[comms] updating ")
term.setTextColor(colors.blue)
print(local_comms_version)
term.setTextColor(colors.white)
print(" \xbb ")
term.setTextColor(colors.blue)
println(remote_comms_version)
term.setTextColor(colors.white)
print("[comms] ")
term.setTextColor(colors.yellow)
println("other devices on the network will require an update")
term.setTextColor(colors.white)
elseif mode == "install" then
print("[comms] reinstalling ")
term.setTextColor(colors.blue)
println(local_comms_version)
term.setTextColor(colors.white)
end
else
print("[comms] new install of ")
term.setTextColor(colors.blue)
println(remote_comms_version)
term.setTextColor(colors.white)
end
-- display graphics version change information
show_pkg_change("graphics", ver.graphics.v_local, ver.graphics.v_remote)
ver.graphics.changed = ver.graphics.v_local ~= ver.graphics.v_remote
-- ask for confirmation
if not ask_y_n("Continue?", false) then return end
--------------------------
-- START INSTALL/UPDATE --
@ -386,20 +409,26 @@ elseif mode == "install" or mode == "update" then
println("WARNING: Insufficient space available for a full download!")
term.setTextColor(colors.white)
println("Files can be downloaded one by one, so if you are replacing a current install this will not be a problem unless installation fails.")
println("Do you wish to continue? (y/N)")
local confirm = read()
if confirm ~= "y" and confirm ~= "Y" then
println("installation cancelled")
if mode == "update" then println("If installation still fails, delete this device's log file and try again.") end
if not ask_y_n("Do you wish to continue?", false) then
println("Operation cancelled.")
return
end
end
---@diagnostic disable-next-line: undefined-field
os.sleep(2)
local success = true
-- helper function to check if a dependency is unchanged
---@nodiscard
---@param dependency string
---@return boolean
local function unchanged(dependency)
if dependency == "system" then return not ver.boot.changed
elseif dependency == "graphics" then return not ver.graphics.changed
elseif dependency == app then return not ver.app.changed
else return true end
end
if not single_file_mode then
if fs.exists(install_dir) then
fs.delete(install_dir)
@ -408,20 +437,12 @@ elseif mode == "install" or mode == "update" then
-- download all dependencies
for _, dependency in pairs(dependencies) do
if mode == "update" and ((dependency == "system" and local_boot_version == remote_boot_version) or (local_app_version == remote_app_version)) then
-- skip system package if unchanged, skip app package if not changed
-- skip packages that have no version if app version didn't change
term.setTextColor(colors.white)
print("skipping download of unchanged package ")
term.setTextColor(colors.blue)
println(dependency)
if mode == "update" and unchanged(dependency) then
pkg_message("skipping download of unchanged package", dependency)
else
term.setTextColor(colors.white)
print("downloading package ")
term.setTextColor(colors.blue)
println(dependency)
pkg_message("downloading package", dependency)
term.setTextColor(colors.lightGray)
local files = file_list[dependency]
for _, file in pairs(files) do
println("GET " .. file)
@ -444,20 +465,12 @@ elseif mode == "install" or mode == "update" then
-- copy in downloaded files (installation)
if success then
for _, dependency in pairs(dependencies) do
if mode == "update" and ((dependency == "system" and local_boot_version == remote_boot_version) or (local_app_version == remote_app_version)) then
-- skip system package if unchanged, skip app package if not changed
-- skip packages that have no version if app version didn't change
term.setTextColor(colors.white)
print("skipping install of unchanged package ")
term.setTextColor(colors.blue)
println(dependency)
if mode == "update" and unchanged(dependency) then
pkg_message("skipping install of unchanged package", dependency)
else
term.setTextColor(colors.white)
print("installing package ")
term.setTextColor(colors.blue)
println(dependency)
pkg_message("installing package", dependency)
term.setTextColor(colors.lightGray)
local files = file_list[dependency]
for _, file in pairs(files) do
if mode == "install" or file ~= config_file then
@ -478,36 +491,28 @@ elseif mode == "install" or mode == "update" then
write_install_manifest(manifest, dependencies)
term.setTextColor(colors.green)
if mode == "install" then
println("installation completed successfully")
println("Installation completed successfully.")
else
println("update completed successfully")
println("Update completed successfully.")
end
else
if mode == "install" then
term.setTextColor(colors.red)
println("installation failed")
println("Installation failed.")
else
term.setTextColor(colors.orange)
println("update failed, existing files unmodified")
println("Update failed, existing files unmodified.")
end
end
else
-- go through all files and replace one by one
for _, dependency in pairs(dependencies) do
if mode == "update" and ((dependency == "system" and local_boot_version == remote_boot_version) or (local_app_version == remote_app_version)) then
-- skip system package if unchanged, skip app package if not changed
-- skip packages that have no version if app version didn't change
term.setTextColor(colors.white)
print("skipping install of unchanged package ")
term.setTextColor(colors.blue)
println(dependency)
if mode == "update" and unchanged(dependency) then
pkg_message("skipping install of unchanged package", dependency)
else
term.setTextColor(colors.white)
print("installing package ")
term.setTextColor(colors.blue)
println(dependency)
pkg_message("installing package", dependency)
term.setTextColor(colors.lightGray)
local files = file_list[dependency]
for _, file in pairs(files) do
if mode == "install" or file ~= config_file then
@ -534,16 +539,16 @@ elseif mode == "install" or mode == "update" then
write_install_manifest(manifest, dependencies)
term.setTextColor(colors.green)
if mode == "install" then
println("installation completed successfully")
println("Installation completed successfully.")
else
println("update completed successfully")
println("Update completed successfully.")
end
else
term.setTextColor(colors.red)
if mode == "install" then
println("installation failed, files may have been skipped")
println("Installation failed, files may have been skipped.")
else
println("update failed, files may have been skipped")
println("Update failed, files may have been skipped.")
end
end
end
@ -576,8 +581,8 @@ elseif mode == "remove" or mode == "purge" then
println("purging all " .. app .. " files...")
end
---@diagnostic disable-next-line: undefined-field
os.sleep(2)
-- ask for confirmation
if not ask_y_n("Continue?", false) then return end
local file_list = manifest.files
local dependencies = manifest.depends[app]
@ -666,7 +671,7 @@ elseif mode == "remove" or mode == "purge" then
end
term.setTextColor(colors.green)
println("done!")
println("Done!")
end
term.setTextColor(colors.white)

View File

@ -7,6 +7,8 @@ local flasher = require("graphics.flasher")
local core = {}
core.version = "1.0.0"
core.flasher = flasher
core.events = events

View File

@ -23,11 +23,11 @@ def dir_size(path):
return total
# get the version of an application at the provided path
def get_version(path, is_comms = False):
def get_version(path, is_lib = False):
ver = ""
string = "comms.version = \""
string = ".version = \""
if not is_comms:
if not is_lib:
string = "_VERSION = \""
f = open(path, "r")
@ -49,6 +49,7 @@ def make_manifest(size):
"installer" : get_version("./ccmsi.lua"),
"bootloader" : get_version("./startup.lua"),
"comms" : get_version("./scada-common/comms.lua", True),
"graphics" : get_version("./graphics/core.lua", True),
"reactor-plc" : get_version("./reactor-plc/startup.lua"),
"rtu" : get_version("./rtu/startup.lua"),
"supervisor" : get_version("./supervisor/startup.lua"),

File diff suppressed because one or more lines are too long

View File

@ -75,7 +75,7 @@ function facility.new(num_reactors, cooling_conf)
burn_target = 0.1, -- burn rate target for aggregate burn mode
charge_setpoint = 0, -- FE charge target setpoint
gen_rate_setpoint = 0, -- FE/t charge rate target setpoint
group_map = { 0, 0, 0, 0 }, -- units -> group IDs
group_map = {}, -- units -> group IDs
prio_defs = { {}, {}, {}, {} }, -- priority definitions (each level is a table of units)
at_max_burn = false,
ascram = false,
@ -109,6 +109,7 @@ function facility.new(num_reactors, cooling_conf)
-- create units
for i = 1, num_reactors do
table.insert(self.units, unit.new(i, cooling_conf[i].BOILERS, cooling_conf[i].TURBINES))
table.insert(self.group_map, 0)
end
-- init redstone RTU I/O controller
@ -790,7 +791,7 @@ function facility.new(num_reactors, cooling_conf)
---@param unit_id integer unit ID
---@param group integer group ID or 0 for independent
function public.set_group(unit_id, group)
if group >= 0 and group <= 4 and self.mode == PROCESS.INACTIVE then
if (group >= 0 and group <= 4) and (unit_id > 0 and unit_id <= num_reactors) and self.mode == PROCESS.INACTIVE then
-- remove from old group if previously assigned
local old_group = self.group_map[unit_id]
if old_group ~= 0 then

View File

@ -120,7 +120,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
if u_type == false then
-- validation fail
log.debug(log_header .. "advertisement unit validation failure")
log.debug(log_header .. "_handle_advertisement(): advertisement unit validation failure")
else
if unit_advert.reactor > 0 then
local target_unit = self.fac_units[unit_advert.reactor] ---@type reactor_unit
@ -146,7 +146,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
-- skip virtual units
log.debug(util.c(log_header, "skipping virtual RTU unit #", i))
else
log.error(util.c(log_header, "bad advertisement: encountered unsupported reactor-specific RTU type ", type_string))
log.warning(util.c(log_header, "_handle_advertisement(): encountered unsupported reactor-specific RTU type ", type_string))
end
else
-- facility RTUs
@ -172,7 +172,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
-- skip virtual units
log.debug(util.c(log_header, "skipping virtual RTU unit #", i))
else
log.error(util.c(log_header, "bad advertisement: encountered unsupported reactor-independent RTU type ", type_string))
log.warning(util.c(log_header, "_handle_advertisement(): encountered unsupported facility RTU type ", type_string))
end
end
end
@ -181,9 +181,7 @@ function rtu.new_session(id, s_addr, in_queue, out_queue, timeout, advertisement
self.units[i] = unit
unit_count = unit_count + 1
elseif u_type ~= RTU_UNIT_TYPE.VIRTUAL then
_reset_config()
log.error(util.c(log_header, "bad advertisement: error occured while creating a unit (type is ", type_string, ")"))
break
log.warning(util.c(log_header, "_handle_advertisement(): problem occured while creating a unit (type is ", type_string, ")"))
end
end

View File

@ -20,7 +20,7 @@ local supervisor = require("supervisor.supervisor")
local svsessions = require("supervisor.session.svsessions")
local SUPERVISOR_VERSION = "v0.17.7"
local SUPERVISOR_VERSION = "v0.17.9"
local println = util.println
local println_ts = util.println_ts