From ef7567152785bf3ef2e6e392a04f045798c2e153 Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Sun, 2 Aug 2026 11:37:41 +0800 Subject: [PATCH] feat: Add train pre-arrival broadcast via CRN create_target --- CloudServer/server.js | 50 +++++++++++++++++++++++++++++++++++++++++++ station_broadcast.lua | 45 +++++++++++++++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/CloudServer/server.js b/CloudServer/server.js index c90feed..e479295 100644 --- a/CloudServer/server.js +++ b/CloudServer/server.js @@ -1687,6 +1687,9 @@ function handleMessage(ws, data) { case 'train_arrival': handleTrainArrival(ws, data); break; + case 'train_approaching': + handleTrainApproaching(ws, data); + break; case 'train_departure': handleTrainDeparture(ws, data); break; @@ -1854,6 +1857,53 @@ function findStationByFlexibleName(targetName) { return null; } +function handleTrainApproaching(ws, data) { + const trainId = data.trainId; + const stationName = getCorrectStationName(data.stationName); + const stationCode = data.stationCode; + const platform = data.stationPlatform || data.platform || '1'; + + const destCode = data.destCode || getStationCodeFromName(data.destination) || 'UNK'; + + log('INFO', `Train ${trainId} approaching ${stationName}. Broadcasting pre-arrival...`); + + ws.send(JSON.stringify({ + type: 'train_approaching_ack', + success: true, + message: 'Train approaching processed successfully', + trainId + })); + + // Pre-arrival Audio Logic + // 提示音:ksts + // 日文:ja-fc1 + ja-站台编号 + ja-fc2 + ja-终点编号 + ja-fc3 + // 中文:ch-fc1 + ch-fc2 + ch-fc3 + ch-终点编号 + ch-fc4 + const seq = [ + 'ksts', + 'ja-fc1', `ja-${platform}`, 'ja-fc2', `ja-${destCode}`, 'ja-fc3', + 'ch-fc1', 'ch-fc2', 'ch-fc3', `ch-${destCode}`, 'ch-fc4' + ]; + + enqueueHlsPush(stationName, seq); + + const audioId = `approaching-${stationCode}-${Date.now()}`; + const built = buildSequenceWavFile(seq); + if (built) { + enqueueStationAudioTask(stationName, ws, { + audioFormat: built.audioFormat, + sourcePath: built.sourcePath, + streamUrl: built.streamUrl, + durationSec: built.durationSec, + priority: 1, + interruptMode: 'ifLower', + source: 'train_approaching', + audioId, + consoleStreamStart: { type: 'stream_start', station: stationName, seq, streamName: getStationStreamName(stationName), hlsUrl: getStationHlsUrl(getStationStreamName(stationName)) }, + consoleStreamEnd: { type: 'stream_end', station: stationName } + }); + } +} + function handleTrainArrival(ws, data) { const trainId = data.trainId; const stationName = getCorrectStationName(data.stationName); diff --git a/station_broadcast.lua b/station_broadcast.lua index 02e3522..9e2223c 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -2,7 +2,7 @@ -- ============================================================================ -- 1. Configuration & Constants -- ============================================================================ -local APP_VERSION_TEXT = "v1.0.19" +local APP_VERSION_TEXT = "v1.0.20" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group", @@ -120,6 +120,11 @@ function Peripherals.init() end -- Speakers Peripherals.speakers = { peripheral.find("speaker") } + -- Create Target Block (CRN) + Peripherals.createTarget = peripheral.find("create_target") + if Peripherals.createTarget then + pcall(Peripherals.createTarget.resize, 80, 10) + end end -- ============================================================================ @@ -2229,9 +2234,47 @@ end -- 8. Main Logic -- ============================================================================ local Main = {} +State.announcedApproaching = {} function Main.loop() while true do + if Peripherals.createTarget then + local lines = Peripherals.createTarget.dump() + for _, lineText in pairs(lines) do + if lineText and lineText ~= "" and lineText:match("[%w%?%[]") then + local etaVal, etaUnit, tName, dest + etaVal, etaUnit, tName, dest = string.match(lineText, "^(%d+)%s+(.-)%s+(%[.-%][^%s]*)%s+(.*)$") + if not tName then + etaVal, etaUnit, tName, dest = string.match(lineText, "^([^%s]+)%s+(.-)%s+(%[.-%][^%s]*)%s+(.*)$") + end + if not tName then + etaVal, etaUnit, tName, dest = string.match(lineText, "^([^%s]+)%s+(.-)%s+([^%s]+)%s+(.*)$") + end + + if tName and etaVal then + if etaVal == "1" or etaVal == "现在" then + local announceKey = tName .. "_" .. dest + local now = os.epoch("utc") + -- Prevent spamming: only announce once per minute per train + if not State.announcedApproaching[announceKey] or (now - State.announcedApproaching[announceKey] > 60000) then + State.announcedApproaching[announceKey] = now + Utils.log("INFO", "Train Approaching: " .. tName) + Network.send({ + type = "train_approaching", + stationName = State.stationName, + stationCode = State.stationCode, + stationPlatform = State.stationPlatform, + trainId = tName, + destination = dest, + eta = etaVal + }) + end + end + end + end + end + end + if not Peripherals.station then State.currentTrain = nil Display.render()