很多人刚开始用 Meshtastic 的时候,会默认以为消息天然就会一直在那里等着自己。可它更像电视直播,而不是点播视频。你要在电视开着的时候,才能看到当下正在播的节目;如果那时候电视没开,节目播过去了,后面就不会自动补给你看。
Meshtastic 里的消息,在很多时候也是类似的逻辑。你在线时收到,离线时没收到,那一段内容很可能就这么过去了。可一旦你开始认真部署节点,尤其是山顶节点、楼顶节点、车载节点、手持节点混着用的时候,这个问题很快就会冒出来。比如你刚好下山、进楼、进电梯,或者一段时间离开了 LoRa 覆盖范围,等你重新回到网络里时,就会发现中间那段消息已经不在自己设备的缓存里了。
Store & Forward 模块解决的,正是这种临时掉线后的补消息问题。简单说,它允许一台专门的服务器节点帮你暂存收到的文本消息;当客户端设备重新回到覆盖范围内,就可以向这台服务器请求历史消息,把自己错过的那一段补回来。
这个功能不是每个人都必须开,但如果你的网络里已经有固定常在线的高位节点,或者你经常让部分设备临时离网再回来,它就会非常有价值。很多人搭了基础设施节点之后,最先补上的往往不是更远的天线,而是这一类让网络更像网络的辅助能力。
Store & Forward 到底是做什么的
Store & Forward 的核心思路并不复杂。网络里有一台特殊的 Store & Forward Server,它会把自己收到的文本消息存起来。当某台客户端设备回来之后,它可以向这台服务器请求一段时间窗口内的历史消息,服务器再通过 LoRa 把这些文本消息重新发出来。
这件事和设备本地那几十条左右的普通缓存不是一回事。自从 Meshtastic 2.4 之后,当你用客户端 App 连接到 Store & Forward Server 本机时,历史消息会自动拉取回来,容量通常也会比设备本地默认缓存大得多。所以它更像是给网络加了一个专门负责补课的消息中转站,而不是单纯把缓存再做大一点。

Store & Forward 并非万能,有两点要注意
- Store & Forward 只知道自己收到了哪些消息,并不知道你到底漏了哪几条,所以补回来的内容可能会有重复
- 第二,请求历史消息时,服务器可能在短时间内重发很多文本消息,这会给整张 Mesh 带来一波额外负载,因此不能毫无节制地频繁拉历史。
这个功能最适合的,不是完全静止不动的单机使用,而是网络里已经有一个相对稳定的常在线节点(比如枢纽节点),另一部分节点会临时离开覆盖范围再回来(比如手持节点)。
最典型的例子,就是楼顶或者山顶放着一台常年在线的节点做基础设施,手里的手持节点白天移动、晚上回来;又或者你有一台阳台基站常年在线,出门携带的设备中途经过信号盲区,回家以后再把错过的文本消息补回来。再比如测试环境里两台普通客户端互相发消息,第三台固定服务器节点帮忙存档,这样其中一台临时掉线后,回来还能主动索取历史。
如果你的网络里没有常在线节点,或者服务器自己也经常离线,那 Store & Forward 的效果就会打折。因为服务器一旦自己漏收消息,它当然也就没法帮你补回来。
Store & Forward Server 不是随便一款 Meshtastic 设备都能做。它必须是基于 ESP32 的设备,并且板载带有 PSRAM。
如果设备没有这部分硬件条件,就不要先急着在配置里找开关,因为就算你把模块打开了,它也不一定能稳定承担服务器角色。
Store & Forward 是给有条件的基础设施节点准备的功能,而不是给所有手持和低功耗节点默认打开的通用模块。
这个功能大概怎么搭起来
如果你想通过 LoRa 方式直接测试 Store & Forward(简称 SF),最好准备至少三台设备。
一台是带 PSRAM 的 ESP32 节点,用来做 SF 服务器;另外两台是普通客户端 client。其中一台在另一台不在线的时候发文本消息,等离线那台重新回到范围后,再向服务器请求历史消息,看能不能把漏掉的内容补回来。
如果你是配合手机客户端来体验这个功能,最少两台设备也够。一台是 Store & Forward Server,另一台负责在你没有连接 App 到服务器时发送文本消息。之后你再用 App 连接到这台服务器,自 2.4 之后,历史消息会自动被取回并显示出来。
无论哪种用法,服务器节点都应该尽量保持长期在线。Store & Forward 不是一个适合轮流开关机的功能,服务器自己漏消息越多,客户端能补回来的内容就越不完整。
服务器怎么配置
你可以在模块里直接把 store_forward.is_server 设为 true,也可以把节点配置成 ROUTER。
我会建议先从 store_forward.is_server 设置开始。
两种思路都能让这台节点承担服务器角色,而 is_server 这种方式是 2.4 之后才有的。
更实用的建议是,给这台节点起一个一眼就能认出的名字,比如在节点名里带上 S&F 或者 Store,这样以后在节点列表里比较容易认出来。
真正要开的基础配置其实不多,最关键的是先启用模块:
meshtastic --set store_forward.enabled true
如果你确定客户端已经知道这台服务器是谁,或者你主要是通过 App 直接连接到服务器本机来取历史,而不是靠它在网络里持续广播存在感,那还可以考虑关闭 heartbeat,减少额外流量:
meshtastic --set store_forward.heartbeat false
heartbeat 默认会周期性告诉网络里其他设备,附近有一台 Store & Forward Server 在监听消息。这个机制有用,但在一些本来就比较忙的网络里,能少一类周期广播就少一类,所以很多人实际部署时会把它关掉。
客户端怎么取回历史消息
现在这个功能在 Android 和 Apple 客户端上都已经有可用支持,文档里提到的版本门槛是 2.2.23 及以上。
Android 的做法比较直接。如果你要通过 LoRa 主动向服务器索取历史,需要给那台 Store & Forward Server 发一条私信,内容就是 SF。服务器收到之后,就会把你请求范围内的历史文本消息重新发出来。
苹果端的体验更图形化一些。只要设备先听到了服务器的 heartbeat,它就能在节点列表里把这台节点显示为 Store & Forward Server。之后你可以长按这个节点,选择 Client History 来请求历史消息。
另外,自从 2.4 之后,如果你不是通过 LoRa 命令去索取,而是客户端 App 直接连接到了 Store & Forward Server 本机,那么历史消息会自动取回并显示出来。这也是为什么很多人把它和固定基站放在一起用时,体验会明显比纯设备本地缓存更好。
需要注意的是,通过 LoRa 请求历史消息这件事,在默认公共频道上并不可用。所以如果你准备认真测试,最好是在自己的网络环境里做,不要直接拿默认公共频道去试。
配置项到底该怎么理解
Store & Forward 的配置项不算多,但每一个都和网络负载或者消息保留能力直接相关,所以值得单独讲清楚。
Enabled 很简单,就是开关本身,决定这个模块是否启用。
Heartbeat 控制服务器是否周期性往网络里发送存在告知。它的意义是让 Android、iOS、Web 这一类客户端知道附近有可用的 Store & Forward Server,但代价就是会增加一点周期性流量。
History Return Max 是客户端每次请求历史时,服务器最多返回多少条消息。默认值写成 0 时,实际表示使用默认上限,也就是 25 条。这个值越大,单次补回来的消息越多,但给网络带来的瞬时压力也越大。
History Return Window 是客户端允许请求的时间窗口,单位是分钟。默认 0 表示 240 分钟,也就是 4 小时。你可以理解成,客户端一次最多能向服务器追溯多长时间范围内的消息。
Records 决定服务器最多保存多少条记录。默认写成 0 时,模块会自动使用设备可用 PSRAM 的三分之二。文档给出的量级大约是 11000 条记录,这也是为什么服务器必须依赖带 PSRAM 的设备。
Is Server 是把这台节点直接指定为 Store & Forward Server 的开关。它是把节点设为 ROUTER 之外的另一种配置方式,只在 2.4 及以后的版本里可用。
参数怎么取值,并没有适合所有网络的一套万能答案。节点少、消息少的网络,可以放宽一点;节点多、流量重的网络,通常就该保守一些,尤其别把历史窗口和返回上限同时拉得太夸张。
不同客户端从哪里配置
Android 端已经提供 Store & Forward 的配置页面,入口在 Settings > Store & Forward。
Apple 端在 iOS、iPadOS 和 macOS 上都提供完整配置,入口是 Settings > Module Configuration > Store & Forward。
Web 端同样可以配置全部相关选项,位置在 Config > Module Config > S&F。
CLI 则最适合做精确控制,尤其是你已经习惯用命令行改模块参数的时候。对应的主要字段如下:
| 配置项 | 可接受值 | 默认值 |
|---|---|---|
store_forward.enabled |
true / false |
false |
store_forward.heartbeat |
true / false |
false |
store_forward.history_return_max |
integer |
0,表示默认 25 条 |
store_forward.history_return_window |
integer |
0,表示默认 240 分钟 |
store_forward.records |
integer |
0,约 11000 条记录 |
store_forward.is_server |
true / false |
false |
文档里还特别提醒了一点:CLI 每发一条配置命令,设备通常都会重启一次。所以如果你要连续改同一组配置,最好把命令串起来一次发完,不然来回重启会很拖,也容易出错。比如:
meshtastic --set store_forward.enabled true --set store_forward.history_return_max 0
实际部署时最容易踩的坑
第一个坑,是把一台并不稳定在线的节点当成服务器。Store & Forward 的前提就是服务器比别人更稳定,如果它自己也时断时续,那你指望它帮别人补消息,效果自然不会好。
第二个坑,是忽视网络负载。服务器需要把大量信息通过 LoRa 发一遍。你把窗口开太大、返回条数设太高,短时间内就可能让 mesh 网络过载。
第三个坑,是误以为它能精确知道你漏了哪些消息。实际上服务器只会按请求条件重发自己存到的文本消息,它并不知道客户端到底缺哪几条,所以收到重复消息是正常现象,不是功能出错。
第四个坑,是在默认公共频道上测试 LoRa 历史请求。文档已经明确写了,这种请求方式在默认公共频道上不可用。
总结
Store & Forward 不是那种装上就立刻让信号变远的功能,但它能明显改善网络的可用性。
尤其是当你的网络里已经有一两台长期在线的固定节点,而其他节点会临时离网再回来时,它能把很多原本会断掉的文本消息重新补回来。
本文作者: Hays Chan | 陈希
本文链接: https://meshcn.net/store-and-forward-meshtastic-tutorial/