-- install.lua -- ETT entry-point for hele autopiloten. Samme kommando paa begge PC-er: -- -- wget run https://gt.zyon.no/Stian/airship-autopilot/raw/branch/main/install.lua -- -- Installeren DETEKTERER selv hvilken PC den staar paa (flysensorer = autopilot, -- monitor = cockpit), installerer riktig rolle, og gaar RETT videre i setup/oppstart -- -- ingen reboot, ingen rollenavn aa huske. Re-run samme kommando for aa oppdatere. -- Eksplisitt rolle som argument overstyrer deteksjonen (avansert): -- wget run .../install.lua autopilot | cockpit -- -- Roles: -- autopilot machine-room PC: full v3 observer autopilot (setup wizard / standby) -- cockpit pilot-house PC: control console (monitor + modem) -- -- Per-skip TILSTAND (sides/calib/target/settings) shippes ALDRI av installeren -- den maales -- av setup-wizarden PAA skipet. Ved re-install kan profilen beholdes eller nullstilles. -- Filer som er fjernet fra manifestet siden sist (eller kjente legacy-filer) ryddes bort. local BASE = "https://gt.zyon.no/Stian/airship-autopilot/raw/branch/main" local ROLES = { "autopilot", "cockpit" } -- per-skip tilstand: roeres aldri automatisk, men tilbys nullstilt ved install local STATE_FILES = { "sides.txt", "calib.txt", "target.txt", "settings.txt" } -- kjente filer fra eldre versjoner som ikke lenger hoerer til rollen (engangs-rydding; -- videre oppdateringer ryddes automatisk via installasjons-loggen .installed_) local LEGACY = { autopilot = { "stabilize.lua", "diag.lua", "probe.lua", "scan.lua", "scan.txt", "pid_gains.txt", "cockpit.lua", "pilot_startup.lua" }, cockpit = {}, } local args = { ... } -- ---- helpers --------------------------------------------------------------- local function die(msg) term.setTextColor(colors.red) print(msg) term.setTextColor(colors.white) error("", 0) end local function get(url) local h, err = http.get(url) if not h then return nil, tostring(err) end local body = h.readAll() h.close() return body end local function writeFile(path, data) local dir = fs.getDir(path) if dir ~= "" and not fs.exists(dir) then fs.makeDir(dir) end local f = fs.open(path, "w") f.write(data) f.close() end local function inList(list, x) for _, v in ipairs(list) do if v == x then return true end end return false end local function chooseRole() print("Select role to install:") print(" 1) autopilot (machine room -- has the") print(" altitude + gimbal sensors)") print(" 2) cockpit (pilot house -- has a") print(" monitor + modem)") write("> ") local sel = read() local n = tonumber(sel) if n and ROLES[n] then return ROLES[n] end for _, r in ipairs(ROLES) do if r == sel then return r end end die("Unknown role: " .. tostring(sel)) end -- gjett rollen ut fra hva som er koblet til: flysensorer er det sterkeste signalet -- (maskinrommet kan ogsaa ha monitor), deretter monitor -> cockpit local function detectRole() if peripheral.find("altitude_sensor") or peripheral.find("gimbal_sensor") then return "autopilot", "flight sensors attached" end if peripheral.find("monitor") then return "cockpit", "monitor attached, no flight sensors" end return nil end -- ---- preflight ------------------------------------------------------------- if not http then die("HTTP API is disabled on this server.\n" .. "Enable it in the server's computercraft-server.toml:\n" .. " [http] enabled = true then restart the server.") end local role = args[1] if role then local ok = false for _, r in ipairs(ROLES) do if r == role then ok = true end end if not ok then die("Unknown role '" .. role .. "'. Valid: " .. table.concat(ROLES, ", ")) end else local guess, why = detectRole() if guess then print("This looks like the " .. (guess == "autopilot" and "MACHINE-ROOM" or "PILOT-HOUSE") .. " PC") print(" (" .. why .. ")") write("Install '" .. guess .. "'? [Y/n] ") role = (read():lower() == "n") and chooseRole() or guess else print("Could not auto-detect this PC's role") print("(no flight sensors or monitor attached).") role = chooseRole() end end -- ---- fetch manifest -------------------------------------------------------- print("Installing role: " .. role) local manifestUrl = BASE .. "/files/" .. role .. "/manifest" local manifest, mErr = get(manifestUrl) if not manifest then die("Could not fetch manifest (" .. mErr .. ")\n" .. manifestUrl) end local files = {} for line in manifest:gmatch("[^\r\n]+") do local p = line:match("^%s*(.-)%s*$") if p ~= "" then files[#files + 1] = p end end if #files == 0 then die("Manifest is empty: " .. manifestUrl) end -- ---- download -------------------------------------------------------------- local ok, fail = 0, {} for i, rel in ipairs(files) do term.write(("[%d/%d] %s "):format(i, #files, rel)) local data, err = get(BASE .. "/files/" .. role .. "/" .. rel) if data then writeFile(rel, data) term.setTextColor(colors.green); print("ok"); term.setTextColor(colors.white) ok = ok + 1 else term.setTextColor(colors.red); print("FAIL"); term.setTextColor(colors.white) fail[#fail + 1] = rel .. " (" .. tostring(err) .. ")" end end print(("Installed %d/%d files."):format(ok, #files)) if #fail > 0 then term.setTextColor(colors.red) print("Failed:") for _, f in ipairs(fail) do print(" " .. f) end term.setTextColor(colors.white) die("Install incomplete -- re-run after fixing the errors above.") end -- ---- rydd: legacy + filer fjernet fra manifestet siden forrige install ------ local removed = 0 for _, f in ipairs(LEGACY[role] or {}) do if fs.exists(f) then fs.delete(f); removed = removed + 1; print("removed legacy: " .. f) end end local RECORD = ".installed_" .. role if fs.exists(RECORD) then local rf = fs.open(RECORD, "r"); local prev = rf.readAll(); rf.close() for line in (prev or ""):gmatch("[^\r\n]+") do local p = line:match("^%s*(.-)%s*$") if p ~= "" and not inList(files, p) and not inList(STATE_FILES, p) and fs.exists(p) then fs.delete(p); removed = removed + 1; print("removed obsolete: " .. p) end end end writeFile(RECORD, table.concat(files, "\n") .. "\n") if removed > 0 then print(("Cleaned up %d old file(s)."):format(removed)) end -- ---- skip-profil: behold eller nullstill (ETTER vellykket install, foer boot) ---- -- (kun autopilot-rollen har skip-tilstand; sletter aldri noe hvis nedlastingen feilet) if role == "autopilot" then local found = {} for _, f in ipairs(STATE_FILES) do if fs.exists(f) then found[#found + 1] = f end end if #found > 0 then print("Existing ship profile found:") print(" " .. table.concat(found, ", ")) write("Keep it? (n = new/rewired ship) [Y/n] ") if read():lower() == "n" then for _, f in ipairs(found) do fs.delete(f) end print("Profile reset -- the setup wizard takes over.") end end end -- ---- ferdig: gaa RETT videre (ingen reboot noedvendig) ---------------------- -- startup.lua er installert, saa alt auto-starter ved fremtidige reboots; naa -- fortsetter vi direkte inn i samme flyt som boot ville gitt. term.setTextColor(colors.green) print("Done. (auto-starts on every reboot)") term.setTextColor(colors.white) print("") if role == "autopilot" then print("Continuing into setup/standby...") sleep(1.0) shell.run("ap", "boot") else print("Starting the pilot console...") sleep(1.0) shell.run("cockpit") end