4、应用层协议(一):信息发布协议、文本信息格式定义、信息优先级机制、信息生命周期管理。

各位好,咱们今天聊聊PIS系统里最贴近“人”的一层——应用层协议。说白了,就是信息怎么从后台走到乘客眼前的屏幕上的。这部分内容,我个人觉得是整个PIS系统的灵魂。你想想看,硬件再牛,网络再快,如果信息发不出来、显示不对、优先级乱套,那一切都是白搭。

今天这一讲,我们聚焦四个核心点:信息发布协议文本信息格式定义信息优先级机制,以及信息生命周期管理。嗯,内容有点多,但都是干货,咱们一个一个来啃。

4.1 信息发布协议:谁说了算?

信息发布协议,就是定义“谁”能发信息、“怎么”发、“发给谁”的一套规则。在轨道交通里,信息发布源通常有这几个:

  • 中心级ATS(自动列车监控系统):比如列车晚点、下一站预告,这是最高级别的自动触发源。
  • 运营调度员工作站:人工发布的紧急通知、临时变更。
  • 车站级PIS服务器:本地缓存的信息,或者车站值班员手动发布的公告。
  • 第三方系统:比如气象预警、反恐联动信息。

我参与过一个项目,当时就遇到一个问题:中心ATS和车站本地同时发了一条“列车晚点”信息,结果屏幕上两条信息打架,一会儿显示中心的数据,一会儿显示车站的数据,乘客看得一头雾水。后来怎么解决的?就是靠协议里明确了一个“发布源优先级”字段。

协议里一般会这样定义发布消息的帧结构(简化版):

| 字段名        | 长度(字节) | 说明                          |
|---------------|------------|-------------------------------|
| 消息头        | 4          | 固定标识,比如0xAA55          |
| 发布源ID      | 2          | 0x01=中心ATS, 0x02=调度台...  |
| 目标终端组    | 4          | 位掩码,指定哪些屏幕接收      |
| 信息类型      | 1          | 0x01=文本, 0x02=图片...       |
| 优先级        | 1          | 0-255,数值越大优先级越高     |
| 时间戳        | 4          | Unix时间戳                    |
| 信息体长度    | 2          | 后续信息体的字节数            |
| 信息体        | 可变       | 具体内容(文本、图片URL等)   |
| 校验和        | 2          | CRC16                         |

你看,这个结构里,发布源ID优先级是分开的。为什么?因为同一个发布源也可以发不同优先级的信息。比如调度员发一条“列车晚点10分钟”是普通优先级,发一条“紧急疏散”就是最高优先级。这个设计,我个人觉得非常合理。

我的小建议:在实际项目中,发布源ID的分配一定要提前规划好,最好做成可配置的。我曾经见过一个项目,把发布源ID写死在代码里,结果后期新增了一个应急广播系统,不得不升级所有终端固件,那叫一个折腾。

4.2 文本信息格式定义:屏幕上的“字”怎么排?

信息发出来了,但屏幕怎么显示?这就涉及到文本信息格式定义了。别小看这个,格式没定好,屏幕上可能出现乱码、文字重叠、或者信息被截断。

我们通常用XMLJSON来定义文本信息的格式。我个人更倾向于JSON,因为它轻量、解析快,适合嵌入式终端。下面是一个典型的文本信息格式定义:

{
  "msg_id": "202405201530001",
  "type": "text",
  "priority": 100,
  "content": {
    "lines": [
      {
        "line_index": 0,
        "text": "尊敬的乘客,您好!",
        "font_size": 24,
        "font_color": "#FFFFFF",
        "alignment": "center",
        "scroll": "none"
      },
      {
        "line_index": 1,
        "text": "开往 蓝海站 的列车即将进站",
        "font_size": 32,
        "font_color": "#00FF00",
        "alignment": "center",
        "scroll": "left_to_right",
        "scroll_speed": 50
      },
      {
        "line_index": 2,
        "text": "请先下后上,注意安全",
        "font_size": 20,
        "font_color": "#FFFF00",
        "alignment": "left",
        "scroll": "none"
      }
    ],
    "background_color": "#000080",
    "display_duration": 10
  },
  "valid_time": {
    "start": "2024-05-20 15:30:00",
    "end": "2024-05-20 16:00:00"
  }
}

