Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Datei: orchestrator.lua
- -- Hauptsteuerung für mehrere Turbinen (standardisierte API für alle Modvarianten)
- -- Laden aller benötigten Programmdateien
- -- Loading of all neccessary programfiles
- local turbine = require("turbine")
- local state = require("state")
- local gui = require("gui")
- local language = require("language")
- local settings = state.settings
- local langKey = state.langKey
- local rebootRequested = false
- state.turbines = turbine.getTurbines()
- for id, t in ipairs(state.turbines) do
- state.turbineInfos[id] = turbine.getTurbineInfo(t)
- state.lastRotorSpeed[id] = state.turbineInfos[id].rotorSpeed
- print(state.turbineInfos[id].rotorSpeed)
- state.bladeEfficiencyFlow[id] = state.turbineInfos[id].numberOfBlades * settings.mBPerBlade
- state.turbineDiagnosis[id] = { coilFault = false, lastFaultTime = 0, multiBlockFault = false, energyLimitReached = false }
- state.rpmDelta[id] = state.turbineInfos[id].rotorSpeed - state.lastRotorSpeed[id]
- end
- -- ==== LOGIKFUNKTION ZUR TURBINENBEWERTUNG ==================================
- local function evaluate(id)
- local action = {
- shouldActivate = state.turbineInfos[id].active,
- inductorStatus = state.turbineInfos[id].inductorEngaged,
- flowRate = state.turbineInfos[id].fluidFlowRateMax,
- }
- local turbine = state.turbineInfos[id]
- local turbineDiagnosis = state.turbineDiagnosis[id]
- local rpmIsFalling = state.rpmDelta[id] < 0.7
- local rpmIsRising = state.rpmDelta[id] > 0.7
- local rotorInertia = math.min(math.max(1.0, turbine.rotorMass / settings.referenceMass), 4.0)
- local rotorThresholdInduction = (settings.referenceRPMThreshold1 / rotorInertia) * (1800 / settings.rotorMaxSpeed)
- local rotorThresholdFar = (settings.referenceRPMThreshold2 / rotorInertia) * (1800 / settings.rotorMaxSpeed)
- local rotorThresholdClose = (settings.referenceRPMThreshold3 / rotorInertia) * (1800 / settings.rotorMaxSpeed)
- -- Rekonfiguration bei unvollständigem Multiblock
- if not turbine.assembled then
- action.shouldActivate = false
- action.inductorStatus = false
- action.flowRate = 0
- end
- -- Diagnose: Zu viele Coils? Volle Flowrate, trotzdem keine RPM-Zielerreichung?
- if turbine.rotorSpeed < settings.rotorMaxSpeed - rotorThresholdInduction and turbine.inductorEngaged then
- turbineDiagnosis.lastFaultTime = state.unixTime
- turbineDiagnosis.coilFault = true
- elseif not turbine.assembled then
- turbineDiagnosis.lastFaultTime = state.unixTime
- turbineDiagnosis.multiBlockFault = true
- elseif turbine.energyStored >= turbine.energyCapacity * settings.energyStopThreshold then
- turbineDiagnosis.lastFaultTime = state.unixTime
- turbineDiagnosis.energyLimitReached = true
- elseif state.unixTime - turbineDiagnosis.lastFaultTime ~= 0 and state.unixTime - turbineDiagnosis.lastFaultTime > settings.errorResetTime then
- turbineDiagnosis.lastFaultTime = 0
- turbineDiagnosis.coilFault = false
- turbineDiagnosis.multiBlockFault = false
- turbineDiagnosis.energyLimitReached = false
- end
- if turbine.energyStored >= turbine.energyCapacity * settings.energyStopThreshold and settings.energyForceStop then
- action.shouldActivate = false
- action.inductorStatus = false
- elseif turbine.energyStored <= turbine.energyCapacity * settings.energyStartThreshold and settings.energyForceStart then
- action.shouldActivate = true
- end
- if turbine.active and action.shouldActivate then
- if action.inductorStatus and turbine.rotorSpeed < settings.rotorMaxSpeed - rotorThresholdInduction then
- action.inductorStatus = false
- elseif not action.inductorStatus and turbine.rotorSpeed > settings.rotorMaxSpeed - rotorThresholdInduction then
- action.inductorStatus = true
- end
- end
- if turbine.active then
- if turbine.rotorSpeed == 0 then
- action.flowRate = state.bladeEfficiencyFlow[id]
- elseif turbine.rotorSpeed <= settings.rotorMaxSpeed - rotorThresholdFar then
- if rpmIsRising then
- if state.rpmDelta[id] > 48 / rotorInertia then
- action.flowRate = turbine.fluidFlowRate - 25
- elseif state.rpmDelta[id] < 16 / rotorInertia then
- if action.flowRate < state.bladeEfficiencyFlow[id] then
- action.flowRate = math.min(turbine.fluidFlowRate + (25 * rotorInertia), state.bladeEfficiencyFlow[id])
- elseif not settings.flowEfficiencyLimit then
- action.flowRate = turbine.fluidFlowRate + (25 * rotorInertia)
- end
- end
- elseif rpmIsFalling then
- if action.flowRate < state.bladeEfficiencyFlow[id] then
- action.flowRate = math.min(turbine.fluidFlowRate + 100, state.bladeEfficiencyFlow[id])
- elseif not settings.flowEfficiencyLimit then
- action.flowRate = turbine.fluidFlowRate + 100
- end
- elseif action.flowRate < state.bladeEfficiencyFlow[id] then
- action.flowRate = math.min(turbine.fluidFlowRate + 25, state.bladeEfficiencyFlow[id])
- elseif not settings.flowEfficiencyLimit then
- action.flowRate = turbine.fluidFlowRate + 25
- end
- --
- elseif turbine.rotorSpeed <= settings.rotorMaxSpeed - rotorThresholdClose then
- if rpmIsRising then
- if state.rpmDelta[id] > 12 / rotorInertia then
- action.flowRate = turbine.fluidFlowRate - 10
- elseif state.rpmDelta[id] < 4 / rotorInertia then
- if action.flowRate < state.bladeEfficiencyFlow[id] then
- action.flowRate = math.min(turbine.fluidFlowRate + 10, state.bladeEfficiencyFlow[id])
- elseif not settings.flowEfficiencyLimit then
- action.flowRate = turbine.fluidFlowRate + 10
- end
- end
- elseif rpmIsFalling then
- if action.flowRate < state.bladeEfficiencyFlow[id] then
- action.flowRate = math.min(turbine.fluidFlowRate + 50, state.bladeEfficiencyFlow[id])
- elseif not settings.flowEfficiencyLimit then
- action.flowRate = turbine.fluidFlowRate + 50
- end
- elseif action.flowRate < state.bladeEfficiencyFlow[id] then
- action.flowRate = math.min(turbine.fluidFlowRate + 25, state.bladeEfficiencyFlow[id])
- elseif not settings.flowEfficiencyLimit then
- action.flowRate = turbine.fluidFlowRate + 25
- end
- --
- elseif turbine.rotorSpeed > settings.rotorMaxSpeed - rotorThresholdClose and turbine.rotorSpeed < settings.rotorMaxSpeed + rotorThresholdClose then
- if rpmIsRising and state.rpmDelta[id] >= 2 / rotorInertia then
- action.flowRate = turbine.fluidFlowRate - 5
- elseif rpmIsFalling and state.rpmDelta[id] >= 2 / rotorInertia then
- if action.flowRate < state.bladeEfficiencyFlow[id] then
- action.flowRate = math.min(turbine.fluidFlowRate + 5, state.bladeEfficiencyFlow[id])
- elseif not settings.flowEfficiencyLimit then
- action.flowRate = turbine.fluidFlowRate + 5
- end
- end
- elseif turbine.rotorSpeed >= settings.rotorMaxSpeed + rotorThresholdClose and turbine.rotorSpeed < 2000 then
- if rpmIsRising then
- action.flowRate = turbine.fluidFlowRate - 50
- else
- action.flowRate = turbine.fluidFlowRate - 10
- end
- elseif turbine.rotorSpeed >= 2000 then
- action.flowRate = 0
- end
- end
- return action
- end
- -- ==== TURBINENSTEUERUNG ====================================================
- local function turbineControlLoop()
- while true do
- if rebootRequested then return end
- state.unixTime = os.time(os.date("*t"))
- if state.turbineEvaluateCount >= 1 then
- state.turbineEvaluateCount = 0
- gui.initTerminal()
- for id, t in ipairs(state.turbines) do
- local info = turbine.getTurbineInfo(t)
- -- Aktualisierung der Turbinen Infowerte / Update turbine info values
- state.turbineInfos[id] = turbine.getTurbineInfo(t)
- state.rpmDelta[id] = state.turbineInfos[id].rotorSpeed - state.lastRotorSpeed[id]
- -- Funktionsaufruf zur Berechnung aktueller Turbinenaktionen / Evaluate turbine actions
- local action = evaluate(id)
- -- Speicherung der Turbinengeschwindigkeit als Referenzwert / Save rotor speed
- state.lastRotorSpeed[id] = state.turbineInfos[id].rotorSpeed
- -- Ausführung der Turbinen Steueraktionen / Execute turbine control
- turbine.setActive(t, action.shouldActivate)
- turbine.setInductorEngaged(t, action.inductorStatus)
- turbine.setFluidFlowRateMax(t, action.flowRate)
- end
- else
- state.turbineEvaluateCount = state.turbineEvaluateCount + settings.updateInterval
- end
- -- Aktuelle Zeit und RF-Produktion seit letztem Update / Current time and RF production
- local rfSum = 0
- local steamSum = 0
- for _, t in ipairs(state.turbines) do
- rfSum = rfSum + (t.getEnergyProducedLastTick() or 0)
- steamSum = steamSum + (t.getFluidFlowRate() or 0)
- end
- -- RF/tick * 20 = RF/s bei normalem Takt / RF per second
- local interval = settings.updateInterval or 1
- local rfEstimated = math.floor(rfSum * 20)
- local steamEstimated = math.floor(steamSum * 20)
- -- In Verlauf einfügen / Insert into history
- table.insert(state.rfProduction.history, 1, {
- time = state.unixTime,
- rf = rfEstimated,
- steam = steamEstimated
- })
- -- Verlauf auf 1 Stunde begrenzen / Limit to 1 hour
- local cutoff = state.unixTime - 3600
- while #state.rfProduction.history > 0 and state.rfProduction.history[#state.rfProduction.history].time < cutoff do
- table.remove(state.rfProduction.history)
- end
- gui.renderPage()
- os.sleep(settings.updateInterval)
- end
- end
- -- Tastatur-Reset, Monitor-Touch und Resize-Handler bleiben unverändert --
- local function keyListenerLoop()
- while true do
- local event, key = os.pullEvent("key")
- if key == 211 then
- rebootRequested = true
- return
- end
- end
- end
- local function handleTouchInput()
- while true do
- if rebootRequested then return end
- local event, side, x, y = os.pullEvent("monitor_touch")
- local width, height = gui.getMonitorSize()
- if settings.debugTouch == 1 or settings.debug == 1 then
- print("x=" .. x .. " and y=" .. y)
- end
- if x < 7 and y < 6 then
- gui.setSpecialPage("options")
- elseif x >= 2 and x <= 6 and y >= height - 3 then
- gui.setPage(gui.currentPage - 1)
- elseif x >= width - 5 and x <= width - 1 and y >= height - 3 then
- gui.setPage(gui.currentPage + 1)
- elseif x >= 8 and x <= math.floor(width / 2) - 1 and y >= height - 3 then
- gui.setPage(1)
- elseif x >= math.ceil(width / 2) + 2 and x <= width - 6 and y >= height - 3 then
- gui.setSpecialPage("system")
- end
- end
- end
- local function handleMonitorResize()
- while true do
- if rebootRequested then return end
- local event, side = os.pullEvent("monitor_resize")
- if side == peripheral.getName(peripheral.find("monitor")) then
- gui.debugPrint("Monitorgröße geändert – GUI wird neu initialisiert.")
- gui.initMonitor()
- gui.initSystemWindows()
- gui.initInfoWindows()
- gui.renderPage()
- end
- end
- end
- -- ==== Programm Start ================================================================
- gui.initMonitor()
- gui.initTerminal()
- gui.initSystemWindows()
- gui.initInfoWindows()
- gui.initInfoWindowsMaxLength()
- parallel.waitForAny(
- turbineControlLoop,
- keyListenerLoop,
- handleTouchInput,
- handleMonitorResize
- )
- if rebootRequested then
- print(language.data[langKey].orchestrator.restartInfo)
- gui.rebootScreen(language.data[langKey].orchestrator.restartInfo)
- os.sleep(1)
- os.reboot()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement