meshcli: Meshtastic MQTT 纯 CLI 聊天客户端(数据包解码参考 meshtastic_mqtt_server)

This commit is contained in:
dsh
2026-08-20 20:55:06 +08:00
commit 7beecfc7ce
7 changed files with 1131 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
# meshcli — Meshtastic MQTT 纯 CLI 聊天客户端
纯命令行 Meshtastic MQTT 客户端:连接 MQTT broker,订阅频道流量,解码 Meshtastic 数据包(含 AES-CTR 频道加密),实现频道聊天。
协议实现参考 [meshtastic_mqtt_server](https://git.lmve.net/kevin/meshtastic_mqtt_server)MIT License):
ServiceEnvelope / MeshPacket / Data 均为 protobuf wire 格式手写解析(`google.golang.org/protobuf/encoding/protowire`),加密包用频道 PSK + AES-CTR 解密。
## 构建
需要 Go 1.25+
```bash
go build -o meshcli .
```
## 用法
```bash
# 交互式聊天(默认连 mesh.lmve.netmeshdev/large4cats
./meshcli
# 完整参数
./meshcli \
-server mesh.lmve.net -port 1883 \
-user meshdev -pass large4cats \
-psk AQ== \
-prefix msh/CN -channel LongFast \
-node-id !1234abcd -name "CLI 聊天" -short CLIC \
-announce
# 单发模式:发一条消息后退出
./meshcli -send "大家好"
# 私聊(PSK 频道直发,需对方同频道)
./meshcli -to !501492cf -send "你好"
# 显示全部数据包(位置/遥测/节点信息等)
./meshcli -verbose
```
### 参数
| 参数 | 默认值 | 说明 |
| --- | --- | --- |
| `-server` | `mesh.lmve.net` | MQTT broker 地址 |
| `-port` | `1883` | MQTT 端口 |
| `-user` / `-pass` | `meshdev` / `large4cats` | MQTT 连接认证 |
| `-psk` | `AQ==` | 频道 PSKBase64`AQ==` 为 Meshtastic 默认密钥索引 1|
| `-prefix` | `msh/CN` | MQTT topic 前缀 |
| `-channel` | `LongFast` | 频道名 |
| `-node-id` | 随机生成 | 本机节点 ID`!xxxxxxxx`|
| `-name` / `-short` | `MeshCLI` / `MCLI` | 节点 Long/Short Name |
| `-announce` | `true` | 连接后广播一次节点信息(NODEINFO_APP|
| `-to` | 广播 | 私聊目标节点 ID |
| `-send` | 空 | 发送一条消息后退出 |
| `-verbose` | `false` | 显示位置/遥测/节点信息等全部数据包 |
## 交互命令
| 命令 | 说明 |
| --- | --- |
| `/help` | 显示帮助 |
| `/who` | 列出已见到的节点 |
| `/name <名字>` | 修改本机名字并重新广播 |
| `/to !xxxxxxxx` | 设置私聊目标(PSK 频道直发)|
| `/to 广播` | 恢复频道广播 |
| `/quit` | 退出 |
## 实现要点
- **订阅**`<prefix>/2/e/#`(如 `msh/CN/2/e/#`),覆盖全部频道与节点
- **发送**:发布到 `<prefix>/2/e/<channel>/!<本机节点>`,包体为加密的
`ServiceEnvelope { MeshPacket { Data { portnum=TEXT_MESSAGE_APP } } }`
- **加密**AES-CTRnonce = little-endian(packetID 8B) + little-endian(from 4B) + 4B 零;
MeshPacket.channel = xor(频道名) ^ xor(PSK)
- **解码**:文本消息、节点信息(用于显示名字)、位置(`-verbose`);其他类型摘要显示
- **私聊说明**`-to` 走 PSK 频道加密直发(非 PKI 端到端加密),仅对同一频道的节点可见
## 测试记录
实测连接 mesh.lmve.netmeshdev/large4cats):
- 订阅 `msh/CN/2/e/#` 成功;
- 发送 `meshcli命令行客户端连接测试` 后经 broker 中转正确解密回显(`!6fa5b924`);
- broker 侧 `text_message` 正常入库(id 1274598),NODEINFO 广播也正常入库。