tune: stabilize approaching trigger and show precise ETA

This commit is contained in:
2026-08-02 19:25:57 +08:00
parent fb1256fbcc
commit 22ea43c1c1
+58 -7
View File
@@ -2,7 +2,7 @@
-- ============================================================================
-- 1. Configuration & Constants
-- ============================================================================
local APP_VERSION_TEXT = "v1.0.41"
local APP_VERSION_TEXT = "v1.0.42"
local CONFIG = {
CLOUD_URL = "ws://stabadmin.fse-media.group",
@@ -18,6 +18,7 @@ local CONFIG = {
ALERT_CONFIRM_MS = 60000,
ALERT_COOLDOWN_MS = 300000,
APPROACHING_COOLDOWN_MS = 120000,
APPROACHING_STABLE_MS = 15000,
DEBUG = true
}
@@ -2406,7 +2407,15 @@ local function buildEtaLabel(etaSeconds, textEta)
return "~" .. tostring(value) .. "m"
end
end
return tostring(math.max(0, tonumber(etaSeconds) or 0)) .. "s"
local secs = math.max(0, tonumber(etaSeconds) or 0)
local whole = math.floor(secs + 0.0001)
if whole >= 60 then
return string.format("%02d:%02d", math.floor(whole / 60), whole % 60)
end
if secs >= 10 then
return string.format("%02ds", whole)
end
return string.format("%.1fs", secs)
end
local function mapTrainStatusReason(statusId)
@@ -2494,6 +2503,7 @@ function Main.loop()
local elapsedSeconds = (now - (State.lastRefreshedEpoch or now)) / 1000
local currentTick = (data.LastRefreshed or 0) + math.floor(elapsedSeconds * (State.tickRate or 20))
local seenAlertKeys = {}
local seenApproachKeys = {}
cleanupTimestampMap(State.announcedApproaching, now, tonumber(CONFIG.APPROACHING_COOLDOWN_MS) or 120000)
cleanupTimestampMap(State.announcedAlerts, now, tonumber(CONFIG.ALERT_COOLDOWN_MS) or 300000)
@@ -2529,7 +2539,7 @@ function Main.loop()
local scheduledArrival = pickEarlierTick(st.ScheduledArrival, st.ScheduledDeparture)
local realArrival = pickEarlierTick(st.RealTimeArrival, st.RealTimeDeparture)
local etaTicks = realArrival - currentTick
local etaSeconds = math.floor(etaTicks / (State.tickRate or 20))
local etaSeconds = etaTicks / (State.tickRate or 20)
if etaSeconds < 0 then etaSeconds = 0 end
local announceKey = normalizeUpcomingKey(trainName, destination)
local etaLabel = buildEtaLabel(etaSeconds, etaTextByKey[announceKey])
@@ -2575,9 +2585,22 @@ function Main.loop()
end
if etaSeconds >= 0 and etaSeconds < 30 then
if not State.announcedApproaching[announceKey] then
seenApproachKeys[announceKey] = true
local pending = State.pendingApproaching[announceKey]
if not pending then
State.pendingApproaching[announceKey] = { since = now, lastEta = etaSeconds }
else
if etaSeconds > (tonumber(pending.lastEta) or etaSeconds) + 0.5 then
pending.since = now
end
pending.lastEta = etaSeconds
end
local stableMs = tonumber(CONFIG.APPROACHING_STABLE_MS) or 15000
local currentPending = State.pendingApproaching[announceKey]
if currentPending and (now - (currentPending.since or now)) >= stableMs and not State.announcedApproaching[announceKey] then
State.announcedApproaching[announceKey] = now
Utils.log("INFO", string.format("Train Approaching: %s (ETA: %ds, Delay: %dm)", trainName, etaSeconds, delayMinutes))
Utils.log("INFO", string.format("Train Approaching: %s (ETA: %.1fs, Delay: %dm)", trainName, etaSeconds, delayMinutes))
Network.send({
type = "train_approaching",
stationName = State.stationName,
@@ -2585,13 +2608,15 @@ function Main.loop()
stationPlatform = platform,
trainId = trainName,
destination = destination,
eta = tostring(etaSeconds) .. "s",
eta = string.format("%.1fs", etaSeconds),
etaSeconds = etaSeconds,
delay = displayDelayMinutes,
cancelled = cancelled,
reason = reason
})
end
else
State.pendingApproaching[announceKey] = nil
end
end
end
@@ -2601,6 +2626,11 @@ function Main.loop()
State.pendingAlerts[k] = nil
end
end
for k, _ in pairs(State.pendingApproaching) do
if not seenApproachKeys[k] then
State.pendingApproaching[k] = nil
end
end
end
end
@@ -2608,6 +2638,7 @@ function Main.loop()
if not Peripherals.blockReader and Peripherals.createTarget then
local lines = Peripherals.createTarget.dump()
local seenAlertKeys = {}
local seenApproachKeys = {}
cleanupTimestampMap(State.announcedApproaching, now, tonumber(CONFIG.APPROACHING_COOLDOWN_MS) or 120000)
cleanupTimestampMap(State.announcedAlerts, now, tonumber(CONFIG.ALERT_COOLDOWN_MS) or 300000)
@@ -2687,7 +2718,20 @@ function Main.loop()
-- 触发逻辑:当 ETA 已经明确小于30秒(包括15秒、现在等),且之前没有播报过
if etaSeconds >= 0 and etaSeconds < 30 then
if not State.announcedApproaching[announceKey] then
seenApproachKeys[announceKey] = true
local pending = State.pendingApproaching[announceKey]
if not pending then
State.pendingApproaching[announceKey] = { since = now, lastEta = etaSeconds }
else
if etaSeconds > (tonumber(pending.lastEta) or etaSeconds) + 0.5 then
pending.since = now
end
pending.lastEta = etaSeconds
end
local stableMs = tonumber(CONFIG.APPROACHING_STABLE_MS) or 15000
local currentPending = State.pendingApproaching[announceKey]
if currentPending and (now - (currentPending.since or now)) >= stableMs and not State.announcedApproaching[announceKey] then
State.announcedApproaching[announceKey] = now
Utils.log("INFO", string.format("Train Approaching: %s (ETA: %ds, Delay: %dm)", tName, etaSeconds, delay))
Network.send({
@@ -2702,6 +2746,8 @@ function Main.loop()
delay = delay
})
end
else
State.pendingApproaching[announceKey] = nil
end
end
end
@@ -2712,6 +2758,11 @@ function Main.loop()
State.pendingAlerts[k] = nil
end
end
for k, _ in pairs(State.pendingApproaching) do
if not seenApproachKeys[k] then
State.pendingApproaching[k] = nil
end
end
end
-- Update Upcoming Trains globally for the monitor