Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -------------------------
- -- Konfiguration
- -------------------------
- local version = 3.2
- local CFG = {
- tickSeconds = 1.0,
- -- Energie-Puffer in % (0..100)
- targetBuffer = 60,
- hysteresis = 4,
- startAt = 35,
- stopAt = 90,
- -- Steuerstab-Limits
- minRod = 0,
- maxRod = 100,
- -- Temperaturgrenzen
- maxFuelTemp = 2000,
- maxCasingTemp = 1500,
- -- Fuel-Schutz
- minFuelPercent = 2,
- -- Anzeige
- useMonitor = true,
- monitorScale = 0.5,
- -- WebSocket
- wsEnabled = true,
- wsUrl = "ws://lupus7x.de:7777/ws/ingest",
- wsSendEveryTicks = 1,
- -- Redstone-Freigabe: Reaktor nur aktiv wenn Signal==15 ankommt
- rsEnableGate = true,
- rsEnableSides = { "top", "bottom" }, -- oben oder unten
- rsEnableLevel = 15, -- analoger Level, muss exakt passen
- rsGateScramRods = true -- wenn nicht freigegeben: rods auf 100
- }
- local lastActiveKnown = false
- -------------------------
- -- Hilfsfunktionen
- -------------------------
- local function clamp(x, a, b)
- if x < a then
- return a
- end
- if x > b then
- return b
- end
- return x
- end
- local function round(x)
- return math.floor(x + 0.5)
- end
- local function safeCall(fn, default)
- local ok, val = pcall(fn)
- if ok then
- return val
- end
- return default
- end
- local function fmtPercent(x)
- return tostring(round(x)) .. "%"
- end
- -- RS Gate: TRUE wenn Freigabe anliegt (analog==15 an top oder bottom)
- local function rsIsEnabled()
- if not CFG.rsEnableGate then return true end
- for _, side in ipairs(CFG.rsEnableSides or {}) do
- local lvl = redstone.getAnalogInput(side) or 0
- if lvl == CFG.rsEnableLevel then
- return true
- end
- end
- return false
- end
- local function getEnergyCapacity(reactor)
- local candidates = {
- "getEnergyCapacity",
- "getEnergyStoredMax",
- "getMaxEnergyStored",
- "getEnergyBufferSize",
- "getEnergyMax"
- }
- for _, m in ipairs(candidates) do
- if type(reactor[m]) == "function" then
- local ok, v = pcall(reactor[m])
- if ok and type(v) == "number" and v > 0 then
- return v, m
- end
- end
- end
- return nil, nil
- end
- local function findReactor()
- local candidates = {
- "BigReactors-Reactor",
- "ExtremeReactors-Reactor",
- "BiggerReactors_Reactor",
- "Reactor"
- }
- for _, t in ipairs(candidates) do
- local p = peripheral.find(t)
- if p then
- return p, t
- end
- end
- for _, name in ipairs(peripheral.getNames()) do
- local p = peripheral.wrap(name)
- if
- p and type(p.getEnergyStored) == "function" and type(p.setActive) == "function" and
- type(p.getNumberOfControlRods) == "function"
- then
- return p, peripheral.getType(name) or name
- end
- end
- return nil, nil
- end
- local function findMonitor()
- local m = peripheral.find("monitor")
- if m then
- pcall(
- function()
- m.setTextScale(CFG.monitorScale)
- end
- )
- end
- return m
- end
- local function setAllRods(reactor, level)
- local n = reactor.getNumberOfControlRods()
- for i = 0, n - 1 do
- reactor.setControlRodLevel(i, level)
- end
- end
- local function getAvgRodLevel(reactor)
- local n = reactor.getNumberOfControlRods()
- if n <= 0 then
- return 0
- end
- local sum = 0
- for i = 0, n - 1 do
- sum = sum + reactor.getControlRodLevel(i)
- end
- return sum / n
- end
- local function getReactorActive(reactor, fallback)
- local candidates = {"getActive", "getIsActive", "isActive"}
- for _, m in ipairs(candidates) do
- if type(reactor[m]) == "function" then
- local ok, v = pcall(reactor[m])
- if ok and type(v) == "boolean" then
- return v
- end
- end
- end
- return fallback
- end
- -------------------------
- -- Self-Update (Pastebin)
- -------------------------
- local PASTEBIN_ID = "VeAGySQm"
- local STARTUP_FILE = "startup"
- local function downloadPastebin(id)
- if not http or type(http.get) ~= "function" then
- return nil, "HTTP nicht verfügbar (in CC/Tweaked config HTTP aktivieren)."
- end
- local url = "https://pastebin.com/raw/" .. tostring(id)
- local h = http.get(url)
- if not h then
- return nil, "Download fehlgeschlagen (http.get nil). URL: " .. url
- end
- local data = h.readAll()
- h.close()
- if not data or data == "" then
- return nil, "Leerer Download von Pastebin (ID ok?)."
- end
- return data, nil
- end
- local function writeFile(path, content)
- local h = fs.open(path, "w")
- if not h then
- return false, "Kann Datei nicht öffnen: " .. tostring(path)
- end
- h.write(content)
- h.close()
- return true, nil
- end
- local function selfUpdate()
- -- Script holen, BEVOR wir startup anfassen (damit wir nicht ohne Datei dastehen)
- local newCode, err = downloadPastebin(PASTEBIN_ID)
- if not newCode then
- return false, "Update abgebrochen: " .. tostring(err)
- end
- -- alte startup löschen (wenn möglich)
- if fs.exists(STARTUP_FILE) then
- if fs.isDir(STARTUP_FILE) then
- return false, "Update abgebrochen: 'startup' ist ein Ordner?!"
- end
- pcall(
- function()
- fs.delete(STARTUP_FILE)
- end
- )
- end
- -- neue startup schreiben
- local ok, werr = writeFile(STARTUP_FILE, newCode)
- if not ok then
- return false, "Update fehlgeschlagen beim Schreiben: " .. tostring(werr)
- end
- return true, "Update OK: neue startup installiert."
- end
- -------------------------
- -- Persistenter Name
- -------------------------
- local NAME_FILE = "reactor_name.txt"
- local function loadReactorName(defaultName)
- if fs.exists(NAME_FILE) and not fs.isDir(NAME_FILE) then
- local h = fs.open(NAME_FILE, "r")
- local txt = h.readAll()
- h.close()
- txt = (txt and txt:gsub("^%s+", ""):gsub("%s+$", "")) or ""
- if txt ~= "" then
- return txt
- end
- end
- return defaultName
- end
- local function saveReactorName(name)
- local h = fs.open(NAME_FILE, "w")
- h.write(tostring(name or ""))
- h.close()
- end
- -------------------------
- -- WebSocket Client (Auto-Reconnect)
- -------------------------
- local ws = nil
- local wsLastErr = nil
- local function wsConnect()
- if not CFG.wsEnabled then
- return
- end
- if not http or type(http.websocket) ~= "function" then
- wsLastErr = "http.websocket nicht verfügbar (HTTP in CC config aktivieren)."
- return
- end
- if ws then
- return
- end
- local ok, connOrErr =
- pcall(
- function()
- return http.websocket(CFG.wsUrl)
- end
- )
- if ok and connOrErr then
- ws = connOrErr
- wsLastErr = nil
- else
- wsLastErr = tostring(connOrErr)
- ws = nil
- end
- end
- local function wsClose()
- if ws then
- pcall(
- function()
- ws.close()
- end
- )
- end
- ws = nil
- end
- local function wsSend(tbl)
- if not CFG.wsEnabled or not ws then
- return
- end
- local msg = textutils.serializeJSON(tbl)
- local ok =
- pcall(
- function()
- ws.send(msg)
- end
- )
- if not ok then
- wsClose()
- end
- end
- -------------------------
- -- UI
- -------------------------
- local UI = {}
- UI.tab = 1 -- 1=Reactor, 2=Status, 3=Temperatur, 4=Steuerung
- local HAS_COLOR = (term.isColor and term.isColor()) or false
- local function setBG(t, c) if HAS_COLOR and t.setBackgroundColor then t.setBackgroundColor(c) end end
- local function setFG(t, c) if HAS_COLOR and t.setTextColor then t.setTextColor(c) end end
- local function clampInt(x, a, b)
- if x < a then return a end
- if x > b then return b end
- return x
- end
- local function fill(t, x, y, w, h, ch, fg, bg)
- ch = ch or " "
- if bg then setBG(t, bg) end
- if fg then setFG(t, fg) end
- for yy = y, y + h - 1 do
- t.setCursorPos(x, yy)
- t.write(string.rep(ch, w))
- end
- end
- local function writeAt(t, x, y, s, fg, bg)
- if x < 1 or y < 1 then return end
- local w, h = t.getSize()
- if y > h then return end
- if x > w then return end
- if bg then setBG(t, bg) end
- if fg then setFG(t, fg) end
- t.setCursorPos(x, y)
- local maxLen = w - x + 1
- if maxLen <= 0 then return end
- if #s > maxLen then s = s:sub(1, maxLen) end
- t.write(s)
- end
- local function hr(t, y, fg, bg)
- local w = t.getSize()
- fill(t, 1, y, w, 1, " ", fg, bg)
- end
- local function bar(t, x, y, w, pct, label, colFill, colEmpty, colText, bg)
- pct = pct or 0
- if w < 6 then
- writeAt(t, x, y, tostring(math.floor(pct+0.5)) .. "%", colText, bg)
- return
- end
- local inner = math.max(1, w - 2)
- local filled = clampInt(math.floor((pct / 100) * inner + 0.5), 0, inner)
- writeAt(t, x, y, "[", colText, bg)
- writeAt(t, x + w - 1, y, "]", colText, bg)
- if filled > 0 then
- writeAt(t, x + 1, y, string.rep("=", filled), colFill, bg)
- end
- if inner - filled > 0 then
- writeAt(t, x + 1 + filled, y, string.rep("-", inner - filled), colEmpty, bg)
- end
- if label and label ~= "" then
- local txt = label
- if #txt > inner then txt = txt:sub(1, inner) end
- local lx = x + 1 + math.floor((inner - #txt) / 2)
- writeAt(t, lx, y, txt, colText, bg)
- end
- end
- local function pill(t, x, y, text, active, fgActive, bgActive, fgInactive, bgInactive)
- if active then
- writeAt(t, x, y, " " .. text .. " ", fgActive, bgActive)
- else
- writeAt(t, x, y, " " .. text .. " ", fgInactive, bgInactive)
- end
- return x + #text + 2
- end
- local function drawHeaderAndTabs(t, state)
- local w, h = t.getSize()
- local BG = HAS_COLOR and colors.black or nil
- local TOP = HAS_COLOR and colors.blue or BG
- local TXT = HAS_COLOR and colors.white or nil
- local MUTED = HAS_COLOR and colors.lightGray or nil
- fill(t, 1, 1, w, 1, " ", TXT, TOP)
- local title = (state.reactorName or "Reactor Control")
- local right = "V" .. tostring(state.version)
- local head = " " .. title
- if #head + #right + 2 <= w then
- head = head .. string.rep(" ", w - (#head + #right) - 1) .. right
- end
- writeAt(t, 1, 1, head, TXT, TOP)
- fill(t, 1, 2, w, 1, " ", TXT, BG)
- local x = 2
- local tabBG = HAS_COLOR and colors.gray or BG
- local tabFG = HAS_COLOR and colors.white or nil
- local offBG = BG
- local offFG = MUTED
- x = pill(t, x, 2, "1 Reactor", UI.tab == 1, tabFG, tabBG, offFG, offBG) + 1
- x = pill(t, x, 2, "2 Status", UI.tab == 2, tabFG, tabBG, offFG, offBG) + 1
- x = pill(t, x, 2, "3 Temperatur", UI.tab == 3, tabFG, tabBG, offFG, offBG) + 1
- x = pill(t, x, 2, "4 Steuerung", UI.tab == 4, tabFG, tabBG, offFG, offBG)
- hr(t, 3, TXT, HAS_COLOR and colors.gray or BG)
- return 4
- end
- local function drawFooter(t, state)
- local w, h = t.getSize()
- local BG = HAS_COLOR and colors.black or nil
- local FOOT = HAS_COLOR and colors.gray or BG
- local TXT = HAS_COLOR and colors.white or nil
- local MUTED = HAS_COLOR and colors.lightGray or nil
- fill(t, 1, h - 1, w, 2, " ", TXT, FOOT)
- writeAt(t, 2, h - 1, "Tabs: 1-4 | Q quit | S SCRAM | R rename | U update", TXT, FOOT)
- local hint = ("ID " .. tostring(os.getComputerID()) .. (os.getComputerLabel() and (" | " .. os.getComputerLabel()) or ""))
- writeAt(t, w - #hint - 1, h, hint, MUTED, FOOT)
- end
- local function pageReactor(t, state, x, y, w, h)
- local BG = HAS_COLOR and colors.black or nil
- local TXT = HAS_COLOR and colors.white or nil
- local MUTED = HAS_COLOR and colors.lightGray or nil
- local GOOD = HAS_COLOR and colors.lime or nil
- local WARN = HAS_COLOR and colors.orange or nil
- local BAD = HAS_COLOR and colors.red or nil
- local CYAN = HAS_COLOR and colors.cyan or nil
- local barW = math.max(10, w - 4)
- local bufferColor = (state.bufferPct >= 80) and GOOD or ((state.bufferPct >= 40) and WARN or BAD)
- local fuelColor = (state.fuelPct >= 10) and GOOD or ((state.fuelPct >= 4) and WARN or BAD)
- writeAt(t, x, y, "Energie & Fuel", CYAN, BG); y = y + 2
- bar(t, x, y, barW, state.bufferPct, "Buffer " .. state.bufferTxt, bufferColor, MUTED, TXT, BG); y = y + 2
- bar(t, x, y, barW, state.fuelPct, "Fuel " .. state.fuelTxt, fuelColor, MUTED, TXT, BG); y = y + 2
- writeAt(t, x, y, "RF/tick:", CYAN, BG)
- writeAt(t, x + 12, y, state.rfTxt, TXT, BG); y = y + 1
- writeAt(t, x, y, "Energy:", CYAN, BG)
- writeAt(t, x + 12, y, state.energyTxt, TXT, BG); y = y + 1
- if state.capMethod and state.capMethod ~= "" then
- writeAt(t, x, y, "CapMeth:", CYAN, BG)
- writeAt(t, x + 12, y, tostring(state.capMethod), MUTED, BG)
- end
- end
- local function pageStatus(t, state, x, y, w, h)
- local BG = HAS_COLOR and colors.black or nil
- local TXT = HAS_COLOR and colors.white or nil
- local MUTED = HAS_COLOR and colors.lightGray or nil
- local GOOD = HAS_COLOR and colors.lime or nil
- local WARN = HAS_COLOR and colors.orange or nil
- local BAD = HAS_COLOR and colors.red or nil
- local CYAN = HAS_COLOR and colors.cyan or nil
- local function badge(label, ok, yy, warnIfFalse)
- local c
- if ok then
- c = GOOD
- else
- c = warnIfFalse and BAD or WARN
- end
- local sym = ok and "[OK]" or "[..]"
- writeAt(t, x, yy, label, CYAN, BG)
- writeAt(t, x + 18, yy, sym, c, BG)
- end
- writeAt(t, x, y, "Systemstatus", CYAN, BG); y = y + 2
- badge("Reaktor Active", state.active, y); y = y + 1
- badge("RS Gate (15)", state.rsEnabled, y, true); y = y + 1
- local wsOK = (state.wsState == "connected")
- badge("WebSocket", wsOK, y); y = y + 1
- writeAt(t, x, y, "WS:", CYAN, BG)
- writeAt(t, x + 18, y, state.wsState, MUTED, BG); y = y + 2
- local statusColor = (state.status:find("SCRAM")) and BAD or (state.status == "OK" and GOOD or WARN)
- writeAt(t, x, y, "Controller:", CYAN, BG); y = y + 1
- writeAt(t, x, y, tostring(state.status), statusColor, BG)
- end
- local function pageTemps(t, state, x, y, w, h)
- local BG = HAS_COLOR and colors.black or nil
- local TXT = HAS_COLOR and colors.white or nil
- local GOOD = HAS_COLOR and colors.lime or nil
- local WARN = HAS_COLOR and colors.orange or nil
- local BAD = HAS_COLOR and colors.red or nil
- local CYAN = HAS_COLOR and colors.cyan or nil
- local function tempLine(label, value, max, yy)
- local c = (value <= max * 0.75) and GOOD or ((value <= max * 0.92) and WARN or BAD)
- writeAt(t, x, yy, label, CYAN, BG)
- writeAt(t, x + 18, yy, string.format("%4d C", value), c, BG)
- writeAt(t, x + 28, yy, ("(max " .. tostring(max) .. ")"), TXT, BG)
- end
- writeAt(t, x, y, "Temperatur", CYAN, BG); y = y + 2
- tempLine("Fuel Temp", state.fuelTemp, state.maxFuelTemp, y); y = y + 1
- tempLine("Casing Temp", state.casingTemp, state.maxCasingTemp, y); y = y + 2
- writeAt(t, x, y, "Hinweis: SCRAM bei Grenzwertüberschreitung.", TXT, BG)
- end
- local function pageControl(t, state, x, y, w, h)
- local BG = HAS_COLOR and colors.black or nil
- local TXT = HAS_COLOR and colors.white or nil
- local MUTED = HAS_COLOR and colors.lightGray or nil
- local GOOD = HAS_COLOR and colors.lime or nil
- local WARN = HAS_COLOR and colors.orange or nil
- local BAD = HAS_COLOR and colors.red or nil
- local CYAN = HAS_COLOR and colors.cyan or nil
- local barW = math.max(10, w - 4)
- local rodColor = (state.rod <= 20) and GOOD or ((state.rod <= 70) and WARN or BAD)
- writeAt(t, x, y, "Steuerung", CYAN, BG); y = y + 2
- bar(t, x, y, barW, state.rod, "Rod " .. state.rodTxt, rodColor, MUTED, TXT, BG); y = y + 2
- writeAt(t, x, y, "TargetBuffer:", CYAN, BG)
- writeAt(t, x + 18, y, tostring(state.targetBuffer) .. "%", TXT, BG); y = y + 1
- writeAt(t, x, y, "Hysterese:", CYAN, BG)
- writeAt(t, x + 18, y, tostring(state.hysteresis) .. "%", TXT, BG); y = y + 1
- writeAt(t, x, y, "Start/Stop:", CYAN, BG)
- writeAt(t, x + 18, y, tostring(state.startAt) .. "% / " .. tostring(state.stopAt) .. "%", TXT, BG); y = y + 2
- writeAt(t, x, y, "Rod: 0=raus, 100=rein", MUTED, BG)
- end
- function UI.render(t, state)
- local w, h = t.getSize()
- local BG = HAS_COLOR and colors.black or nil
- local TXT = HAS_COLOR and colors.white or nil
- setBG(t, BG); setFG(t, TXT)
- t.clear()
- local contentY = drawHeaderAndTabs(t, state)
- local top = contentY
- local bottom = h - 2
- local contentH = bottom - top + 1
- if contentH < 4 then
- writeAt(t, 1, top, "Monitor zu klein :(", TXT, BG)
- drawFooter(t, state)
- return
- end
- local padX = 2
- local x = padX
- local y = top + 1
- local cw = w - (padX * 2) + 1
- fill(t, 1, top, w, contentH, " ", TXT, BG)
- if UI.tab == 1 then
- pageReactor(t, state, x, y, cw, contentH)
- elseif UI.tab == 2 then
- pageStatus(t, state, x, y, cw, contentH)
- elseif UI.tab == 3 then
- pageTemps(t, state, x, y, cw, contentH)
- else
- pageControl(t, state, x, y, cw, contentH)
- end
- drawFooter(t, state)
- end
- -------------------------
- -- Hauptlogik
- -------------------------
- local reactor, rType = findReactor()
- if not reactor then
- print("Kein Reaktor-Peripheral gefunden.")
- print("Tipps:")
- print("- Computer direkt an den Reaktor stellen oder per Modem verbinden")
- print("- Prüfen: peripheral.getNames()")
- return
- end
- local monitor = CFG.useMonitor and findMonitor() or nil
- local reactorName = loadReactorName("Reactor")
- if reactorName == "Reactor" then
- reactorName = loadReactorName("Reactor Control")
- end
- local scrammed = false
- local lastRod = nil
- local tickCounter = 0
- local function scram(reason)
- scrammed = true
- pcall(
- function()
- reactor.setActive(false)
- end
- )
- pcall(
- function()
- setAllRods(reactor, 100)
- end
- )
- return reason or "SCRAM"
- end
- local function controlStep()
- local active = getReactorActive(reactor, lastActiveKnown)
- lastActiveKnown = active
- local eStored =
- safeCall(
- function()
- return reactor.getEnergyStored()
- end,
- 0
- )
- local eMax, capMethod = getEnergyCapacity(reactor)
- local bufferPct
- if not eMax then
- bufferPct = 0
- else
- bufferPct = (eStored / eMax) * 100
- end
- bufferPct = clamp(bufferPct, 0, 100)
- local fuelAmt =
- safeCall(
- function()
- return reactor.getFuelAmount()
- end,
- 0
- )
- local fuelMax =
- safeCall(
- function()
- return reactor.getFuelAmountMax()
- end,
- 1
- )
- local fuelPct = (fuelAmt / math.max(fuelMax, 1)) * 100
- local fuelTemp =
- safeCall(
- function()
- return reactor.getFuelTemperature()
- end,
- 0
- )
- local casingTemp =
- safeCall(
- function()
- return reactor.getCasingTemperature()
- end,
- 0
- )
- local rfTick =
- safeCall(
- function()
- return reactor.getEnergyProducedLastTick()
- end,
- 0
- )
- local rodAvg =
- safeCall(
- function()
- return getAvgRodLevel(reactor)
- end,
- 0
- )
- -- Safety
- if fuelPct < CFG.minFuelPercent then
- return bufferPct, fuelPct, fuelTemp, casingTemp, rfTick, rodAvg, active, scram("SCRAM: Fuel zu niedrig"), eStored, eMax, capMethod
- end
- if fuelTemp > CFG.maxFuelTemp then
- return bufferPct, fuelPct, fuelTemp, casingTemp, rfTick, rodAvg, active, scram("SCRAM: FuelTemp zu hoch"), eStored, eMax, capMethod
- end
- if casingTemp > CFG.maxCasingTemp then
- return bufferPct, fuelPct, fuelTemp, casingTemp, rfTick, rodAvg, active, scram("SCRAM: CasingTemp zu hoch"), eStored, eMax, capMethod
- end
- scrammed = false
- -- RS Gate: nur wenn analog 15 an top oder bottom anliegt
- local enabled = rsIsEnabled()
- if not enabled then
- pcall(function() reactor.setActive(false) end)
- active = false
- lastActiveKnown = false
- if CFG.rsGateScramRods then
- pcall(function() setAllRods(reactor, 100) end)
- lastRod = 100
- end
- return bufferPct, fuelPct, fuelTemp, casingTemp, rfTick, rodAvg, active, "OFF (kein RS 15 top/bottom)", eStored, eMax, capMethod
- end
- -- Start/Stop
- if bufferPct <= CFG.startAt and not active then
- pcall(
- function()
- reactor.setActive(true)
- end
- )
- active = true
- lastActiveKnown = true
- elseif bufferPct >= CFG.stopAt then
- pcall(
- function()
- reactor.setActive(false)
- end
- )
- active = false
- lastActiveKnown = false
- end
- if not active then
- return bufferPct, fuelPct, fuelTemp, casingTemp, rfTick, rodAvg, active, "OFF (Puffer hoch genug)", eStored, eMax, capMethod
- end
- -- Hysterese
- local low = CFG.targetBuffer - CFG.hysteresis
- local high = CFG.targetBuffer + CFG.hysteresis
- local newRod = rodAvg
- if bufferPct < low then
- local err = (low - bufferPct)
- local step = clamp(math.floor(err * 0.6) + 1, 1, 10)
- newRod = rodAvg - step
- elseif bufferPct > high then
- local err = (bufferPct - high)
- local step = clamp(math.floor(err * 0.6) + 1, 1, 10)
- newRod = rodAvg + step
- end
- newRod = clamp(newRod, CFG.minRod, CFG.maxRod)
- if lastRod == nil or math.abs(newRod - lastRod) >= 1 then
- pcall(
- function()
- setAllRods(reactor, newRod)
- end
- )
- lastRod = newRod
- end
- return bufferPct, fuelPct, fuelTemp, casingTemp, rfTick, newRod, active, "OK", eStored, eMax, capMethod
- end
- -- UI Loop
- local function uiLoop()
- while true do
- tickCounter = tickCounter + 1
- if CFG.wsEnabled and not ws then
- wsConnect()
- end
- local bufferPct, fuelPct, fuelTemp, casingTemp, rfTick, rod, active, status, eStored, eMax, capMethod =
- controlStep()
- if CFG.wsEnabled and ws and (tickCounter % math.max(CFG.wsSendEveryTicks, 1) == 0) then
- wsSend(
- {
- type = "reactor_telemetry_single",
- computerId = os.getComputerID(),
- label = os.getComputerLabel(),
- reactorName = reactorName,
- reactorType = rType,
- timeUtcMs = (os.epoch and os.epoch("utc")) or nil,
- active = active,
- status = status,
- bufferPct = bufferPct,
- fuelPct = fuelPct,
- fuelTemp = fuelTemp,
- casingTemp = casingTemp,
- rod = rod,
- rfTick = rfTick,
- energyStored = eStored,
- energyMax = eMax,
- energyCapMethod = capMethod
- }
- )
- end
- local state = {
- version = version,
- reactorName = reactorName,
- active = active,
- status = tostring(status),
- rsEnabled = rsIsEnabled(),
- bufferPct = bufferPct,
- fuelPct = fuelPct,
- fuelTemp = round(fuelTemp),
- casingTemp = round(casingTemp),
- rod = round(rod),
- rfTick = round(rfTick),
- energyStored = eStored,
- energyMax = eMax,
- capMethod = capMethod,
- targetBuffer = CFG.targetBuffer,
- startAt = CFG.startAt,
- stopAt = CFG.stopAt,
- maxFuelTemp = CFG.maxFuelTemp,
- maxCasingTemp = CFG.maxCasingTemp,
- bufferTxt = fmtPercent(bufferPct),
- fuelTxt = fmtPercent(fuelPct),
- rodTxt = tostring(round(rod)) .. "%",
- rfTxt = tostring(round(rfTick)),
- energyTxt = (eMax and (tostring(math.floor(eStored)) .. "/" .. tostring(math.floor(eMax))) or tostring(math.floor(eStored))),
- wsState = (CFG.wsEnabled and (ws and "connected" or "down") or "disabled"),
- hysteresis = CFG.hysteresis,
- }
- UI.render(term, state)
- if monitor then UI.render(monitor, state) end
- local timer = os.startTimer(CFG.tickSeconds)
- while true do
- local ev, p1 = os.pullEvent()
- if ev == "timer" and p1 == timer then
- break
- elseif ev == "websocket_closed" or ev == "websocket_failure" then
- wsClose()
- wsLastErr = (ev == "websocket_failure") and tostring(p1) or "websocket_closed"
- elseif ev == "char" then
- local c = string.lower(p1)
- if c == "\t" then
- UI.tab = (UI.tab % 4) + 1
- elseif c == "1" then UI.tab = 1
- elseif c == "2" then UI.tab = 2
- elseif c == "3" then UI.tab = 3
- elseif c == "4" then UI.tab = 4
- elseif c == "q" then
- term.setCursorPos(1, 1)
- term.clear()
- print("Beendet.")
- wsClose()
- return
- elseif c == "s" then
- scram("SCRAM: Manuell")
- elseif c == "r" then
- term.setCursorPos(1, 1)
- term.clear()
- if monitor then
- monitor.setCursorPos(1, 1)
- monitor.clear()
- end
- print("Neuer Reaktor-Name (leer = abbrechen):")
- write("> ")
- local newName = read()
- newName = (newName and newName:gsub("^%s+", ""):gsub("%s+$", "")) or ""
- if newName ~= "" then
- reactorName = newName
- saveReactorName(reactorName)
- end
- elseif c == "u" then
- term.setCursorPos(1, 1)
- term.clear()
- if monitor then
- monitor.setCursorPos(1, 1)
- monitor.clear()
- end
- print("Update wird geladen (Pastebin: " .. tostring(PASTEBIN_ID) .. ") ...")
- local ok, msg = selfUpdate()
- print(msg)
- if ok then
- print("Neustart...")
- wsClose()
- os.sleep(1)
- os.reboot()
- else
- print("Beliebige Taste zum Fortfahren...")
- os.pullEvent("char")
- end
- end
- end
- end
- end
- end
- uiLoop()
Advertisement
Add Comment
Please, Sign In to add comment