fix: use NBT ETA and clean monitor debug output
This commit is contained in:
+51
-126
@@ -2,7 +2,7 @@
|
||||
-- ============================================================================
|
||||
-- 1. Configuration & Constants
|
||||
-- ============================================================================
|
||||
local APP_VERSION_TEXT = "v1.0.34"
|
||||
local APP_VERSION_TEXT = "v1.0.35"
|
||||
|
||||
local CONFIG = {
|
||||
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
||||
@@ -51,7 +51,6 @@ local State = {
|
||||
currentPlaying = nil,
|
||||
currentPriority = -1,
|
||||
interruptSeq = 0,
|
||||
debugUpcoming = nil,
|
||||
tickRate = 20
|
||||
}
|
||||
|
||||
@@ -2135,65 +2134,6 @@ function Display.render()
|
||||
mon.setTextColor(COLORS.DEBUG)
|
||||
mon.setCursorPos(1, upcomingStartY)
|
||||
mon.write("UPCOMING TRAINS:")
|
||||
if CONFIG.DEBUG and State.debugUpcoming and upcomingStartY + 1 <= h then
|
||||
mon.setCursorPos(1, upcomingStartY + 1)
|
||||
mon.setTextColor(COLORS.DEBUG)
|
||||
local dbg = State.debugUpcoming
|
||||
local dbgLine = string.format(
|
||||
"SRC BR:%s CT:%s OK:%s TS:%s TPS:%s",
|
||||
dbg.hasBR and "Y" or "N",
|
||||
dbg.hasCT and "Y" or "N",
|
||||
dbg.ok and "Y" or "N",
|
||||
tostring(dbg.trainStopsCount or 0),
|
||||
tostring(math.floor((dbg.tickRate or 20) * 10) / 10)
|
||||
)
|
||||
if #dbgLine > w then dbgLine = dbgLine:sub(1, w) end
|
||||
mon.write(dbgLine)
|
||||
if upcomingStartY + 2 <= h then
|
||||
mon.setCursorPos(1, upcomingStartY + 2)
|
||||
local keyLine = string.format(
|
||||
"TK:%s NK:%s",
|
||||
tostring(dbg.textKey or "-"),
|
||||
tostring(dbg.nbtKey or "-")
|
||||
)
|
||||
if #keyLine > w then keyLine = keyLine:sub(1, w) end
|
||||
mon.write(keyLine)
|
||||
end
|
||||
if upcomingStartY + 3 <= h then
|
||||
mon.setCursorPos(1, upcomingStartY + 3)
|
||||
local etaLine = string.format(
|
||||
"TXT:%s NBT:%s USE:%s",
|
||||
tostring(dbg.textEta or "-"),
|
||||
tostring(dbg.nbtEta or "-"),
|
||||
tostring(dbg.usedEta or "-")
|
||||
)
|
||||
if #etaLine > w then etaLine = etaLine:sub(1, w) end
|
||||
mon.write(etaLine)
|
||||
end
|
||||
if upcomingStartY + 4 <= h then
|
||||
mon.setCursorPos(1, upcomingStartY + 4)
|
||||
local rawLine = "ETASTR:" .. tostring(dbg.textEtaRaw or "-")
|
||||
if #rawLine > w then rawLine = rawLine:sub(1, w) end
|
||||
mon.write(rawLine)
|
||||
end
|
||||
if upcomingStartY + 5 <= h then
|
||||
mon.setCursorPos(1, upcomingStartY + 5)
|
||||
local partsLine = string.format(
|
||||
"VAL:%s UNIT:%s",
|
||||
tostring(dbg.textEtaValue or "-"),
|
||||
tostring(dbg.textEtaUnit or "-")
|
||||
)
|
||||
if #partsLine > w then partsLine = partsLine:sub(1, w) end
|
||||
mon.write(partsLine)
|
||||
end
|
||||
if upcomingStartY + 6 <= h then
|
||||
mon.setCursorPos(1, upcomingStartY + 6)
|
||||
local lineRaw = "RAW:" .. tostring(dbg.rawLine or "-")
|
||||
if #lineRaw > w then lineRaw = lineRaw:sub(1, w) end
|
||||
mon.write(lineRaw)
|
||||
end
|
||||
logsStartY = upcomingStartY + 7
|
||||
end
|
||||
if hasUpcoming then
|
||||
mon.setTextColor(COLORS.INFO)
|
||||
local visibleCount = math.min(3, #State.upcomingTrains, math.max(0, maxUpcomingRows - 1))
|
||||
@@ -2213,7 +2153,8 @@ function Display.render()
|
||||
if t.platform and tostring(t.platform) ~= "" then
|
||||
pfx = "P" .. tostring(t.platform) .. " "
|
||||
end
|
||||
local lineText = string.format("%s%s->%s ETA:%ds%s", pfx, t.trainName, t.dest, t.eta, suffix)
|
||||
local etaLabel = tostring(t.etaLabel or (tostring(t.eta or 0) .. "s"))
|
||||
local lineText = string.format("%s%s->%s ETA:%s%s", pfx, t.trainName, t.dest, etaLabel, suffix)
|
||||
if #lineText > w then lineText = lineText:sub(1, w) end
|
||||
mon.write(lineText)
|
||||
end
|
||||
@@ -2221,7 +2162,6 @@ function Display.render()
|
||||
else
|
||||
mon.setTextColor(COLORS.WARNING)
|
||||
local msgY = upcomingStartY + 1
|
||||
if CONFIG.DEBUG and State.debugUpcoming then msgY = upcomingStartY + 2 end
|
||||
if msgY <= h then
|
||||
mon.setCursorPos(1, msgY)
|
||||
mon.write("NONE / WAITING DATA")
|
||||
@@ -2436,38 +2376,52 @@ local function pickEarlierTick(a, b)
|
||||
return ta or tb or 0
|
||||
end
|
||||
|
||||
local function buildEtaLabel(etaSeconds, textEta)
|
||||
if type(textEta) == "table" then
|
||||
local value = tonumber(textEta.value)
|
||||
local unit = tostring(textEta.unit or "")
|
||||
if value and unit == "??" and value <= 10 then
|
||||
return "~" .. tostring(value) .. "m"
|
||||
end
|
||||
end
|
||||
return tostring(math.max(0, tonumber(etaSeconds) or 0)) .. "s"
|
||||
end
|
||||
|
||||
local function mapTrainStatusReason(statusId)
|
||||
local key = tostring(statusId or "")
|
||||
if key == "" then
|
||||
return nil
|
||||
end
|
||||
local tail = string.match(key, ":(.+)$") or key
|
||||
local known = {
|
||||
delay_from_previous_journey = "prev",
|
||||
previous_train_delayed = "train",
|
||||
priority_other_train = "prio",
|
||||
red_signal = "signal",
|
||||
track_closed = "track",
|
||||
staff_shortage = "staff",
|
||||
operational_disruption = "ops",
|
||||
special_journey = "special",
|
||||
out_of_service = "oos",
|
||||
default_delay = "delay",
|
||||
cancelled = "cancel"
|
||||
}
|
||||
return known[tail] or tail
|
||||
end
|
||||
|
||||
function Main.loop()
|
||||
while true do
|
||||
local now = os.epoch("utc")
|
||||
local newUpcoming = {}
|
||||
local etaByText = {}
|
||||
local dbg = {
|
||||
hasBR = Peripherals.blockReader ~= nil,
|
||||
hasCT = Peripherals.createTarget ~= nil,
|
||||
ok = false,
|
||||
trainStopsCount = 0,
|
||||
tickRate = State.tickRate or 20,
|
||||
rawLine = nil,
|
||||
textKey = nil,
|
||||
textEtaRaw = nil,
|
||||
textEtaValue = nil,
|
||||
textEtaUnit = nil,
|
||||
nbtKey = nil,
|
||||
textEta = nil,
|
||||
nbtEta = nil,
|
||||
usedEta = nil
|
||||
}
|
||||
local etaTextByKey = {}
|
||||
|
||||
-- Prefer CRN's own ETA display text (create_target) when available.
|
||||
-- This avoids drift when TPS fluctuates, while still using NBT for delay/status.
|
||||
-- Read CRN text ETA only for display wording.
|
||||
-- Timing decisions and numeric ETA still come from NBT.
|
||||
if Peripherals.createTarget then
|
||||
local okLines, lines = pcall(Peripherals.createTarget.dump)
|
||||
if okLines and type(lines) == "table" then
|
||||
for _, lineText in pairs(lines) do
|
||||
if lineText and lineText ~= "" and lineText:match("[%w%?%[]") then
|
||||
if not dbg.rawLine then
|
||||
dbg.rawLine = lineText
|
||||
end
|
||||
local cleanLine = string.gsub(lineText, "%s*%(?%+%s*%d+.-%)?", "")
|
||||
local etaValue, etaUnit, tName, dest
|
||||
etaValue, etaUnit, tName, dest = string.match(cleanLine, "^(%S+)%s+(.-)%s+(%[.-%][^%s]*)%s+(.*)$")
|
||||
@@ -2475,21 +2429,13 @@ function Main.loop()
|
||||
etaValue, etaUnit, tName, dest = string.match(cleanLine, "^([^%s]+)%s+(.-)%s+([^%s]+)%s+(.*)$")
|
||||
end
|
||||
if tName and etaValue then
|
||||
local etaStr = tostring(etaValue or "")
|
||||
if etaUnit and etaUnit ~= "" then
|
||||
etaStr = etaStr .. " " .. tostring(etaUnit)
|
||||
end
|
||||
local etaSeconds = parseEtaText(etaStr)
|
||||
if dest then
|
||||
local textKey = normalizeUpcomingKey(tName, dest)
|
||||
etaByText[textKey] = etaSeconds
|
||||
if not dbg.textKey then
|
||||
dbg.textKey = textKey
|
||||
dbg.textEtaRaw = etaStr
|
||||
dbg.textEtaValue = etaValue
|
||||
dbg.textEtaUnit = etaUnit
|
||||
dbg.textEta = etaSeconds
|
||||
end
|
||||
etaTextByKey[textKey] = {
|
||||
value = etaValue,
|
||||
unit = etaUnit,
|
||||
raw = tostring(etaValue or "") .. ((etaUnit and etaUnit ~= "") and (" " .. tostring(etaUnit)) or "")
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2500,14 +2446,7 @@ function Main.loop()
|
||||
-- Check Block Reader (Advanced Peripherals) first for precise ETA and Delay
|
||||
if Peripherals.blockReader then
|
||||
local ok, data = pcall(Peripherals.blockReader.getBlockData)
|
||||
dbg.ok = ok and true or false
|
||||
if ok and data and data.TrainStops then
|
||||
local c = 0
|
||||
for _ in ipairs(data.TrainStops) do c = c + 1 end
|
||||
if c == 0 then
|
||||
for _ in pairs(data.TrainStops) do c = c + 1 end
|
||||
end
|
||||
dbg.trainStopsCount = c
|
||||
-- Real-time interpolation: estimate actual tick rate (TPS) from CRN refreshes
|
||||
if not State.lastRefreshed or State.lastRefreshed ~= data.LastRefreshed then
|
||||
if State.lastRefreshed and State.lastRefreshedEpoch then
|
||||
@@ -2523,7 +2462,6 @@ function Main.loop()
|
||||
State.lastRefreshed = data.LastRefreshed
|
||||
State.lastRefreshedEpoch = now
|
||||
end
|
||||
dbg.tickRate = State.tickRate or 20
|
||||
|
||||
local elapsedSeconds = (now - (State.lastRefreshedEpoch or now)) / 1000
|
||||
local currentTick = (data.LastRefreshed or 0) + math.floor(elapsedSeconds * (State.tickRate or 20))
|
||||
@@ -2552,14 +2490,7 @@ function Main.loop()
|
||||
if type(status) == "table" then
|
||||
for _, s in ipairs(status) do
|
||||
if type(s) == "string" then
|
||||
if string.find(s, "delay_from_previous_journey", 1, true) then
|
||||
reason = "prev"
|
||||
elseif string.find(s, "cancel", 1, true) then
|
||||
reason = "cancel"
|
||||
else
|
||||
local tail = string.match(s, ":(.+)$")
|
||||
reason = tail or s
|
||||
end
|
||||
reason = mapTrainStatusReason(s) or reason
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2575,17 +2506,7 @@ function Main.loop()
|
||||
local etaSeconds = math.floor(etaTicks / (State.tickRate or 20))
|
||||
if etaSeconds < 0 then etaSeconds = 0 end
|
||||
local announceKey = normalizeUpcomingKey(trainName, destination)
|
||||
if not dbg.nbtKey then
|
||||
dbg.nbtKey = announceKey
|
||||
dbg.nbtEta = etaSeconds
|
||||
end
|
||||
local textEta = etaByText[announceKey]
|
||||
if type(textEta) == "number" and textEta >= 0 then
|
||||
etaSeconds = textEta
|
||||
end
|
||||
if not dbg.usedEta then
|
||||
dbg.usedEta = etaSeconds
|
||||
end
|
||||
local etaLabel = buildEtaLabel(etaSeconds, etaTextByKey[announceKey])
|
||||
|
||||
-- Calculate Delay in minutes
|
||||
local delayTicks = realArrival - scheduledArrival
|
||||
@@ -2597,6 +2518,7 @@ function Main.loop()
|
||||
dest = destination,
|
||||
platform = platform,
|
||||
eta = etaSeconds,
|
||||
etaLabel = etaLabel,
|
||||
delay = delayMinutes,
|
||||
cancelled = cancelled,
|
||||
reason = reason
|
||||
@@ -2678,6 +2600,10 @@ function Main.loop()
|
||||
dest = dest,
|
||||
platform = platform or State.stationPlatform or "1",
|
||||
eta = etaSeconds >= 0 and etaSeconds or 0,
|
||||
etaLabel = buildEtaLabel(etaSeconds >= 0 and etaSeconds or 0, {
|
||||
value = string.match(etaStr, "(%d+)"),
|
||||
unit = string.match(etaStr, "%d+%s*(.*)")
|
||||
}),
|
||||
delay = delay,
|
||||
cancelled = false,
|
||||
reason = nil
|
||||
@@ -2708,7 +2634,6 @@ function Main.loop()
|
||||
|
||||
-- Update Upcoming Trains globally for the monitor
|
||||
State.upcomingTrains = newUpcoming
|
||||
State.debugUpcoming = dbg
|
||||
|
||||
if not Peripherals.station then
|
||||
State.currentTrain = nil
|
||||
|
||||
Reference in New Issue
Block a user