From a58632272e130d6f56eeabd2cd19d634d2fea8ed Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Mon, 17 Aug 2026 18:05:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(announce):=20=E4=BF=AE=E5=A4=8D=E8=BF=9B?= =?UTF-8?q?=E7=AB=99=E9=A2=84=E5=91=8A=E9=9F=B3=E9=A2=91=E7=BB=88=E7=82=B9?= =?UTF-8?q?=E7=AB=99=E5=90=8D=E5=AD=97=E8=A2=AB=E8=B7=B3=E8=BF=87=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20=E6=A0=B9=E5=9B=A0=E9=93=BE:=20-=20station?= =?UTF-8?q?=5Fbroadcast.lua=20=E9=80=9A=E8=BF=87=20BlockReader=20/=20Creat?= =?UTF-8?q?eTarget=20=E4=B8=A4=E4=B8=AA=E5=88=86=E6=94=AF=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=20train=5Fapproaching=20=E5=8F=91=E9=80=81=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E5=8F=AA=E5=B8=A6=20destination=20(=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E5=90=8D/=E7=AB=99=E5=90=8D)=EF=BC=8C=E6=9C=AA=E5=B8=A6=20dest?= =?UTF-8?q?Code=EF=BC=9Bserver=20=E7=AB=AF=E5=8F=AA=E8=83=BD=E8=B5=B0=20ge?= =?UTF-8?q?tStationCodeFromName(destination)=20=E6=AD=A3=E5=88=99=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=EF=BC=8C=E6=AD=A3=E5=88=99=E6=B2=A1=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E5=88=B0=E5=B0=B1=E4=BC=9A=E5=BE=97=E5=88=B0=20UNK=20=E2=86=92?= =?UTF-8?q?=20ch-UNK.wav=20/=20ja-UNK.wav=20=E4=B8=8D=E5=AD=98=E5=9C=A8=20?= =?UTF-8?q?=E2=86=92=20=E6=95=B4=E6=9D=A1=E7=9B=AE=E7=9A=84=E5=9C=B0?= =?UTF-8?q?=E6=AE=B5=E9=9F=B3=E9=A2=91=E8=A2=AB=20ffmpeg=20concat=20?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=20-=20=E5=AF=B9=E6=AF=94=20train=5Farrival?= =?UTF-8?q?=20(Peripherals.station=20=E5=88=86=E6=94=AF)=20=E6=98=AF?= =?UTF-8?q?=E6=9C=89=20destCode=20=E5=AD=97=E6=AE=B5=E7=9A=84=EF=BC=88?= =?UTF-8?q?=E7=94=B1=20Utils.getStationCode=20+=20schedule=20=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=BE=97=E5=88=B0=EF=BC=89=EF=BC=8C=E6=89=80=E4=BB=A5?= =?UTF-8?q?=E5=88=B0=E7=AB=99=E5=B9=BF=E6=92=AD=E7=BB=88=E7=82=B9=E7=AB=99?= =?UTF-8?q?=E5=90=8D=E8=83=BD=E6=AD=A3=E5=B8=B8=E6=92=AD=E5=87=BA=EF=BC=8C?= =?UTF-8?q?=E9=A2=84=E5=91=8A=EF=BC=88=E8=B5=B0=20Display/BlockReader=20?= =?UTF-8?q?=E5=88=86=E6=94=AF=EF=BC=89=E4=B8=8D=E8=83=BD=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D:=201.=20station=5Fbroadcast.lua=20=E5=9B=9B=E5=A4=84?= =?UTF-8?q?=20train=5Fapproaching=20/=20train=5Falert=20Network.send=20?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E8=A1=A5=20destCode=20=3D=20Utils.getStation?= =?UTF-8?q?Code(destination)=EF=BC=9A=20=20=20=20-=20L4053=20(alert,=20blo?= =?UTF-8?q?ckreader)=20/=20L4091=20(approach,=20blockreader)=20=20=20=20-?= =?UTF-8?q?=20L4221=20(alert,=20createTarget)=20/=20L4257=20(approach,=20c?= =?UTF-8?q?reateTarget)=202.=20server.js=20=E6=96=B0=E5=A2=9E=20resolveSta?= =?UTF-8?q?tionAudioCode(rawCode,=20rawName)=20=E4=B8=89=E7=BA=A7=E5=85=9C?= =?UTF-8?q?=E5=BA=95=E8=A7=A3=E6=9E=90=EF=BC=9A=20=20=20=20-=20L1:=20?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E7=94=A8=20raw=20destCode=EF=BC=88=E4=BC=98?= =?UTF-8?q?=E5=85=88=E7=BA=A7=E6=9C=80=E9=AB=98=EF=BC=8C=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E7=AE=97=E5=A5=BD=E7=9A=84=EF=BC=89=20=20=20=20-=20L2?= =?UTF-8?q?:=20=E6=AD=A3=E5=88=99=E8=A7=A3=E6=9E=90=20destination=20?= =?UTF-8?q?=E5=90=8D=E5=AD=97=E6=8A=BD=E5=8F=96=20code=EF=BC=88parens/dash?= =?UTF-8?q?/=E4=B8=8B=E5=88=92=E7=BA=BF=E6=A8=A1=E5=BC=8F=EF=BC=89=20=20?= =?UTF-8?q?=20=20-=20L3:=20=E6=8A=8A=20destination=20=E5=90=8D=E6=8B=BF?= =?UTF-8?q?=E5=8E=BB=20findStationByFlexibleName=20=E5=B7=B2=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E7=AB=99=E5=8F=B0=E8=A1=A8=E9=87=8C=20fuzzy=20?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=EF=BC=8C=E5=8F=96=E5=85=B6=20code=20=20=20?= =?UTF-8?q?=20-=20=E8=A7=A3=E6=9E=90=E4=B8=8D=E5=88=B0=E5=B0=B1=E6=89=93?= =?UTF-8?q?=20WARN=20=E6=97=A5=E5=BF=97=EF=BC=8C=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E4=BC=9A=E8=B7=B3=E8=BF=87=E8=BF=99=E4=B8=80=E6=AE=B5=203.=20h?= =?UTF-8?q?andleTrainApproaching=20/=20handleTrainArrival=20/=20handleTrai?= =?UTF-8?q?nDeparture=20=E4=B8=89=E4=B8=AA=20handler=20=E7=9A=84=20destCod?= =?UTF-8?q?e=20/=20nextCode=20=E5=85=A8=E9=83=A8=E5=88=87=E5=88=B0=20resol?= =?UTF-8?q?veStationAudioCode=20=E7=BB=9F=E4=B8=80=E5=85=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=86=8D=E5=90=84=E5=86=99=E4=B8=80=E9=81=8D?= =?UTF-8?q?=E6=AD=A3=E5=88=99=EF=BC=8C=E6=89=80=E6=9C=89=E9=A2=84=E5=91=8A?= =?UTF-8?q?/=E5=88=B0=E7=AB=99/=E5=8F=91=E8=BD=A6=E9=9F=B3=E9=A2=91?= =?UTF-8?q?=E7=94=A8=E5=90=8C=E4=B8=80=E6=9D=A1=E8=A7=A3=E6=9E=90=E9=93=BE?= =?UTF-8?q?=EF=BC=8C=E4=BF=9D=E8=AF=81=E7=BB=93=E6=9E=9C=E4=B8=80=E8=87=B4?= =?UTF-8?q?=20APP=5FVERSION=5FTEXT=20bump=20=E5=88=B0=20v1.0.110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CloudServer/server.js | 45 ++++++++++++++++++++++++++++++++++++++----- station_broadcast.lua | 30 ++++++++++++++++------------- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/CloudServer/server.js b/CloudServer/server.js index baa19a1..298e1fd 100644 --- a/CloudServer/server.js +++ b/CloudServer/server.js @@ -1963,6 +1963,39 @@ function ensureSilenceWav() { execSync(`ffmpeg -y -v quiet -f lavfi -i anullsrc=r=48000:cl=mono -t 1 -c:a pcm_s16le "${silence1sWavPath}"`); } +function resolveStationAudioCode(rawCode, rawName) { + const code1 = String(rawCode || '').trim().toLowerCase().replace(/_/g, '-'); + const name = String(rawName || '').trim(); + const pick = (c) => { + if (!c) return null; + const v = String(c).trim().toLowerCase().replace(/_/g, '-'); + return v && v !== 'unk' && v !== 'unknown' ? v : null; + }; + // Level 1: raw destCode (already provided) + let result = pick(code1); + let levelHit = result ? 1 : 0; + // Level 2: extract from destination name string (parens / dash / pattern) + if (!result && name) { + const extracted = getStationCodeFromName(name); + result = pick(extracted); + if (result) levelHit = 2; + } + // Level 3: fuzzy match station name to registered stations and use their code + if (!result && name) { + const reg = findStationByFlexibleName(name); + if (reg && reg.code) { + result = pick(reg.code); + if (result) levelHit = 3; + } + } + if (result && (name || rawCode)) { + log('DEBUG', `[Station-Audio-Code] resolved destCode=${result} (level=${levelHit}) rawCode=${JSON.stringify(rawCode || null)} name=${JSON.stringify(name || null)}`); + } else { + log('WARN', `[Station-Audio-Code] FAILED to resolve station audio code: rawCode=${JSON.stringify(rawCode || null)} name=${JSON.stringify(name || null)} → sequence will skip this station audio (silence / missing wav)`); + } + return result || null; +} + function getOrCreateHlsStreamState(streamName) { if (!hlsStreams[streamName]) { hlsStreams[streamName] = { @@ -2688,7 +2721,7 @@ function handleTrainApproaching(ws, data) { const finalPlatform = cleanPlatform || '1'; const lineCode = data.lineCode || (stationCode ? stationCode.split('-')[0] : 'UNK'); - const destCode = data.destCode || getStationCodeFromName(data.destination) || 'UNK'; + const destCode = resolveStationAudioCode(data.destCode, data.destination) || 'UNK'; log('INFO', `Train ${trainId} approaching ${stationName}. Broadcasting pre-arrival...`); @@ -2804,9 +2837,10 @@ function handleTrainArrival(ws, data) { const finalPlatform = cleanPlatform || '1'; const lineCode = data.lineCode || (stationCode ? stationCode.split('-')[0] : 'UNK'); - const destCode = data.destCode || getStationCodeFromName(data.destination) || 'UNK'; + const destCode = resolveStationAudioCode(data.destCode, data.destination) || 'UNK'; const nextStationRaw = data.nextStation ? String(data.nextStation).trim() : ''; - const nextCodeRaw = data.nextCode ? String(data.nextCode).trim() : (nextStationRaw ? getStationCodeFromName(nextStationRaw) : ''); + const nextCodeRaw = resolveStationAudioCode(data.nextCode, nextStationRaw) || + (nextStationRaw ? getStationCodeFromName(nextStationRaw) : ''); const hasNextStation = nextStationRaw && nextStationRaw !== '' && nextCodeRaw && nextCodeRaw !== 'UNK' && nextCodeRaw !== ''; const finalNextCode = hasNextStation ? nextCodeRaw : null; @@ -2885,9 +2919,10 @@ function handleTrainDeparture(ws, data) { const beep = data.departureBeep || data.beep || 'fc1'; const lineCode = data.lineCode || (stationCode ? stationCode.split('-')[0] : 'UNK'); - const destCode = data.destCode || getStationCodeFromName(data.destination) || 'UNK'; + const destCode = resolveStationAudioCode(data.destCode, data.destination) || 'UNK'; const nextStationRaw = data.nextStation ? String(data.nextStation).trim() : ''; - const nextCodeRaw = data.nextCode ? String(data.nextCode).trim() : (nextStationRaw ? getStationCodeFromName(nextStationRaw) : ''); + const nextCodeRaw = resolveStationAudioCode(data.nextCode, nextStationRaw) || + (nextStationRaw ? String(data.nextCode || '').trim() || getStationCodeFromName(nextStationRaw) : ''); const hasNextStation = nextStationRaw && nextStationRaw !== '' && nextCodeRaw && nextCodeRaw !== 'UNK' && nextCodeRaw !== ''; const finalNextCode = hasNextStation ? nextCodeRaw : null; diff --git a/station_broadcast.lua b/station_broadcast.lua index 8617d38..2ee9164 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -1,6 +1,6 @@ -- 1. Configuration & Constants -local APP_VERSION_TEXT = "v1.0.109" +local APP_VERSION_TEXT = "v1.0.110" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group", @@ -4044,18 +4044,19 @@ function Main.loop() Utils.log("INFO", string.format("Train Alert: %s (ETA: %ds, Delay: %dm, Cancelled: %s, Reason: %s)", trainName, etaSeconds, displayDelayMinutes, tostring(cancelled), tostring(reason or ""))) if Utils.isLocalStationMaster() then Network.send({ - type = "train_alert", - stationName = State.stationName, - stationCode = State.stationCode, - stationPlatform = platform, - trainId = trainName, - destination = destination, - eta = tostring(etaSeconds) .. "s", - etaSeconds = etaSeconds, - delay = displayDelayMinutes, - cancelled = cancelled, - reason = reason - }) + type = "train_alert", + stationName = State.stationName, + stationCode = State.stationCode, + stationPlatform = platform, + trainId = trainName, + destination = destination, + destCode = Utils.getStationCode(destination), + eta = tostring(etaSeconds) .. "s", + etaSeconds = etaSeconds, + delay = displayDelayMinutes, + cancelled = cancelled, + reason = reason + }) end end end @@ -4087,6 +4088,7 @@ function Main.loop() stationPlatform = platform, trainId = trainName, destination = destination, + destCode = Utils.getStationCode(destination), eta = string.format("%.1fs", etaSeconds), etaSeconds = etaSeconds, delay = displayDelayMinutes, @@ -4216,6 +4218,7 @@ function Main.loop() stationPlatform = platform or State.stationPlatform or "1", trainId = tName, destination = dest, + destCode = Utils.getStationCode(dest), eta = etaStr, etaSeconds = etaSeconds, delay = delay @@ -4251,6 +4254,7 @@ function Main.loop() stationPlatform = platform or State.stationPlatform or "1", trainId = tName, destination = dest, + destCode = Utils.getStationCode(dest), eta = etaStr, etaSeconds = etaSeconds, delay = delay