loraserver 源码解析 (五) lora-gateway-bridge 与 gateway 通信协议的具体实现 - 代码天地
loraserver 源码解析 (五) lora-gateway-bridge 与 gateway 通信协议的具体实现
其他 2018-07-18 14:04:26 阅读次数: 0
详细的协议内容请参考前文 loraserver 源码解析 (四) lora-gateway-bridge
bridge 启动后会开启3个 routine
1, cleanup 间隔一分钟,不断地清理 非active得gateway
2. readPackets,侦听默认1700的udp端口,收到的udp报文 就再新建 routine 来处理,保证接收routine不阻塞。
3. sendPackets,不断侦听 udpSendChan channel上是否有待发送的报文,有就发送出去
先看 readPackets routine
func (b *Backend) readPackets() error {
buf := make([]byte, 65507) // max udp data size
for {
i, addr, err := b.conn.ReadFromUDP(buf)
if err != nil {
if b.closed {
return nil
}
log.WithError(err).Error("gateway: read from udp error")
continue
}
data := make([]byte, i)
copy(data, buf[:i])
go func(data []byte) {
if err := b.handlePacket(addr, data); err != nil {
log.WithFields(log.Fields{
"data_base64": base64.StdEncoding.EncodeToString(data),
"addr": addr,
}).Errorf("gateway: could not handle packet: %s", err)
}
}(data)
}
}
b.conn.ReadFromUDP(buf) 后 buf拿到了gateway上传的 packet
拷贝到 data 后 再开启新的 routine 处理data,然后继续接收新的 udp 报文
如果没有新的报文到达 readPackets 就阻塞在 b.conn.ReadFromUDP(buf) 这里
再来看看怎么解析 data 报文
Bytes | Function
:------:|---------------------------------------------------------------------
0 | protocol version = 2
1-2 | random token
3 | PUSH_DATA identifier 0x00
4-11 | Gateway unique identifier (MAC address)
12-end | JSON object, starting with {, ending with }, see section 4
取出data[3],看看是啥类型的包?
#define PKT_PUSH_DATA 0
#define PKT_PUSH_ACK 1
#define PKT_PULL_DATA 2
#define PKT_PULL_RESP 3
#define PKT_PULL_ACK 4
#define PKT_TX_ACK 5
gateway上传数据是 PKT_PUSH_DAT, 相当于 brige代码里的 PushData
func (b *Backend) handlePacket(addr *net.UDPAddr, data []byte) error {
pt, err := GetPacketType(data)
if err != nil {
return err
}
switch pt {
case PushData:
return b.handlePushData(addr, data)
case PullData:
return b.handlePullData(addr, data)
case TXACK:
return b.handleTXACK(addr, data)
default:
return fmt.Errorf("gateway: unknown packet type: %s", pt)
}
}
稍后, data被转解析成 brige的 PushDataPacket 结构
然后生成这个PUSH相应的 ack 包 推送到 udpSendChan 管道中, 文章开头提到的 sendPackets routine 是一直侦听 udpSendChan 管道的,它收到数据后发回给 gateway
data接着被处理,若是多个终端数据打包成的包,则解析后一一拆分,解析成一个个的packets后逐个 转交给 rxChan 管道
bridge 还有个专门等待 rxChan数据的 routine,这个rourine接收到 rxChan 传过来的 packet后, 转发给 mqtt broker
话题即为 gateway/ node 的 mac /rx
由于 loraserver 订阅了 这个 话题,mqtt broker 转发给 loraserver
从日志上也能反馈出一些处理流程
INFO[61640] gateway: received udp packet from gateway addr="127.0.0.1:48878" protocol_version=2 type=PushData
INFO[61640] gateway: rxpk packet received addr="127.0.0.1:48878" data="gCSa8QZQZQAMliBl0jg75+2lgQvFcA==" mac=1234567812345678
INFO[61640] backend: publishing packet qos=0 topic=gateway/1234567812345678/rx