这里有几个关键点,我重点说一下:

  • 行索引(line_index):决定了文字在屏幕上的垂直位置。0是顶部,依次往下。注意,不同屏幕尺寸的行数上限不一样,协议里要约定好最大行数。
  • 滚动方式(scroll):常见的有“none”(静态)、“left_to_right”(左移)、“up_down”(上下滚动)。滚动速度(scroll_speed)一般用毫秒/像素表示,数值越小滚动越快。
  • 显示时长(display_duration):这条信息在屏幕上停留多久。单位是秒。如果设为0,表示一直显示直到被新信息覆盖。
注意:我曾经在一个项目里踩过坑——字体颜色用了RGB值,但终端屏幕是16位色深的,结果颜色显示完全不对。后来我们统一在协议里规定:颜色值必须使用标准的24位RGB(#RRGGBB),终端自己负责做色深转换。这个坑,大家一定要避开。

4.3 信息优先级机制:谁先上屏?

优先级机制,是PIS系统里最容易出问题的地方。为什么?因为信息太多了!ATS发一条、调度员发一条、车站再发一条,屏幕就那么大,到底显示谁?

我们通常采用数值优先级机制,数值越大优先级越高。一般会划分几个等级:

优先级数值 等级名称 典型应用场景
255 紧急 火灾疏散、恐怖袭击警报
200 重要 列车故障、大面积晚点
100 普通 日常到站信息、换乘指引
50 低优先级 广告、公益宣传
0 背景 时钟、日期等常驻信息

这里有个关键规则:高优先级信息可以抢占低优先级信息的显示位置。但抢占之后,低优先级信息怎么办?是丢弃还是排队?这就引出了下一个话题——信息生命周期管理。

我记得有一次,某地铁线路的PIS系统在早晚高峰时,广告信息(优先级50)和到站信息(优先级100)频繁交替显示,导致屏幕一直在“闪烁”。后来排查发现,是终端在处理优先级抢占时,没有做“防抖”处理。解决方案很简单:设置一个最小显示时间,比如一条信息至少显示3秒,才能被更高优先级的信息抢占。这样既保证了紧急信息的及时性,又避免了屏幕频繁闪烁。

核心原则:优先级机制的设计,要兼顾“及时性”和“稳定性”。不能为了及时而让屏幕乱闪,也不能为了稳定而延误紧急信息。这个平衡点,需要在项目调试中反复打磨。

4.4 信息生命周期管理:信息从生到死

一条信息从产生到消失,经历哪些阶段?这就是生命周期管理要解决的问题。我把它分为四个阶段:

  1. 创建:信息被发布源生成,并发送到PIS服务器。
  2. 分发:服务器根据目标终端组,将信息推送到对应的终端。
  3. 显示:终端根据优先级和当前显示状态,决定是否显示这条信息。
  4. 消亡:信息被新信息覆盖、过期、或者被手动删除。

这里最容易被忽视的是“消亡”阶段。很多系统只定义了“如何显示”,没定义“如何消失”。结果就是,一条“列车晚点”信息在屏幕上挂了三天,乘客都以为还在晚点呢。

所以,协议里必须包含有效时间(valid_time)字段,就像前面JSON示例里的那样。终端要定期检查当前时间是否在有效期内,如果过期了,自动清除这条信息。

另外,还有一种情况:信息被更高优先级的信息覆盖后,当高优先级信息消失时,低优先级信息要不要恢复显示? 我个人建议:不要自动恢复。为什么?因为低优先级信息可能已经过时了。比如一条“列车晚点10分钟”的信息,被“紧急疏散”覆盖了,等疏散结束,晚点信息可能已经失效了。所以,更合理的做法是:高优先级信息消失后,终端重新从服务器拉取当前有效的所有信息,重新排序显示。

避坑指南:我曾经在一个项目里,把信息生命周期管理做得太复杂——支持了“定时发布”、“循环发布”、“条件触发发布”等等。结果终端代码变得非常臃肿,还经常出bug。后来我学乖了:生命周期管理尽量在服务器端做,终端只负责“接收-显示-过期清除”这三步。终端越简单,系统越稳定。

好了,今天的内容就到这里。信息发布协议、文本格式、优先级、生命周期,这四个点环环相扣,构成了PIS应用层协议的基石。下一讲,我们会继续深入,聊聊图片、视频、以及多语言信息的发布。到时候见。