
一个支持使用OpenDHT代理作为后端的Mesh路由系统,使得节点可以通过互联网直接通信。非常早期的预alpha阶段,概念验证,可能实际上无法工作,等等。
它既适用于业余爱好/火腿(HAM)应用场景,也适用于更典型的消费/商业物联网工作,但明确不试图取代互联网,也不试图用全向天线覆盖高流量大面积区域。
它没有Meshtastic式的下一跳路由,因此得名LazyMesh。如果你想在密集区域将其用于离网类应用,可能需要定向天线和手动协调的路由ID。
目前这是唯一实际的应用。打开示例Arduino草图,用你的用户名和必须为强密码的秘密通道密钥进行修改。
在Arduino串行监视器中输入你的消息,你应该能够与所有其他设备聊天。
只要节点位于同一网络或两者都有互联网接入,消息就应该能够送达。
访问 网页客户端 通过MQTT从互联网与节点聊天。只需设置用户名,添加频道,并输入频道密码。频道名称可以是任何内容,仅影响UI中的标签。
你也可以尝试读取/写入数据示例草图。它将数据ID 195暴露为可读,数据ID 196暴露为可读可写。前往网站,输入你的频道详情,使用数据请求对话框向所有设备请求ID 196。
然后点击"设置"并将其设置为其他值,再尝试读取它。
网页客户端目前硬编码使用test.mosquitto.org,这将在未来改变。
节点需要某种方式来同步时间以进行通信。目前,如果它们从未从可信来源接收到时间,它们将从看到的任何随机数据包设置时间。
这可能是一个允许重放攻击的安全风险,因此需要安全性的设备应具有可信的时间源。
一旦时间初始设置,代码将每天调整其系统时间最多1秒以与其他节点保持同步,因此不同步漂移不应成为主要问题。
在Lazymesh中,一切都是频道,没有直接消息。如果你想要,只需创建一个专用的私有频道。
频道由密码定义,知道密码即可获得读写权限。
有256个路由编号。每个数据包都有一个,中继器仅在启用了匹配的路由编号时才进行中继。默认情况下,所有数据都以路由编号0发送,该编号默认启用。
这仅影响中继器,节点将监听任何直接发给它们的网格路由编号。
数据包负载是MessagePack数组。它们交替整数数据ID和数据项。192-256保留给应用特定消息。
ID 32用于文本消息,可以带用户名和冒号前缀。
ID 2用于唯一ID,必须是整数。许多应用可能根本不需要它。
附加一个元数据长度字节和N字节的元数据。
要创建IV,取12个随机字节作为IV。然后加密整个内容。在开头添加IV,末尾添加4个认证标签字节。
然后取路由ID哈希的前8个字节并转换为十六进制。
MQTT主题将是 lazymesh_route_HEX
注意我们使用顶级主题。这是为了防止你可以在公共代理上使用通配符一次性订阅所有lazymesh频道,这将使你能够相当容易地DoS所有人。
只是在224.0.0.251:2221上广播的原始数据包
对此没有任何东西是最终确定的!!!
All numbers are little-endian.
1 byte header:
2 bit packet type(Either 1 or 2, depending on if we want ACK)
3 bits TTL hops remaining
1 bit allow slow transport(LoRa etc)
1 bit allow global routing
1 bit was already global routed
1 byte header 2:
1 bit first send attempt:
Whenever we create a or recieve a packet, set this bit. After trying to send it,
clear it. This way, as long as we assume packet loss is low-ish, we can count the repeaters in the area
without extra overhead.
1 bit repeater bit:
Marks that this packet should be included when counting repeaters.
Set it if you would repeat the packet or one like it, even if you originated it.
1 bit interest bit:
If this is set, the node who sent it is directly interested in the channel,
not purely just a repeater. If first send is also set, it is treated as an
implicit ack
1 bit location enabled
If this bit is set, repeaters may add location metadata to the packets forwarded to the internet. This metadata must be encrypted with the routing ID as the key,
meaning nearby people could track you for 1 hour after you get out of range.
Not implemented anywhere at the moment.
5 reserved 0 bits
1 byte mesh route number
1 byte path loss accumulated:
5 bits total
3 bits last hop
Every hop is a point of path loss,
plus whatever extra cost heuristic the transport applies.
1 extra point of loss should be roughly the same "badness" as
10dbm extra loss on wifi.
16 bytes routing ID:
Changes every hour, derived from the channel PSK by a hash.
The PSK is just the 16 byte SHA256 of the password.
The routing ID changes hourly, and is the SHA256 of:
The letter 'cr'
The count of hours since 1970 as a 32 bit unsigned int
the PSK
8 Bytes random entropy:
Used as part of the IV for the cipher
4 bytes timestamp:
Also part of the IV, also prevents replay attacks
N bytes ciphertext:
AES-GCM encrypted.
The encryption key changes hourly, and is the SHA256 of:
The letter 'c'
The count of hours since 1970 as a 32 bit unsigned int
the PSK
6 bytes auth tag:
The last 6 bytes are the GCM tag
某些实现可能选择完全忽略这一点。
ACK纯粹是每跳的,除非更高协议层想要做端到端ACK。
ACK数据包不会被重复或路由等,也不会被认证。网格中继的每一步都有自己的确认,从原始发送者的角度来看,它是“发射并忘记”。
与Meshtastic和大多数其他协议一样,该协议是“半可靠”的,与所有网络一样,存在导致失败的边缘情况。
真正的可靠性必须在更高层级实现。
对于每个数据包,每个对该特定频道感兴趣的监听器恰好发送一次频道确认,除非它检测到其他节点已经发送了超过8个ACK。
此数据包必须在所有传输上发送,而不仅仅是数据包来自的那个,否则其他节点可能对监听器数量产生错误认识。
当一个数据包同时具有首次发送尝试位和兴趣标志时,它就像隐式ACK。如果我们正在发送数据包的副本,我们不需要再发送ACK来将自己加入兴趣计数。
中继器通过仅发送数据包的副本来确认,当它标记有首次副本标志时,我们对其进行计数。因此,像WiFi这样的传输必须中继,即使这实际上没有意义。
这不适用于全球路由传输,全球路由单独处理,不受任何ACK或重复等影响,我们假设MQTT服务器处理一切。
如果节点收到的回复少于预期,它们可能会重新发送消息几次。
节点绝不能期望超过6个中继器和6个频道监听器,即使它们收到更多回复,因为简单的ACK方案在适度丢包的情况下超过该数量会变得不准确。
1 byte header:
Always 0, packet type is control, and these are not routable or repeatable
1 byte header 2:
Same as on the data packets. Not really used at the moment
1 byte subtype:
CONTROL_TYPE_CHANNEL_ACKNOWLEDGE
You can acknowlege as a channel listener
so the sender knows how many there are.
4 byte message ID:
just the first 4 bytes of the random IV from the packet we are ACKing
每小时,在整点前几分钟,节点应发送它们感兴趣的频道公告。
这应使用下一个小时的滚动代码发送,而不是当前小时,以便可以提前建立连接,即使在时间不同步时一切也能正常工作。
节点通过蓝牙进行Mesh组网,使用包含服务UUID d1a77e11-420f-9f11-1a00-10a6beef0001的扩展广播数据包,负载仅为上述数据包格式。
BLE数据包绝不能设置“首次副本”标志,我们也不通过BLE计数中继器。对于我能想到的任何简单且可扩展的方案来说,丢包率太高了。
因此,我们只是将其视为固有损耗的信道,通过重复发送数据包最多4次来稍微缓解,或者直到我们需要停止以便发送其他数据包。
只要节点不尝试每秒发送超过一两个数据包,纯重复方案将提供一定的可靠性,如果超过这个限度,它将回退以避免阻塞一切。
如果我们看到同一区域有太多其他节点发送太多数据包副本,我们也会停止发送。