文章目录
前言
LoRa 设备的数据格式非常碎片化,借助于 JavaScript 编解码函数,可将设备的原始数据转换为可读性更强的 JSON 格式。
小能手最近在学习 ChirpStack 项目,应该是最有影响力的 LoRaWAN 服务器开源项目。它组件丰富,代码可读性强,是个很好的学习资料。更多学习笔记,可点此查看。
1 ChirpStack 中如何启用编解码函数功能
在 Device Profile 中除了 LoRaWAN 参数之外,还有一个 codec 模块。
这个模块默认是未启用的,它支持两种协议解析,我们在 AS 的 WEB 界面中可以看到。
- Cayenne Low Power Payload。卡宴的这个协议要求传感器按其协议上报的话,它则会解析出相应的数据。不够灵活,一般做简单的DEMO应用。
- Custom JavaScript codec functions。这就是我们今天重点介绍的 JS 编解码函数。可将设备的原始数据转换为可读性更强的 JSON 格式。
1.1 编解码组件的 API 使用
除了 WEB 界面之外,启用编解码函数,只需要相应在创建 device-profiles 新增字段,以字符串形式将 JavaScript 代码传递进去就好了。
Request URL: http://yourip:8080/api/device-profiles/your_profile_id
Request Method: PUT
请求示例 NONE
{
"deviceProfile":{
"id":"a3bdeb9b-8ad6-4b04-bca1-be0ff3dc45c2",
"name":"A",
"organizationID":"1",
"networkServerID":"6",
"supportsClassB":false,
"classBTimeout":0,
"pingSlotPeriod":0,
"pingSlotDR":0,
"pingSlotFreq":0,
"supportsClassC":false,
"classCTimeout":0,
"macVersion":"1.0.2",
"regParamsRevision":"A",
"rxDelay1":0,
"rxDROffset1":0,
"rxDataRate2":0,
"rxFreq2":505300000,
"factoryPresetFreqs":[505300000],
"maxEIRP":0,
"maxDutyCycle":0,
"supportsJoin":false,
"rfRegion":"CN470",
"supports32BitFCnt":false,
"payloadCodec":"",
"payloadEncoderScript":"",
"payloadDecoderScript":"",
"geolocBufferTTL":0,
"geolocMinBufferSize":0
}
}
请求示例 CAYENNE_LPP
"payloadCodec":"CAYENNE_LPP",
"payloadEncoderScript":"",
"payloadDecoderScript":"",
请求示例 CUSTOM_JS
"payloadCodec":"CUSTOM_JS",
"payloadEncoderScript":"",
"payloadDecoderScript":"",
2 JavaScript 语法基础
不用完整的去学习 JavaScript,编解码函数主要实现数组和对象的转换,只要认识下数组和对象即可。
数组
参考廖雪峰教程:https://www.liaoxuefeng.com/wiki/1022910821149312/1023020967732032
var arr = ['A', 'B', 'C'];
arr[1] = 99;
arr; // arr现在变为['A', 99, 'C']
对象
参考廖雪峰教程:https://www.liaoxuefeng.com/wiki/1022910821149312/1023020997017056
var xiaoming = {
name: '小明'
};
xiaoming.age; // undefined
xiaoming.age = 18; // 新增一个age属性
xiaoming.age; // 18
delete xiaoming.age; // 删除age属性
xiaoming.age; // undefined
delete xiaoming['name']; // 删除name属性
xiaoming.name; // undefined
delete xiaoming.school; // 删除一个不存在的school属性也不会报错
3 JS Decode 实践
我写一个简单的温度示例,取第一字节来做温度。
函数编写
function Decode(fPort, bytes) {
var data = {
"temperature": 22.5
};
data.temperature = bytes[0];
return data;
}
启用 Decode 之前的原始数据
这里看下未启用前的效果。
{
"applicationID":"2",
"applicationName":"demoapp",
"deviceName":"device1",
"devEUI":"0000000000000001",
"rxInfo":[{"gatewayID":"0000e1abb6975615","name":"gw1","rssi":-113,"loRaSNR":-4.3,"location":{"latitude":0,"longitude":0,"altitude":0}}],
"txInfo":{"frequency":470300000,"dr":4},
"adr":true,
"fCnt":14,
"fPort":5,
"data":"aDQAAAAAAGiAJ4yGxDtmZmdm7n1mZsQ9ZmVnaPiHZmZmZsRAZmVoaGZmZmZmZmZmZnMW"
}
启用 Decode 之后的数据
启动 Decode 之后的数据,多了一个 object 对象。
{
"applicationID":"2",
"applicationName":"demoapp",
"deviceName":"device1",
"devEUI":"0000000000000001",
"rxInfo":[{
"gatewayID":"0000e1abb6975615",
"name":"gw1",
"rssi":-113,
"loRaSNR":-4.3,
"location":{"latitude":0,"longitude":0,"altitude":0}
}],
"txInfo":{"frequency":470300000,"dr":4},
"adr":true,
"fCnt":54,
"fPort":5,
"data":"aDQAAAAAAGiAJ4yGxDtmZmdm7n1mZsQ9ZmVnaPiHZmZmZsRAZmVoaGZmZmZmZmZmZnMW",
"object":{"temperature":104}
}
4 JS Encode 实践
假定要下发一个周期,{“period”: 300},经过 Encode 函数后取出2字节的周期数据下发给设备。
函数编写
function Encode(fPort, obj) {
var data = new Array();
data[0] = obj.period & 0x00FF;
data[1] = (obj.period >> 8) & 0x00FF;
return data;
}
下发数据
下发 {“period”: 300} 来试试。
启用之后的效果
downlink phypayload: {"mhdr":{"mType":"ConfirmedDataDown","major":"LoRaWANR1"},"macPayload":{"fhdr":{"devAddr":"12190003","fCtrl":{"adr":true,"adrAckReq":false,"ack":true,"fPending":false,"classB":false},"fCnt":4,"fOpts":[{"bytes":"BQBIGk0IAQ=="}]},"fPort":5,"frmPayload":[{"bytes":"LAE="}]},"mic":"d296d057"}
将这个"LAE="进行base64解码之后得到 0x2c 0x01 两个字节,即 0x012c = 300。
验证完成。
小结
这一节笔记学习了一个强大的功能 JS 编解码函数,可以灵活将设备的原始数据转化为 JSON 格式数据。同时学习了必要的 JS 语法,并做了上下行的demo示例,供朋友们参考。
END
iotisan 博客专家 发布了232 篇原创文章 · 获赞 224 · 访问量 79万+ 关注