helium / console-decoders Goto Github PK
View Code? Open in Web Editor NEWPayload decoder functions for console.
Payload decoder functions for console.
So this is the best decoder I've found on Ubidots guide, somehow the year reporting for GPS Payload is YEAR 3991 so ubidots is not able to read data on specific date format and it cant go pass year 2099. So Map Widget is not able to see data!
Is there something wrong in the code
function calculateDaysInAMonth(month)
{
var daysInMonth = 0;
switch (month)
{
case 1: daysInMonth = 31;break;
case 2: daysInMonth = 28;break;
case 3: daysInMonth = 31;break;
case 4: daysInMonth = 30;break;
case 5: daysInMonth = 31;break;
case 6: daysInMonth = 30;break;
case 7: daysInMonth = 31;break;
case 8: daysInMonth = 31;break;
case 9: daysInMonth = 30;break;
case 10: daysInMonth = 31;break;
case 11: daysInMonth = 30;break;
case 12: daysInMonth = 31;break;
}
return daysInMonth;
}
function timeStampParser(bytes)
{
var timeStamp = 0;
var years = bytes[4] << 8 | bytes[5] << 0;
var months = bytes[6];
var days = bytes[7];
var hours = bytes[8];
var minutes = bytes[9];
var seconds = bytes[10];
var daysInAMonth = calculateDaysInAMonth(months);
timeStamp = (seconds + minutes60 + hours6060 + days246060 + monthsdaysInAMonth246060 + years365246060) *1000;
return timeStamp;
}
function coordinatesParser(coordinate)
{
//134217728=0x80000000
//4294967296=0x100000000
if(coordinate > 134217728){coordinate -= 4294967296};
coordinate /= 1000000;
return coordinate;
}
function noLocationHandler(payload,bytes)
{
var positioningFailureReason;
if(bytes[3] == 00){positioningFailureReason = "WIFI positioning time not enough"}
else if(bytes[3] == 01){positioningFailureReason = "WIFI position strategies timeout"}
else if(bytes[3] == 02){positioningFailureReason = "WIFI module is not detected"}
else if(bytes[3] == 03){positioningFailureReason = "BlueTooth positioning time not enough"}
else if(bytes[3] == 04){positioningFailureReason = "BlueTooth position strategies timeout"}
else if(bytes[3] == 05){positioningFailureReason = "BlueTooth broadcasting in progress"}
else if(bytes[3] == 06){positioningFailureReason = "GPS position time budget over"}
else if(bytes[3] == 07){positioningFailureReason = "GPS coarse positioning timeout"}
else if(bytes[3] == 08){positioningFailureReason = "GPS fine positioning timeout"}
else if(bytes[3] == 09){positioningFailureReason = "GPS position time is not enough"}
else if(bytes[3] == 10){positioningFailureReason = "GPS aiding positioning timeout"}
else if(bytes[3] == 11){positioningFailureReason = "GPS cold start positioning timeout"}
else if(bytes[3] == 12){positioningFailureReason = "Interrupted by downlink for position"}
else if(bytes[3] == 13){positioningFailureReason = "Interrupted positioning at start of movement"}
var dummy = {
"location-fixed":{
"value":0,
"context":{
"payload-type":"no-location-fixed",
"error-source":positioningFailureReason,
}
},
};
Object.assign(payload, dummy);
if(bytes[3] == 6 || bytes[3] == 7 || bytes[3] == 8 || bytes[3] == 9 || bytes[3] == 10 || bytes[3] == 11)
{
var podp = bytes[5] / 10; if(podp == 255){};
var cn0 = bytes[6];
var cn1 = bytes[7];
var cn2 = bytes[8];
var cn3 = bytes[9];
var errors = {
"PODP":podp,
"C/N 0":cn0,
"C/N 1":cn1,
"C/N 2":cn2,
"C/N 3":cn3,
};
Object.assign(payload["location-fixed"]["context"], errors);
}
return payload;
}
function locationHandler(payload,bytes)
{
var positioningType = bytes[3];
var timeStamp = timeStampParser(bytes);
var fixedType;
if(positioningType == 0x00){fixedType = "Wifi";}
else if(positioningType == 0x01){fixedType = "BlueTooth";}
else if(positioningType == 0x02){fixedType = "GPS";}
else
{
return {
"error": "invalid positioning value",
"value": positioningType,
"allowed values":{
"Wifi": 0,
"BlueTooth":1,
"GPS":2
}
};
}
var dummy = {
"location-fixed":{
"value":1,
"timestamp":timeStamp,
"context":{
"payload-type":"location-fixed",
"fixed-type":fixedType
}
},
};
Object.assign(payload, dummy);
Object.assign(payload["battery-status"],{"timestamp":timeStamp});
Object.assign(payload["battery-voltage"],{"timestamp":timeStamp});
Object.assign(payload["temperature"],{"timestamp":timeStamp});
Object.assign(payload["battery-status"]["context"],{"fixed-type":fixedType});
Object.assign(payload["battery-voltage"]["context"],{"fixed-type":fixedType});
Object.assign(payload["temperature"]["context"],{"fixed-type":fixedType});
if(positioningType == 0x02)
{
var lat = (bytes[13]<< 24 | bytes[14]<< 16 | bytes[15]<< 8 | bytes[16]<< 0);
var lng = (bytes[17]<< 24 | bytes[18]<< 16 | bytes[19]<< 8 | bytes[20]<< 0);
var dummyPayload = {};
lat = coordinatesParser(lat);
lng = coordinatesParser(lng);
positionPayload = {
"position":{
"value":1,
"timestamp":timeStamp,
"context":{
"lat":lat,
"lng":lng,
"payload-type":"location-fixed",
"fixed-type":"GPS",
}
},
};
Object.assign(payload, positionPayload);
}
return payload;
}
function buildCommonPayload(port,batteryStatus,batteryVoltage,temperature)
{
var payload = {};
var contx;
if(port == 0x1){contx = "heartbeat-payload";}
else if(port == 0x2){contx = "location-fixed-payload";}
else if(port == 0x3){contx = "no-location-fixed-payload";}
payload = {
"battery-status":{
"value":batteryStatus,
"context": {
"payload-type":contx
},
},
"battery-voltage":{
"value":batteryVoltage,
"context": {
"payload-type":contx
},
},
"temperature":{
"value":temperature,
"context": {
"payload-type":contx
},
},
};
return payload;
}
function buildPayload(bytes,port,batteryStatus,batteryVoltage,temperature){
var payload = {};
switch (port)
{
//heartbeat payload
case 1:
payload = buildCommonPayload(port,batteryStatus,batteryVoltage,temperature);
break;
//location fixed payload
case 2:
payload = buildCommonPayload(port,batteryStatus,batteryVoltage,temperature);
payload = locationHandler(payload, bytes);
break;
//location failure payload
case 3:
payload = buildCommonPayload(port,batteryStatus,batteryVoltage,temperature);
payload = noLocationHandler(payload,bytes);
break;
}
return payload;
}
function Decoder(bytes,port) {
var payload = {};
var deviceStatus = bytes[0];
var temperature = bytes[1];
var ACKAndBatteryVoltage = bytes[2];
var operationMode = deviceStatus & 0x3;//bit0~1
var batteryStatus = deviceStatus & 0x4;//bi2
var motionState = deviceStatus & (1<<5);//bit5
//correction for the sign
if(temperature > 128){temperature -= 256;};
var _ACK = ACKAndBatteryVoltage & 0xF;
var batteryVoltage = ((ACKAndBatteryVoltage & 0xF0)>>4)*0.1 + 2.2;
payload = buildPayload(bytes, port, batteryStatus, batteryVoltage, temperature);
Object.assign(payload, {"port":port});
return payload;
}
my dragino lgt-92 sends an uplink unconfirmed with this payload on port 2:
AAAAAAAAAAAPtmQ=
when parsing this with the lgt-92 latest decoder (v1.6.4) it doesnt pass the validator ("Payload input could not be validly parsed").
Also the mapper integration complains in the uplink integration response:
"body": "{"error":"Invalid Device Latitude or Longitude Values for Lat: 0 Lng: 0"}",
20210820V1 LW001-BG PRO Specification V1.0-.pdf
Does anyone have a decoder for MOKO LW001-BG PRO on the Helium network?
Thank you in advance
Hi,
I have an ELSYS brand sensor and the model is ELT Lite as seen here: https://www.elsys.se/en/lora-elt-lite/
I can confirm that it registers and works with the Helium network and that their TheThingsNetwork decoder listed on this page https://www.elsys.se/en/elsys-payload/ works as expected.
Is someone able to add that in for others to know this and use? Thanks!
A question more than an issue. I am trying to create a Helium Console integration, with my Heltec ESP32 V2 LoRaWAN device. I am serializing the payload into a MsgPack to send to my Helium Console endpoint. Having trouble decoding it via a Helium Console custom function. Although I can manually decode the payload by Base64 decoding it and then unpacking the MsgPack. Is there a quick and easy way to define this as a Helium Console custom function?
Hi,
thanks for the RAK 7201 decoder. It works well on Datacake. However, when added as a Function to the Helium Console, the data does not seem to be integrated as expected in the standard JSON message.
Can anyone help?
function Decoder(bytes, port) {
// Decode plain text from hex.
return {
key_press: String.fromCharCode.apply(null, bytes)
};
}
TBOL100 is the Browan object locator featured in the helium console here:
The source used for the Browan Object Locator function is not included in Git and does not display the script used within Console. It's not clear if this decoder, is the one for the TBOL100:
https://github.com/helium/console-decoders/blob/master/Browan/TAB/decoder.js
TBOL100 -
https://www.browan.com/product/object-locator/detail
https://www.manualslib.com/manual/1902534/Browan-Tbol100.html
Version 1.0 of protocol doesn't support recent corded RTD and switch sensors. I am unable to upload new protocol PDF but you may find it HERE. New sensors add several new MsgType's AND change how temperature is decoded.
I needed MsgType 0x0b (11) which I hacked to be just - also modified "default" case to show specific MsgType:
case 0x0b:
asRTDTemp(decoded, bytes);
break;
default:
decoded.error = 'Unsupported message type '+decoded.MsgType;
I'm using this under CODEC in ChirpStack.
A decoder for /Digital_Matter/Yabby_LoRaWAN/decoder.js does not work.
The payload received from the Yabby Edge devices is some Base64 encoded string. The current decoder function implementation in the console can't process it as the decoder functions expect the parameter to be in hexadecimal encoding.
This is a sample string we get from the device XR/1IU3kYg4ABcE=
It is properly decoded by a decoder on Digital Matter site https://support.digitalmatter.com/support/solutions/articles/16000077653-decoding-the-yabby-lorawan-payload but does not work with the decoder in the repo, if it is saved in the Helium console as a decoder function.
Digital Matter decoder has this js function to get the value for bytes
parameter used In the decoder.
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
function getBase64(input)
{
var output = new Array();
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
var orig_input = input;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
if (orig_input != input)
return null;
if (input.length % 4)
return null;
var j = 0;
while (i < input.length)
{
enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output[j++] = chr1;
if (enc3 != 64)
output[j++] = chr2;
if (enc4 != 64)
output[j++] = chr3;
}
return output;
}
Is there a way to use this function to process the paylod value before it is sent to the decoder?
When I send data to Adafruit it is base64 encoded (I don't want to use cayanneLPP). Could we have a simple function here that just shows how to decode base64, or am I missing something that I can do from the console?
Should be something along theses lines
function Decoder(bytes, port) {
return decoded;
}
// Define the string
var decodedStringBtoA = 'Hello World!';
// Encode the String
var encodedStringBtoA = btoa(decodedStringBtoA);
console.log(encodedStringBtoA);
// Define the string
var encodedStringAtoB = 'SGVsbG8gV29ybGQh';
// Decode the String
var decodedStringAtoB = atob(encodedStringAtoB);
console.log(decodedStringAtoB);
Hi There,
I'm using the Browan Object Locator function to ingest data into Azure IoT Hub. It's working nicely but sometimes the temperature reading goes a bit strange. Here are some examples from today...
30C would be about right on my desk or in my pocket, but where are these 60-something readings coming from?
I know that sometimes you have to take data from IoT sensors with a pinch of salt but I just wondered if anyone else was seeing this? I've looked at the source code and it appears to implement what is described in the Reference Manual so I think that's OK.
Any thoughts?
Cheers
Jason.
Hi,
I have been hunting for this everywhere, There was no documentation supplied with my device... grrr
I am however using chirpstack and am getting the following error:
"execute js error: js vm error: (anonymous): Line 14:24 Unexpected token * (and 4 more errors)"
here is the codec I am using:
function Decode(fPort, bytes) {
var lat = ((bytes[0] << 16) | (bytes[1] << 8) | bytes[2])
if (lat & 0x800000)
lat |= ~0xffffff;
var lon = ((bytes[3] << 16) | (bytes[4] << 8) | bytes[5])
if (lon & 0x800000)
lon |= ~0xffffff;
return {
{latitude: lat / (2.**23 - 1) * 90,
longitude: lon / (2.**23 - 1) * 180,
altitude: (bytes[6] << 8) | bytes[7],
accuracy: 0
};
}
I don't suppose you could let me know where I am going wrong?
Hi,
Ref: https://github.com/helium/console-decoders/blob/master/Digital_Matter/Oyster_LoRaWAN/decoder.js
(by @jas-williams )
I was trying to onboard an Oyster GPS tracker sensor to Helium Console, for learning trial purpose, I want to understand where I can configure the sensor to send at a specific frequency e.g. every 5 mins or send the data only when there is a change in location or event?
Below is my understanding of the Helium console flow and the purpose of the three components involved.
Helium Console Flow:
Device > Function > Integration
Device (Physical Device/Telemetry) >
Function (Decode to be efficient as numeric to be lighter on network and integration understandable) >
Integration (Cloud, data store, analytics, action)
So, if 'Function' is the right place to control the frequency of receiving the data from the device? if then is a custom script the option to choose? or is there a different component in a place where the frequency of operation needs to be controlled?
Is Function/decoder the right place to do it? or is there a separate tool for the Digital Matter/Oyster sensor to be used to configure the sensor at a certain interval?
If decoder.js is the right place to do it, can you please add some comments to that line on how to specify the interval and where is the flag to operate only when there is a change in location and every hour report?
Thanks,
Arun
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.