Henry_Du
5c462a4d09
fix(server): 改用 Express 5 + path-to-regexp v7 兼容的通配写法,避免路由启动崩溃
...
Express 5 内置的 path-to-regexp v7 不再支持裸 '*',也不支持
自定义正则 '.*'(会报 Missing parameter name)。Express 5
官方兼容的单段全通写是 ':name(*)',并且路由注册会在 app 启动
第一时间完成(出错会直接崩)。
同时为了兼容旧 URL 行为,保留 express.static 前置挂载 +
显式 app.get 后备两条路径,因为 Audio 模块可能需要带
Cache-Control / Range / Content-Type 等头的 custom sendBinaryFile
处理(例如 station 动态裁剪音频),所以不能直接用 static 替代。
修复 7 条路由:
/media/audio/general/:path(*)
/media/audio/beep/:path(*)
/media/audio/music/:path(*)
/media/audio/voice/:path(*)
/media/audio/line/:path(*)
/media/audio/station/:path(*)
/media/temp/:path(*)
参数解码加 decodeURIComponent(),兼容中文/空格文件名。
客户端 bump v1.0.101 -> v1.0.102
2026-08-17 15:41:36 +08:00
Henry_Du
fc66e43379
fix: 修复新版 path-to-regexp 不兼容 '*' 通配符导致启动崩溃
...
新版 express/router 依赖的 path-to-regexp 不再接受裸 '*' 路径语法,
改为命名通配参数 :relPath(.*),并同步把 req.params[0] 改为
req.params.relPath。涉及 7 条 /media/* 静态路由:
- /media/audio/general/*
- /media/audio/beep/*
- /media/audio/music/*
- /media/audio/voice/*
- /media/audio/line/*
- /media/audio/station/*
- /media/temp/*
客户端版本号 bump v1.0.100 -> v1.0.101
2026-08-17 15:38:41 +08:00
Henry_Du
c9d8994942
chore: 版本号升到 v1.0.100
2026-08-17 15:33:54 +08:00
Henry_Du
4c7d94f2c9
feat(A1+B1): 引入站台多主机识别、音频线缆分组互斥令牌、本地Modem仲裁、线缆分组管理WebUI
...
服务端 A1 改动(CloudServer/server.js):
- stations 改为 nodes[] 多连接存储,同站台名的多台 CC 主机归入同一组(纯 stationName 精确分组)
- 新增 getStationMaster():hasStationPeripheral + lastSeen 加权选 Master,音频只下发给 Master
- 新增 audioCableGroups 数据结构(持久化到 server-data.json)
- 新增 acquireCableToken/releaseCableToken:同线缆组全局互斥,高优先级发送 audio_preempt 抢占
- 新增 7 路由 REST API:/api/audio-cable-groups CRUD + 批量/单个站台成员管理 + PUT /stations/:name/cable-group 直接改组
- sendAudioControl 给同站组所有节点全量下发(stop/状态同步)
- init_state / state_update 携带 audioCableGroups 给前端
- WS close 自动 removeStationWs 清理节点 + 释放令牌
客户端 B1 改动(station_broadcast.lua v1.0.99):
- Peripherals 新增 wiredModems 扫描(排除无线),自动 rednet.open
- 新增 LocalBus 命名空间:
- station_hello 每 10s 广播 + 30s 超时清理邻居
- 同站台名自动组 stationGroup,按 hasStationPeripheral + nodeId 升序选 Master
- 新增 Utils.isLocalStationMaster(),所有列车上报(arrival/approaching/alert/departure/schedule_sync)仅 Master 执行,彻底解决重复广播
- acquireLocalToken:audio_probe -> 80ms 收响应 -> 必要时 audio_preempt 抢占 -> token_grant
- 令牌持有期间每 2s 广播 audio_playing 心跳,30s 超时自动判死回收
- Audio.playerLoop 在 playItem 前获取本地令牌,失败则跳过该音频
- Audio.stop() 自动释放本地令牌
- WS 新增下行处理:audio_preempt / cable_token_denied / station_group_state
- station_identity.cfg 支持 audio_cable_group= 字段,saveStationIdentity 写回
- Network.register/heartbeat 携带 cableGroup 供服务端回填分组
Web 管理端(CloudServer/public/cablemanager.html,单文件无外部依赖):
- 极简硬边风格,对齐 listmanager.html 配色和字体
- 分组网格卡片:色标/名称/描述/成员数/当前令牌持有者 + 编辑删除
- 新增/编辑 Modal:名称+描述+8色预设色板+自定义#RRGGBB
- 分组详情双栏 Dual List:左栏全部站台(搜索+在线状态+在其他组标签)/ 右栏成员,中间批量添加移除按钮
- 顶部快捷操作:站台下拉+组下拉+确认,直接 PUT /stations/:name/cable-group
- WebSocket 监听 state_update 实时刷新,Toast 提示反馈
2026-08-17 15:32:20 +08:00
Henry_Du
6ac05d3a84
feat(server): 实施 A1 方案 - 多连接存储、站台分组 Master 选举、audioCableGroup 互斥令牌机制
...
- stations 存储改造:stations[name] = { name, code, platform, audioCableGroup, version, lastSeen, nodes: [] } 结构,每个 node 含 ws/hasStationPeripheral/stationPeripheralSide/hasBlockReader/hasCreateTarget/identityMode/nodeId/wsId/connectedAt
- 新增 audioCableGroups:{ id, name, color, description, stationNames: [] } 分组,及 audioCableTokens 互斥令牌 Map(cableGroupId -> { holderStationName, holderAudioId, holderPriority, acquiredAt, cancelToken })
- 新增核心函数:upsertStationNode(按 wsId 去重更新 node、聚合计时表级 schedule)、removeStationWs(WS 关闭时清理 node + 释放令牌 + 下发 group_state)、getStationMaster(hasStationPeripheral=1000加权 + lastSeen小数加权 两轮选举 OPEN ws)、getAllStationConnections、getGroupKeyForStation(纯 stationName 分组,不再 code@@platform)、acquireCableToken(无持者直给/同 holder 更新/高优先级 audio_preempt + 200ms 延迟抢占/低优先级拒绝+denied 消息)、releaseCableToken
- 发送策略改造:sendAudioControl 遍历组内所有节点 ws 全发(同名站同步 stop 等指令);sendAudioBufferToStation/sendLiveWavChunksToStation 只发送 master ws,发送前后 acquire/release token,durationSec 后 setTimeout 延迟释放,audio_start 消息新增 cableGroupId 字段
- enqueueStationAudioQueue 增加 cableGrp 兜底释放;loadData 兼容旧 stations 单值结构导入 nodes=[] 数组新结构 + audioCableGroups 双向回填;saveData 剥离 nodes 中 ws 对象后保存,新增 audioCableGroups 字段持久化
- WS 层改造:wss close 事件调用 removeStationWs;console_connect init_state 增加 audioCableGroups 数组;handleStationRegister/handleHeartbeat/handleScheduleSync 改为调用 upsertStationNode;station_register_ack 返回 nodeId/audioCableGroup
- broadcastUpdate state_update 增加 audioCableGroups 字段;新增 WS 下行 audio_preempt / cable_token_granted / cable_token_denied / station_group_state 四种消息类型
- getStationGroups 完全重写:按 stationName 精确分组,返回 members/nodes 数组(每个 node 带 nodeId/wsId/online/isMaster/connectedAt/lastSeen/hasStationPeripheral/hasBlockReader/hasCreateTarget/identityMode/tickRate/memberTags),增加 masterNodeId、audioCableGroup{id,name,color}、cableGroupId 字段;resolveStationGroup memberNames 返回 nodeId 列表
- REST API 新增 9 个路由:GET/POST/PUT/DELETE /api/audio-cable-groups,POST /api/audio-cable-groups/:id/stations(批量加站台,含 prev cableGroup 自动清理)、DELETE /api/audio-cable-groups/:id/stations/:stationName、PUT /api/stations/:name/cable-group(stations.audioCableGroup 与 group.stationNames 双向同步),stations DELETE 自动同步 cable group 清理
- 兼容性:旧 stations[name].ws 统一改为 getStationMaster(name).ws;TTS、HLS、temp-broadcast、音乐播放、version 管理等功能不受破坏;Lua 客户端版本号提升至 v1.0.99
2026-08-17 15:15:23 +08:00
Henry_Du
55f0312314
feat(audio): 支持斜杠格式的车站编号和模糊搜索匹配
...
- 修改TTS音频导入逻辑,保留编号中的斜杠(/)格式(如 CH-01/CE-12),自动创建子目录
- 移除generator.html中单文件和批量导入时的斜杠转横杠逻辑
- 新增sanitizeStationCode和ensureDirForFile辅助函数,确保路径安全
- 重写findFileCaseInsensitive,支持递归子目录搜索与末尾段模糊匹配
- 新增listAllFilesRecursive和resolveAudioPathWithFuzzy工具函数
- 修改getPlaybackAudioByBaseName/findWavByBaseName支持模糊搜索查找
- 修改resolveManagedPath允许子路径访问,getManagedFiles递归扫描子目录
- 媒体路由从:file参数改为通配符/*形式,safeRelativeToBase确保路径安全
- 升级版本号至v1.0.98
2026-08-17 14:54:21 +08:00
Henry_Du
849b43af39
fix: 修复音乐和临时广播无法播放(AUDIO FREE)的问题
...
- 重写 waitForInterruptibleDelay/waitForNativeSpeakersEmpty 使用 os.clock()
轮询,替换会抢占 websocket_message 事件的 os.pullEvent()
- 重写 queueSamplesSynchronized/playChunkOnSpeakers 重试循环使用
os.sleep() 轮询,不再调用 pullEvent 吞掉音频分块事件
- 重写 Audio.createStream().read() 与 Audio.playerLoop 使用 sleep 轮询,
不再使用 os.pullEvent('audio_chunk')/'audio_queue' 抢事件
- 修复 Audio.playItem 将 wav-stream/wav-stream-live 错误路由到
playPcmS16LEItem,改为路由到 playWavStreamItem(服务端分块每块
带完整 44 字节 WAV 头,需 decodeWavChunkToSamples)
- Network.messageLoop audio_start 分支将 wav-stream-live 加入流式
接收判定,避免走 chunks 缓冲逻辑
- 版本号升级至 v1.0.97
2026-08-17 14:30:54 +08:00
Henry_Du
e9819d4894
fix(multiplayer): normalize CRN BlockReader NBT structure with unwrapNbtObject helper to handle SP vs MP differences (single-player wraps every nested object as { [1] = obj } one-element arrays, while multiplayer uses direct maps without [1] wrapper)
...
- New unwrapNbtObject(obj): detects whether the table actually has a [1] wrapper AND outer table has exactly 1 key AND the inner [1] is useful, then returns inner object; otherwise returns obj unchanged - works transparently for both SP and MP structures
- Replace ALL hard-coded [1] dereferences in BlockReader parsing:
- stop.Station -> unwrapNbtObject(stop.Station)
- st.RealTimeStation -> unwrapNbtObject(st.RealTimeStation)
- st.ScheduledStation -> unwrapNbtObject(st.ScheduledStation)
- rtStation.StationInfo -> unwrapNbtObject(rtStation.StationInfo)
- schStation.StationInfo -> unwrapNbtObject(schStation.StationInfo)
- stop.Train -> unwrapNbtObject(stop.Train)
- stop.Stopovers[i] entries: deep-unwrap if table, try StationName/Name fields to get string destination from potential NBT compound stopovers
- tr.Status entries: unwrap each element before reading as string
- This eliminates the MP-only failure where st=nil (because SP-style Station[1] didn't exist) causing the whole TrainStop loop to skip inserting anything into newUpcoming and render UPCOMING as ???
Bump to v1.0.76
2026-08-16 14:35:18 +08:00
Henry_Du
66683f6d13
fix(upcoming): prevent UPCOMING freeze caused by NBT parsing errors in CC environment
...
- Eliminate empty-then block in Stopovers fallback logic: rewrite nested if/else with empty body to elseif chain to avoid parser error in reduced CC Lua dialect (was silently caught by pcall causing newUpcoming to remain empty)
- Add pcall protection to the standalone CreateTarget.dump() path (previously unprotected), with fallback to empty lines table on failure
- Add explicit WARN log on BlockReader.getBlockData pcall failure so user can diagnose errors via terminal output instead of silent data=nil
- Wrap each TrainStop iteration inside its own pcall so a malformed entry cannot abort the whole loop; failures are logged with stop index
Bump to v1.0.75
2026-08-16 14:23:43 +08:00
Henry_Du
50746ce766
fix(nbt): unwrap single-element arrays in CRN BlockReader NBT parsing (Station[1]/RealTimeStation[1]/ScheduledStation[1]/StationInfo[1]/Train[1]) to get real TrainName/Destination/StationName/Platform; fallback destination to precise StationName code (e.g. CE-03 2) when Destination is invalid or is CRN aggregated tag name. Bump to v1.0.74
2026-08-16 14:15:24 +08:00
Henry_Du
0de59531f9
test(br): diagnose block_reader instead of bailing
...
When no block_reader is found by exact type name, list all connected
peripherals (getType/getMethods/getName) into the output txt so the real
peripheral name can be identified on the target machine.
2026-08-16 14:07:13 +08:00
Henry_Du
926db04a3e
test: add block_reader NBT dumper for advanced display
...
Reads the adjacent block (Advanced Display) via Advanced Peripherals block_reader
and writes registry name, block state, and NBT data as structured text to
blockreader_display_nbt.txt.
2026-08-16 14:02:38 +08:00
Henry_Du
ae213a84a1
feat: 从机站台吸附识别与时刻表自动同步 v1.0.73
...
- Lua端: 新增定期外设重扫描(PERIPHERAL_SCAN_INTERVAL=15s),支持热插拔站台方块
- Lua端: 新增定期身份同步,站台外设热插/热拔时自动刷新身份并重新register
- Lua端: 新增独立的schedule sync coroutine与station_schedule_sync消息类型(SCHEDULE_SYNC_INTERVAL=10s)
- Lua端: 扩展heartbeat携带hasStationPeripheral/stationPeripheralSide/hasBlockReader/hasCreateTarget/identityMode/upcomingTrains/currentTrain等字段
- 从机若吸附有站台方块(train_station外设),则自动进入主机逻辑: 识别到发、停靠列车检测,数据通过WS推送到服务器
- server端: 新增assignDeviceFields工具函数统一写入设备字段与时刻表
- server端: 新增handleScheduleSync处理station_schedule_sync消息,数据写入stations[name]并broadcast
- server端: 扩展handleHeartbeat与handleStationRegister,均调用assignDeviceFields存储设备状态和时刻表摘要
- server端: 扩展getStationGroups分组视图,新增hostCount/slaveCount/hasAnyStationPeripheral/upcomingTrains/currentTrain/members详细信息
- 时刻表合并: 同一站台组多节点的upcomingTrains按trainName@@dest@@platform去重合并; currentTrain优先主机数据
- 版本升级: v1.0.72 -> v1.0.73
2026-08-16 13:33:10 +08:00
Henry_Du
cd5b1d47b0
fix(crn): 修复CRN聚合站(如「千叶」)在CC中文环境下变????导致校正匹配失败引发终点站广播漏播
...
- 新增 extractAlphaNumCodes / hasSharedAlphaNumCode: 提取并比对字母数字代码(CB-03,CE-09等), 在中文变问号乱码环境下仍可通过代码完成跨源匹配
- looksLikeValidDestinationText: 放宽校验, 若问号超过50%但仍存在有效字母数字代码(如「????CB-03 6」)时不直接判为无效——保留代码供后续 hasSharedAlphaNumCode 匹配
- tryCorrectUpcomingEntryWithCurrentTrain:
1) 新增 etaSeconds 形参用于识别在站列车(eta≤0.5s), 据此触发校正
2) 新增 nearbyPlatform 条件: 站台号数字差≤1 时也进入校正候选
3) 新增 sharedCodeDest / sharedCodeTrain: 即使车次/站台全不匹配, 只要 dest 或 id 含有与权威值相同的字母数字代码即可触发
4) 新增兜底触发: (dest或id无效且eta=0) | (双无效且相邻站台) —— 专门覆盖CRN聚合名????这种彻底无代码的场景
5) 新增校正分支: 只要 sharedCodeTrain/sharedCodeDest 命中且 (etaAtStation|samePlatform|invalid) 即直接覆盖原值, 无需 fuzzy match 再次通过
- checkIsAtStationWithCurrentTrain:
1) 无 sameTrain 时用 hasSharedAlphaNumCode 二次匹配车次
2) 若车次/目的地双乱码 + 站台相邻, 也视为同车
3) 乱码目的地分支新增 hasSharedAlphaNumCode 成功即判停靠成功
- BlockReader/CreateTarget 两处预校正均移至 etaSeconds 计算之后, 并将 eta 传入函数, 确保看门条件里的 etaAtStation 可生效
- 全局校正循环也传入 entry.eta
版本升级至 v1.0.72
2026-08-16 13:25:39 +08:00
Henry_Du
716a23cad5
fix(data): 修复权威时刻表与NBT显示粒度不一致导致终点站漏播(「千叶」聚合名 vs「千叶CB-03 6」具体站台)
...
- tryCorrectUpcomingEntryWithCurrentTrain: 校正逻辑从『仅无效乱码才覆盖』改为『同站fuzzy匹配且字符串不等即覆盖』,使schedule中的具体站台名优先于NBT中的粗糙聚合名
- 新增trainName的同粒度校正:车次信息不一致时,同车次fuzzy匹配成功即采用权威id
- BlockReader/CreateTarget两处预校正:解除『looksLikeValidDestinationText为false才替换』的限制,只要tryCorrect...返回的值与原值不同即替换——确保聚合名「千叶」这类『有效但粗糙』的文本也会被升级为具体站台名
- announceKey生成前的预校正与upcomingTrains赋值前的全局校正双保险,使冷却去重key与显示/广播目的地均完全对齐权威时刻表
版本升级至 v1.0.71
2026-08-16 13:05:57 +08:00
Henry_Du
ae96c86288
feat: departure广播新增下一站播报 + 客户端预解析station code
2026-08-16 13:01:32 +08:00
Henry_Du
17b03ce0f7
fix(data): 修复NBT(BlockReader/CreateTarget)与车站时刻表数据源不一致导致终点站广播漏播的问题
...
- 新增 looksLikeValidDestinationText: 检测目的地/车次名是否有效(过滤Unknown和高比例问号乱码)
- 新增 tryCorrectUpcomingEntryWithCurrentTrain: 用权威State.currentTrain数据校正 upcoming 条目中的乱码车次/目的地
- 新增 checkIsAtStationWithCurrentTrain: 增强 isAtStation 匹配鲁棒性, 优先站台号+车次ID匹配, 乱码时降级到目的地模糊匹配
- 提前预校正: 在生成 announceKey 前就校正乱码字段, 确保 approaching/alarm 冷却去重 key 一致
- 后置全局校正: 在赋值 State.upcomingTrains 前再次对所有条目做权威校正, 保证显示和广播使用的终点站信息一致
版本升级至 v1.0.70
2026-08-16 12:44:09 +08:00
Henry_Du
32b2c8ce9d
fix: 终点站到达时下一站广播播放异常 + getNextStation 不回绕起点
...
1. Utils.getNextStation: 移除终点站回绕到起点的逻辑(非环线)
- 此前当前站是 END 时会从 schedule.entries 开头再找,把起点当下一站
- 修复后在终点站返回 nil,明确表示无后续站
2. 服务端 handleTrainArrival: 智能区分普通站/终点站广播序列
- 新增 hasNextStation / finalNextCode 判断:只有当下一站有效时
才在 seq 中插入 ch-nextsta + ch- 片段
- 终点站(finalNextCode 为 null):直接删除 nextsta 和下一站代码,
仅保留 站台-站台-线路-方向-终点站-警示 片段
- 避免 ch-UNK 等无效资源或回绕起点站名被播放
3. 日志增强:arrival 处理时额外打印 nextStation 和 nextCode,
便于快速确认服务端是否收到正确的下一站信息
版本号 v1.0.69 -> v1.0.70
2026-08-16 12:41:19 +08:00
Henry_Du
34d9ed00d6
fix: 解决自动更新无限重启循环 + 终点站列车不显示在预测列表
...
1. CloudServer: publishStationUpdate 发布时同步 Gitea 最新脚本到本地副本
- 新增 fetchGiteaScript() 一次下载全文
- 发布更新时将 Gitea 脚本内容写入 stationScriptPath
- 保证 targetVersion 与 /downloads/station_broadcast.lua 内容版本一致
2. 客户端 AutoUpdate.apply: 下载后校验版本一致性
- 从下载内容正则提取 APP_VERSION_TEXT
- 若 downloadedVersion ~= targetVersion 则中止更新,防止 reboot loop
- 写入错误日志便于排查
3. 预测显示: 在站列车(尤其终点站)强制插入 upcomingTrains 列表头部
- CRN 可能从 TrainStops 提前移除终点站列车
- 使用 normalizeUpcomingKey 去重避免重复条目
- 固定 ETA=0,确保 CURREN T TRAIN 对应列车能在 UPCOMING 中可见
版本号 v1.0.68 -> v1.0.69
2026-08-16 12:32:11 +08:00
Henry_Du
82a4ecd3e8
fix: 确保在站列车(包括终点站列车)始终显示在预测列表中
...
- 当 State.currentTrain 存在时,手动将其信息插入 upcomingTrains 列表头部
- 解决终点站列车被 CRN 导航系统从 TrainStops 提前移除导致预测区无显示的问题
- 使用 normalizeUpcomingKey 去重,避免重复条目
- 版本号 v1.0.68 -> v1.0.69
2026-08-16 12:22:50 +08:00
Henry_Du
1b958c25df
feat(display): 标注终点站[END]与下一站[NEXT]并修复多项显示bug
...
- 修复所有站误标[END]:原来用instruction.id判断是错误的,Create中每个停靠站都是create:destination;现在改为用Utils.getDestination()匹配或取列表最后一个站作为终点站
- 过滤包含NaN的无效站点名
- 当前站匹配:先尝试『站名+站台号』严格匹配(避免CB-03 5和CB-03 6同时高亮,匹配不到再退化到站名匹配
- 新增『下一站』标识:~前缀 + 橙色 + [NEXT]后缀
- 新增『终点站』标识:黄色 + [END]后缀
- 当前站:>前缀 + 绿色 + << 标记
- 未到达站:*前缀 + 白色
- 已过站:浅灰色
- 版本号升级至 v1.0.68
2026-08-16 12:01:04 +08:00
Henry_Du
1d99634957
fix(audio): 修复导致完全没有声音的回归错误,添加超时防止挂起,修复等待缓冲区清空的逻辑
2026-08-16 11:58:31 +08:00
Henry_Du
af00d57e68
feat: 发布更新时优先使用远程 Gitea 仓库的版本号
2026-08-16 11:54:29 +08:00
Henry_Du
4b972c3ae6
fix(display): 修复时刻表不显示的多个问题
...
- 将宽度阈值从 50 降低到 30,适配更小的 monitor
- 重构 schedule.entries 解析逻辑:兼容非纯数字索引(用 pairs 收集后排序)
- 修复视觉逻辑 bug:已到达站(浅灰) vs 未到达站(白) 颜色搞反
- 增加 schedule 为 nil/invalid 时的错误提示显示
- 增加调试日志输出 monitor 尺寸和提取到的站点数
- 版本号升级至 v1.0.65
2026-08-16 11:50:44 +08:00
Henry_Du
71f6800a2a
feat(display): 列车进站后在屏幕右侧显示时刻表信息
...
- 新增 Utils.extractAllStationsFromSchedule() 从时刻表提取所有站点
- 重构 Display.render() 实现左右分栏布局
- 列车存在且屏幕宽度>=50时启用右侧时刻表面板
- 使用颜色区分:已过站(浅灰)/当前站(绿色高亮+>)/未到站(白)/终点站(黄色+[END])
- 版本号升级至 v1.0.64
2026-08-16 11:45:37 +08:00
Henry_Du
b74eb252e3
feat: 在后端增加解析远程 Gitea 最新版本号的接口并展示在前端
2026-08-16 11:40:47 +08:00
Henry_Du
298308b7f3
fix(audio): 修复非高音质环境下 PCM 音频分片播放时的爆音问题
...
1. 移除 server.js 生成的每个音频分片携带的 44 字节 WAV 头,防止将其作为音频样本解码导致每 0.25 秒出现点击声 ('哒')。 2. 优化 playAudio 队列满时的轮询机制,从原先阻塞等待 speaker_audio_empty(会导致扬声器饥饿)改为使用 0.05 秒的定时器定期尝试,以保持缓冲区处于满载状态。 3. 同步修复了 station_broadcast-warning.lua 中潜在的相同轮询饥饿问题。 4. 版本号递增至 v1.0.62。
2026-08-16 11:32:00 +08:00
Henry_Du
6b1a531b77
fix(audio): 修复在没有高音质模块时,回退播放实时音频流产生刺耳噪音及可能导致卡死的问题
2026-08-15 23:30:09 +08:00
Henry_Du
2eddc9fefe
1.0.61
2026-08-15 23:13:10 +08:00
Henry_Du
51968cc825
fix(audio): 当扬声器不支持高音质时退回使用默认原版解码播放
2026-08-15 23:11:25 +08:00
Henry_Du
8f70c1f1d3
fix: 发车音乐列表过长时自动换行显示,修复 UI 溢出重叠问题
2026-08-04 13:13:03 +08:00
Henry_Du
d8eee041c8
feat: 明确音频优先级,优化发车音频触发时机
...
- 到达与发车最高优先级(3),其次是进站预告(2),然后是延误警告(1),最低为背景音乐(0)
- 将发车音乐的触发时机从固定时间改为动态计算(音频时长+1.5秒补偿),确保音频结束时列车刚好发车
- 拆分 handleTrainApproaching 与 handleTrainAlert 逻辑,解耦进站与延误的优先级
- 版本号提升至 v1.0.59
2026-08-04 13:00:04 +08:00
Henry_Du
01ac488aef
fix(client): 解决终端配置界面文字重叠与停站状态进站预告误报问题
...
1. 修复配置界面 UI 布局:当发车音乐可用列表过长时导致与后续输入提示重叠的问题,通过拆分显示并换行解决。
2. 彻底解决停站时误报进站预告:当 CC 电脑检测到当前站台已有列车停靠(`State.currentTrain ~= nil`)时,无论显示器上显示的是该站台的当前列车发车倒计时,还是被阻塞的下一班列车的到达倒计时,均强制抑制针对该站台的“进站预告”触发,直至站台被清空。
2026-08-04 11:29:45 +08:00
Henry_Du
c86fca8449
feat(client): 全面增强站名模糊匹配逻辑,支持中英文混排关键词提取
...
1. 新增 `Utils.getKeywords(text)`:自动提取所有关键信息:
- 包含中划线的字母数字组合(如 CE-03)
- 连续的字母数字(如 CRH01)
- 中文字符串,并在提取时自动过滤掉“站台”、“轨道”、“号”、“线”等噪音词。
2. 将 `Utils.getKeywords` 的匹配逻辑集成至 `Utils.isFuzzyMatch` 的最终校验中,即使在 `Utils.getBaseName` 无法精确比较的情况下,也能通过核心关键字(特别是纯中文关键字)判断两者是否为同一站台。
3. 将列车在站判定(`isAtStation`)对未知列车的目的站比较逻辑统一切换为使用强化的 `Utils.isFuzzyMatch`,保证时刻表、列车站名、NBT、显示器等来源的中英文站名信息均能互相精准匹配。
2026-08-04 07:42:57 +08:00
Henry_Du
6398146ee6
fix(client): 优化停站预告判断条件,彻底解决停站倒秒重复播报
...
修复由于列车时刻表中的目的站字符串与 NBT 或显示器获取到的目的地字符串不完全匹配,导致 `isAtStation` 判断失败的问题。
现在判断列车是否在站(`isAtStation`)主要依据 `trainName` 与 `State.currentTrain.id` 是否匹配。
对于未命名列车(如 ??? 或 Unknown),会额外通过模糊匹配或基础名称匹配目的地,从而保证当任何一列车在站台停留期间,系统正确识别它已停站,并忽略它因为离站倒数带来的 `etaSeconds > 0` 从而错误触发进站预告。
2026-08-04 07:37:11 +08:00
Henry_Du
86e58a5c59
feat(蜂鸣音频资源): 添加 fc2 至 fc14 共13个蜂鸣音效文件
2026-08-03 19:45:57 +08:00
Henry_Du
aa10f0ebe1
chore(server): 屏蔽 HLS RTMP 推流失败的错误日志
...
由于当前环境未配置 RTMP 服务器,当 ffmpeg 尝试推送音频流到 127.0.0.1:1935 时会一直报错 `Connection refused` 从而导致控制台刷屏。
现将该错误日志注释屏蔽,使控制台保持清爽。
2026-08-03 12:35:16 +08:00
Henry_Du
effcd30291
1
2026-08-03 12:33:59 +08:00
Henry_Du
3c25040a84
chore(client): 优化日志输出并清理测试代码
...
1. 引入全局 `CONFIG.DEBUG` 配置项(默认为 `false`),将所有 `Utils.log(DEBUG, ...)` 的大量扫描和推算日志默认隐藏,避免刷屏 CC 终端,需要时可通过配置文件开启。
2. 移除了排查 NBT 结构时添加的 `stop_dump.json` 导出逻辑,保持主机系统文件整洁。
2026-08-03 12:27:37 +08:00
Henry_Du
fdbcfa3b9b
fix(client): 优化停站时间获取,并在列车停站时禁用进站预告
...
1. 修复 `Utils.getStopTime` 和 `Utils.getNextStation` 会误匹配“非车站指令”(如修改最高速度等指令)中的文本的问题,现在仅在 `instruction.id == create:station`
或 `create:destination` 的条目中扫描,保证了 CC 电脑从 `create:track_station`
获取到的时刻表信息(包括计算出的停站时间)100% 准确。
2. 修复显示器(Display Board / NBT)在列车停站后依然显示“离站倒计时 ETA”,导致触发 `train_approaching` 的问题:如果当前列车已经在站内(`State.currentTrain` 存在且匹配),将强制忽略该列车的 `train_approaching` 触发逻辑,彻底解决列车停站时倒秒导致的重复播报。
2026-08-03 12:20:54 +08:00
Henry_Du
87fda31485
fix(client): 在 NBT 分支中也应用非车站指令过滤
...
将 `isStationDestination` 的过滤逻辑同时应用于 Block Reader(读取车站方块 NBT)的分支,
确保无论是通过显示屏还是 NBT 读取,都不会把“设置最高速度”等非停站指令当作列车进站播报。
同时已包含 `etaSeconds > 0` 修复,解决完全停站后重复播报的问题。
2026-08-03 12:09:08 +08:00
Henry_Du
f846004091
fix(client): 过滤非车站指令并修复列车停站后重复播报进站预告的问题
...
1. 新增 `isStationDestination` 过滤器,在通过显示屏(Create Target)读取时刻表时,
自动忽略包含“速度”、“重命名”、“时刻表”、“等待”、“卸载”等关键字的非车站指令,
防止将这些指令当作车站并错误触发进站预告。
2. 修复显示屏读取到的负数 ETA 被错误解析为正数的问题(增加可选负号匹配)。
3. 将触发进站预告的条件从 `etaSeconds >= 0` 修改为 `etaSeconds > 0`。
这样当列车完全停站(ETA=0或负数)时,将不再触发进站预告,彻底解决停站时间
超过冷却期后导致的重复播报“进站预告”的问题。
2026-08-03 12:04:13 +08:00
Henry_Du
439ed9ea3c
chore(client): 增加调试日志以导出 NBT stop 结构
...
用于排查非停站指令(如设置最高速度、新建时刻表区段)的 NBT 结构,
以便后续在代码中精准过滤这些非车站指令。
2026-08-03 11:28:32 +08:00
Henry_Du
eb018dbae9
fix(client): 修复多个同名同目的地的列车互相清除 pending 状态的问题
...
当存在多个列车(如无名列车 ??? 开往同一目的地)时:
- 第二个 ETA 较远的列车会因为 `etaSeconds > 45` 走进 `else` 分支
- 原逻辑在 `else` 分支会直接清空该 key 的 pending 状态
- 导致排在前面的列车永远无法积累 5 秒的稳定期
修改:
1. 移除 `else` 分支,统一交由末尾的清理循环处理
2. 使用 `if not seenApproachKeys[announceKey]` 确保同一个 tick 只有 ETA 最近(排最前)的列车更新状态
2026-08-03 11:14:40 +08:00
Henry_Du
619d4e9a20
杂项(station_broadcast): 更新版本至v1.0.50并添加列车ETA调试日志
...
该调试日志会打印列车名称、ETA秒数、计时tick数及服务器tick率,仅在列车ETA不超过60秒且未触发过接近播报时输出,用于辅助排查列车接近播报的逻辑问题
2026-08-03 11:09:44 +08:00
Henry_Du
3c71d64f79
chore(station_broadcast): 升级版本至v1.0.49并调整ETA触发阈值
...
调整列车接近播报的ETA更新阈值,从3秒改为15秒以减少频繁触发
2026-08-03 10:40:12 +08:00
Henry_Du
a36b21cfaf
fix(server): 完善列车接近音频的处理与日志记录
...
新增列车接近音频入队和构建失败的日志输出
调整音频任务优先级为1,中断模式改为ifLower
修复音频构建为空时的静默失败问题
2026-08-03 10:22:04 +08:00
Henry_Du
101d392840
fix(CloudServer/server): 修复列车接近处理的ch序列遗漏的站台编号参数
2026-08-03 09:59:58 +08:00
Henry_Du
c8681417a8
refactor(音频模块): 重构wav音频播放与解码逻辑
...
移除冗余的流式wav解码工具函数,复用现有decodeWavChunkToSamples
简化playChunkOnSpeakers实现,移除固定帧拆分逻辑与无用常量
优化音频日志与错误处理,解码失败时回退至HQ播放路径
调整应用版本号从v1.0.50回退至v1.0.47
2026-08-03 09:51:33 +08:00
Henry_Du
bf1895ebc5
perf(audio): 优化音频播放帧处理逻辑,升级版本至v1.0.50
...
- 为test.lua添加标准文件头部注释
- 将station_broadcast.lua版本从v1.0.49更新至v1.0.50
- 新增NATIVE_AUDIO_FRAME_SAMPLES常量,将音频处理拆分为128样本每帧
- 修复空音频样本输入的边界异常问题
- 优化原生扬声器播放的循环逻辑,提升兼容性与执行效率
2026-08-03 09:49:01 +08:00
Henry_Du
394f81b9fa
1
2026-08-03 09:39:00 +08:00
Henry_Du
5fb81e3998
feat(audio): 实现流式WAV解码器并优化音频播放逻辑
...
将应用版本更新至v1.0.48;新增WAV头部解析与流式解码逻辑,替换原有的单块解码方案;添加扬声器speakWav兼容性检测,无支持设备时输出错误日志;优化WAV解码错误处理与日志输出,仅首次打印音频格式信息。
2026-08-03 09:37:00 +08:00
Henry_Du
e89b82a8b4
1
2026-08-03 09:27:51 +08:00
Henry_Du
5dbd3d667f
fix: restore speaker peripheral detection
...
Re-add speaker discovery during peripheral init so installed speakers are available for playback and log the detected count at startup.
2026-08-03 09:24:58 +08:00
Henry_Du
6964e7a47d
refactor(station_broadcast): 清理冗余代码与注释,移除无用文件并更新gitignore
...
- 清理station_broadcast.lua中的冗余注释、废弃代码块,移除无用的节分隔注释
- 删除不再使用的austream.lua文件
- 更新.gitignore,新增临时文件与转储文件的忽略规则
2026-08-02 22:03:06 +08:00
Henry_Du
59865138c7
11
2026-08-02 21:26:41 +08:00
Henry_Du
b2888c6c88
chore(安装脚本与文档): 修改安装脚本下载源并新增教程视频
...
将install_station_broadcast.lua中的旧下载地址替换为gitea仓库的https新源,同时新增FSE铁路广播系统教程视频文件
2026-08-02 21:24:57 +08:00
Henry_Du
aef63ca444
fix: install updater alongside startup script
...
Download the update helper during install and expose it from the cloud server so new hosts can run manual updates immediately.
2026-08-02 21:20:28 +08:00
Henry_Du
10d15dfddc
feat: add station auto update publishing
...
Publish the latest station script from the console so online hosts download and reboot immediately while offline hosts update on their next load.
2026-08-02 20:04:55 +08:00
Henry_Du
52a643a868
tune: shorten delay alert confirmation to 15 seconds
2026-08-02 19:48:01 +08:00
Henry_Du
e29cc0c2ba
tune: trigger approaching announcement earlier
2026-08-02 19:34:27 +08:00
Henry_Du
73f0ba8e69
tune: trigger stable approaching announcement at 45 seconds
2026-08-02 19:29:26 +08:00
Henry_Du
22ea43c1c1
tune: stabilize approaching trigger and show precise ETA
2026-08-02 19:25:57 +08:00
Henry_Du
fb1256fbcc
tune: add delay confirmation and approaching cooldown
2026-08-02 19:22:01 +08:00
Henry_Du
04591fc0c8
fix: dedupe delay alerts to reduce music stutter
2026-08-02 19:19:00 +08:00
Henry_Du
906594008a
fix: remove ch-min from delay announcement
2026-08-02 19:06:20 +08:00
Henry_Du
126aaaf02f
fix: trigger delay alerts from displayed CRN delay
2026-08-02 19:04:10 +08:00
Henry_Du
278de7de6b
feat: announce delay alerts as soon as they appear
2026-08-02 18:58:54 +08:00
Henry_Du
ea22c79008
fix: rename Japanese delay reason audio files
2026-08-02 18:52:43 +08:00
Henry_Du
39dc446958
功能(站点广播): 实现延误与停运列车的双语广播功能
...
添加所有中日文广播所需的音频资源文件
将应用版本更新至v1.0.37
修复列车状态原因映射逻辑,补充广播所需的缺失字段
实现根据延误、停运状态生成对应双语广播序列的逻辑
更新测试脚本以适配区块阅读器并正确解析CRN的NBT数据
添加示例NBT转储文件作为参考
2026-08-02 18:50:49 +08:00
Henry_Du
f922ace154
fix: trigger approaching broadcast under 30 seconds
2026-08-02 17:42:49 +08:00
Henry_Du
b7be4cd00d
fix: use NBT ETA and clean monitor debug output
2026-08-02 17:33:05 +08:00
Henry_Du
9060e79006
fix: use earlier realtime tick for arrival ETA
2026-08-02 17:14:51 +08:00
Henry_Du
426e55a7f0
fix: normalize upcoming ETA keys before text override
2026-08-02 17:11:31 +08:00
Henry_Du
db818209f2
debug: show raw create target line and eta fields
2026-08-02 17:08:59 +08:00
Henry_Du
a1db54b295
fix: parse CRN ETA as value plus unit
2026-08-02 17:05:53 +08:00
Henry_Du
96222ebf06
debug: expand text ETA parsing and show raw eta string
2026-08-02 17:03:43 +08:00
Henry_Du
9f2dc5bb3d
debug: compare text and NBT ETA keys on monitor
2026-08-02 17:00:24 +08:00
Henry_Du
4b95c86af6
fix: align NBT destination with CRN display stopovers
2026-08-02 16:55:15 +08:00
Henry_Du
432b82eae9
feat: prefer CRN display ETA text when available
2026-08-02 16:48:42 +08:00
Henry_Du
23196cd59d
fix: compute ETA using measured tick rate
2026-08-02 16:44:12 +08:00
Henry_Du
ea288b6572
feat: show delay reason/status from CRN NBT on monitor
2026-08-02 16:41:01 +08:00
Henry_Du
61576a7d9e
fix: detect advanced peripherals block reader by type or method
2026-08-02 16:33:50 +08:00
Henry_Du
b725c74e1d
debug: add upcoming trains data probe
2026-08-02 16:31:07 +08:00
Henry_Du
c13a0c9dcc
fix: avoid monitor log overlap and show upcoming status
2026-08-02 16:24:32 +08:00
Henry_Du
5134a4ebf0
fix: restore main loop block structure
2026-08-02 16:22:44 +08:00
Henry_Du
544179758e
fix: restore goto label required by earlier logic
2026-08-02 16:19:56 +08:00
Henry_Du
95e550441e
fix: ensure trailing newline at end of file
2026-08-02 16:17:33 +08:00
Henry_Du
8a431147ec
fix: remove unused goto continue label causing lint error
2026-08-02 16:15:23 +08:00
Henry_Du
d28b0eec30
fix: correctly assign State.upcomingTrains before display link fallback
2026-08-02 16:10:52 +08:00
Henry_Du
ad70f4adbc
feat: display upcoming trains and delay info on monitor
2026-08-02 16:07:48 +08:00
Henry_Du
e92348b4db
feat: add real-time ETA interpolation for block reader
2026-08-02 16:04:41 +08:00
Henry_Du
13dc054a01
feat: use block reader for accurate ETA and delay data
2026-08-02 15:57:14 +08:00
Henry_Du
c573260e5d
feat: Implement exact 45s pre-arrival broadcast by delaying 1min signal
2026-08-02 14:59:07 +08:00
Henry_Du
dbf259efe5
fix: Re-enable train pre-arrival broadcast on '1 min' to provide sufficient advance notice
2026-08-02 12:08:16 +08:00
Henry_Du
5c899b30bb
fix: Trigger train pre-arrival broadcast only on '现在' or '0' instead of '1 min'
2026-08-02 12:02:44 +08:00
Henry_Du
53b4d1b296
fix: Reduce train pre-arrival debounce timeout to 1 minute
2026-08-02 11:57:57 +08:00
Henry_Du
b52776fe09
fix: Reduce train pre-arrival debounce timeout to 2.5 minutes
2026-08-02 11:56:20 +08:00
Henry_Du
43a2a4deaf
fix: Increase train pre-arrival debounce timeout to 5 minutes to prevent multiple broadcasts for fuzzy ETA
2026-08-02 11:54:23 +08:00
Henry_Du
712d8bb84d
fix: Ensure platform is stripped of non-digit chars for audio file matching
2026-08-02 11:52:27 +08:00