golang应用实现LoRaWAN节点数据收发
这是使用golang语言实现了一个应用,这个应用可以连接MQTT的服务端,接收JSON数据并解析的功能。
下面是应用,网关和节点的交互流程图
这里是数据使用了base64编码的方式后打包到JSON数据格式。
package main
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"log"
"strings"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
)
var (
serverAddr = "192.168.30.50"
serverPort = 1883
serverUser = ""
serverPass = ""
deviceEui = "eb03290421c69c6a"
applicationID = "b3525049-5fea-4f22-a60d-6510ce7004e1"
uplinkTopic = "application/%s/device/+/event/up"
downlinkTopic = "application/%s/device/%s/command/down"
)
type DownlinkMessage struct {
DevEui string `json:"devEui"`
Confirmed bool `json:"confirmed"`
FPort int `json:"fPort"`
Data string `json:"data"`
}
// Encode encodes a LoRaWAN payload into a base64 string
func Encode(payload []byte) (string, error) {
if len(payload) == 0 {
return "", errors.New("payload is empty")
}
return base64.StdEncoding.EncodeToString(payload), nil
}
// Decode decodes a base64 encoded LoRaWAN payload into a byte slice
func Decode(payload string) ([]byte, error) {
if len(payload) == 0 {
return nil, errors.New("payload is empty")
}
return base64.StdEncoding.DecodeString(payload)
}
func handleMessage(client mqtt.Client, msg mqtt.Message) {
// receive json message
// use vipper to decode the json message
var jsonMessage map[string]interface{}
err := json.Unmarshal(msg.Payload(), &jsonMessage)
if err != nil {
fmt.Println("Error decoding payload:", err)
return
}
fmt.Println("Received message:", jsonMessage)
if jsonMessage["data"] == nil {
fmt.Println("No data in message")
return
}
fmt.Println("RECV RawData:", jsonMessage["data"])
payload, err := Decode(jsonMessage["data"].(string))
if err != nil {
fmt.Println("Error decoding payload:", err)
return
}
fmt.Printf("RECV NodeAddr %s\n", jsonMessage["devAddr"])
// fport is float64, convert to int
fPort := int(jsonMessage["fPort"].(float64))
fmt.Printf("fPort %d\n", fPort)
fmt.Printf("Data 0x%x\n", payload)
}
func publishMessage(client mqtt.Client, topic string, payload []byte) {
token := client.Publish(topic, 0, false, payload)
if token.Wait() && token.Error() != nil {
fmt.Println(token.Error())
}
}
func main() {
opts := mqtt.NewClientOptions().AddBroker(fmt.Sprintf("tcp://%s:%d", serverAddr, serverPort))
opts.SetClientID("go-mqtt-client")
opts.SetUsername(serverUser)
opts.SetPassword(serverPass)
opts.SetDefaultPublishHandler(handleMessage)
client := mqtt.NewClient(opts)
if token := client.Connect(); token.Wait() && token.Error() != nil {
panic(token.Error())
}
token := client.Subscribe(fmt.Sprintf(uplinkTopic, applicationID), 0, nil)
if token.Wait() && token.Error() != nil {
fmt.Println(token.Error())
}
for {
time.Sleep(time.Second * 1)
// wait user input "s,data", then publish message
var input string
fmt.Scanln(&input)
parts := strings.Split(input, ",")
if len(parts) == 2 && parts[0] == "s" {
downlinkMessage := DownlinkMessage{
DevEui: deviceEui,
Confirmed: true,
FPort: 5,
}
encoded, err := Encode([]byte(parts[1]))
if err != nil {
fmt.Println("Error encoding downlink message:", err)
return
}
downlinkMessage.Data = encoded
jsonMessage, err := json.Marshal(downlinkMessage)
if err != nil {
fmt.Println("Error encoding downlink message:", err)
return
}
fmt.Printf("Downlink message: %s\n", string(jsonMessage))
publishMessage(client, fmt.Sprintf(downlinkTopic, applicationID, deviceEui), jsonMessage)
}
}
}
执行程序过程
./lorawan
s,11
Downlink message: {"devEui":"eb03290421c69c6a","confirmed":true,"fPort":5,"data":"MTE="}
Received message: map[adr:true confirmed:false data:EjRW deduplicationId:0e72c729-48bd-4445-abf6-2f047627701c devAddr:0147aae4 deviceInfo:map[applicationId:b3525049-5fea-4f22-a60d-6510ce7004e1 applicationName:i2som-lm401 devEui:eb03290421c69c6a deviceClassEnabled:CLASS_A deviceName:lm401bota deviceProfileId:2e320a4c-f9be-42b6-afcb-89052e8875f4 deviceProfileName:lm401otaa tags:map[] tenantId:52f14cd4-c6f1-4fbd-8f87-4025e1d49242 tenantName:ChirpStack] dr:0 fCnt:11 fPort:2 rxInfo:[map[channel:1 context:CgRe5Q== crcStatus:CRC_OK gatewayId:1172bdd0cd032a42 location:map[] metadata:map[region_common_name:CN470 region_config_id:cn470_10] nsTime:2025-04-28T14:05:24.371805290+00:00 rssi:-29 snr:11.8 uplinkId:33294]] time:2025-04-28T14:05:24.620808640+00:00 txInfo:map[frequency:4.865e+08 modulation:map[lora:map[bandwidth:125000 codeRate:CR_4_5 spreadingFactor:12]]]]
RECV RawData: EjRW
RECV NodeAddr 0147aae4
fPort 2
Data 0x123456
这里s,11
是发送执行,s
是发送命令,11
是数据。11实际发送是0x3232
下面是LM401开发板连接串口后,执行AT+SEND
命令时,接收到的数据。
EVT:5:02:3232
,5是port,02是数据大小,3232是接收到的数据。
作者:SteveChen 创建时间:2025-04-28 21:12
最后编辑:SteveChen 更新时间:2025-05-08 17:19
最后编辑:SteveChen 更新时间:2025-05-08 17:19