Skip to content

Commit

Permalink
feat: Add RAK/RisingHF/Seeed sensor decoders
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuscardosodeveloper committed Jun 4, 2024
1 parent e506bde commit 48cd3d5
Show file tree
Hide file tree
Showing 50 changed files with 4,993 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions decoders/connector/rak/2171-wisnode-trackit/connector.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "RAKWireless 2171 WisNode TrackIt",
"images": {
"logo": "./assets/logo.png"
},
"versions": {
"v1.0.0": {
"src": "./v1.0.0/payload.js",
"manifest": "./v1.0.0/payload-config.jsonc"
}
}
}
1 change: 1 addition & 0 deletions decoders/connector/rak/2171-wisnode-trackit/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The RAK2171 is a GPS tracking device over LoRaWAN
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "../../../../../schema/connector_details.json",
"description": "../description.md",
"install_text": "WisNode TrackIt (RAK2171) is RAKwireless LoRaWAN GPS tracking device. It comes in a small form factor with rechargeable battery and tracking \r\n\r\n\r\n**Features:**\r\n\r\n* Built-in LoRaWAN, Bluetooth, and GPS\r\n* Built-in battery: 400 mAh\r\n* Charger with a magnetic plate\r\n* Tracker Dimensions: 42x42x18 mm\r\n* Tracker weight: 25 g\r\n* Built-in accelerometer\r\n* Operating temperature: -20° C to +60° C",
"install_end_text": "",
"device_annotation": "",
"device_parameters": [],
"networks": [
"../../../../network/lorawan-actility/v1.0.0/payload.js",
"../../../../network/lorawan-citykinect/v1.0.0/payload.js",
"../../../../network/lorawan-chirpstack/v1.0.0/payload.js",
"../../../../network/lorawan-everynet/v1.0.0/payload.js",
"../../../../network/lorawan-helium/v1.0.0/payload.js",
"../../../../network/lorawan-kerlink/v1.0.0/payload.js",
"../../../../network/lorawan-tektelic/v1.0.0/payload.js",
"../../../../network/lorawan-swisscom/v1.0.0/payload.js",
"../../../../network/lorawan-senra/v1.0.0/payload.js",
"../../../../network/lorawan-senet/v1.0.0/payload.js",
"../../../../network/lorawan-orbiwise/v1.0.0/payload.js",
"../../../../network/lorawan-machineq/v1.0.0/payload.js",
"../../../../network/lorawan-loriot-/v1.0.0/payload.js",
"../../../../network/lorawan-ttittn-v3/v1.0.0/payload.js",
"../../../../network/lorawan-brdot-/v1.0.0/payload.js"
]
}
119 changes: 119 additions & 0 deletions decoders/connector/rak/2171-wisnode-trackit/v1.0.0/payload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* eslint-disable no-plusplus */
/* eslint-disable no-redeclare */
/* eslint-disable vars-on-top */
/* eslint-disable no-var */
/* eslint-disable default-case */
/* eslint-disable prefer-destructuring */

function ToTagoFormat(object_item, serie, prefix = "") {
const result = [];
for (const key in object_item) {
if (typeof object_item[key] === "object") {
result.push({
variable: (object_item[key].MessageType || `${prefix}${key}`).toLowerCase(),
value: `${object_item[key].lat}, ${object_item[key].lng}`,
serie: object_item[key].serie || serie,
metadata: object_item[key].metadata,
unit: object_item[key].unit,
location: { lat: Number(object_item[key].lat), lng: Number(object_item[key].lng) },
});
} else {
result.push({
variable: `${prefix}${key}`.toLowerCase(),
value: object_item[key],
serie,
});
}
}

return result;
}
function Decoder(bytes) {
const decoded = {};

// adjust time zone, here Asia/Manila = +8H
const my_time_zone = 8 * 60 * 60;

decoded.num = bytes[1];
decoded.app_id = (bytes[2] << 24) | (bytes[3] << 16) | (bytes[4] << 8) | bytes[5];
decoded.dev_id = (bytes[6] << 24) | (bytes[7] << 16) | (bytes[8] << 8) | bytes[9];
switch (bytes[0]) {
case 0xca: // No Location fix
decoded.acc = 0;
decoded.fix = 0;
decoded.batt = bytes[10];
decoded.time = (bytes[11] << 24) | (bytes[12] << 16) | (bytes[13] << 8) | bytes[14];
// adjust time zone
decoded.time += my_time_zone;
var dev_date = new Date(decoded.time * 1000);
decoded.time_stamp = `${dev_date.getHours()}:${dev_date.getMinutes()}`;
decoded.date_stamp = `${dev_date.getDate()}.${dev_date.getMonth() + 1}.${dev_date.getFullYear()}`;
decoded.time = String((bytes[11] << 24) | (bytes[12] << 16) | (bytes[13] << 8) | bytes[14]);
decoded.stat = bytes[15] & 0x03;
decoded.gps = bytes[15] & 0x0c;
break;
case 0xcb: // Location fix
decoded.fix = 1;
decoded.batt = bytes[20];
decoded.time = (bytes[21] << 24) | (bytes[22] << 16) | (bytes[23] << 8) | bytes[24];
// adjust time zone
decoded.time += my_time_zone;
var dev_date = new Date(decoded.time * 1000);
decoded.time_stamp = `${dev_date.getHours()}:${dev_date.getMinutes()}`;
decoded.date_stamp = `${dev_date.getDate()}.${dev_date.getMonth() + 1}.${dev_date.getFullYear()}`;
decoded.time = String((bytes[21] << 24) | (bytes[22] << 16) | (bytes[23] << 8) | bytes[24]);
decoded.stat = bytes[25] & 0x03;
decoded.gps = bytes[25] & 0x0c;
decoded.location = {
lat: (((bytes[14] << 24) | (bytes[15] << 16) | (bytes[16] << 8) | bytes[17]) * 0.000001).toFixed(6),
lng: (((bytes[10] << 24) | (bytes[11] << 16) | (bytes[12] << 8) | bytes[13]) * 0.000001).toFixed(6),
};
decoded.acc = bytes[18];
decoded.gps_start = bytes[19];
break;
case 0xcc: // SOS
decoded.sos = 1;
decoded.location = {
lat: (((bytes[14] << 24) | (bytes[15] << 16) | (bytes[16] << 8) | bytes[17]) * 0.000001).toFixed(6),
lng: (((bytes[10] << 24) | (bytes[11] << 16) | (bytes[12] << 8) | bytes[13]) * 0.000001).toFixed(6),
};
if (bytes.length > 18) {
let i;
for (i = 18; i < 28; i++) {
decoded.name += bytes[i].toString();
}
for (i = 28; i < 40; i++) {
decoded.country += bytes[i].toString();
}
for (i = 39; i < 50; i++) {
decoded.phone += bytes[i].toString();
}
}
break;
case 0xcd:
decoded.sos = 0;
break;
case 0xce:
decoded.alarm = 0x01;
decoded.alarm_lvl = bytes[10];
break;
}
return decoded;
}

// let payload = [{ variable: "payload", value: "cb0e000000b9000000ce00d740e60289738b3b043762e27c6409" }];
const payload_raw = payload.find((x) => x.variable === "payload_raw" || x.variable === "payload" || x.variable === "data");
if (payload_raw) {
try {
// Convert the data from Hex to Javascript Buffer.
const buffer = Buffer.from(payload_raw.value, "hex");
const serie = new Date().getTime();
const payload_aux = ToTagoFormat(Decoder(buffer));
payload = payload.concat(payload_aux.map((x) => ({ ...x, serie })));
} catch (e) {
// Print the error to the Live Inspector.
console.error(e);
// Return the variable parse_error for debugging.
payload = [{ variable: "parse_error", value: e.message }];
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions decoders/connector/risinghf/rhf1s001/connector.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "RisingHF RHF1S001",
"images": {
"logo": "./assets/logo.png"
},
"versions": {
"v1.0.0": {
"src": "./v1.0.0/payload.js",
"manifest": "./v1.0.0/payload-config.jsonc"
}
}
}
1 change: 1 addition & 0 deletions decoders/connector/risinghf/rhf1s001/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Outdoor IP64 Temperature and Humidity sensor from RisingHF
23 changes: 23 additions & 0 deletions decoders/connector/risinghf/rhf1s001/v1.0.0/payload-config.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "../../../../../schema/connector_details.json",
"description": "../description.md",
"install_text": "Outdoor IP64 Temperature and Humidity LoRaWAN sensor RHF1S001 offers cost effective LoRaWAN end node solution for a variety of applications. \n\nIP64 enclosure concept and water splash proof unique sensor design are ideal for outdoor use and installation in low accessibility locations.\n##\n* Powered by lithium thionyl chloride battery: 5 years of operation for 1 uplink 2 minutes.\n* Extended industrial operating temperature: -40°C to +85°C. ?\n* Outdoor use: IP64 enclosure.\n* ±5% RH typically from 20% RH to 80% RH at 25°C.\n* ±0.5°C typically from +5°C to +60°C.\n* LoRaWAN compatible: Class A, uplink rate programmable from 2 minutes to 24 hours.\n",
"install_end_text": "",
"device_annotation": "Install the dashboard template: https://admin.tago.io/template/5c155bec93d838001dcc246b",
"device_parameters": [],
"networks": [
"../../../../network/lorawan-loriot-/v1.0.0/payload.js",
"../../../../network/lorawan-everynet/v1.0.0/payload.js",
"../../../../network/lorawan-machineq/v1.0.0/payload.js",
"../../../../network/lorawan-orbiwise/v1.0.0/payload.js",
"../../../../network/lorawan-kerlink/v1.0.0/payload.js",
"../../../../network/lorawan-citykinect/v1.0.0/payload.js",
"../../../../network/lorawan-tektelic/v1.0.0/payload.js",
"../../../../network/lorawan-actility/v1.0.0/payload.js",
"../../../../network/lorawan-ttittn-v3/v1.0.0/payload.js",
"../../../../network/lorawan-swisscom/v1.0.0/payload.js",
"../../../../network/lorawan-chirpstack/v1.0.0/payload.js",
"../../../../network/lorawan-helium/v1.0.0/payload.js",
"../../../../network/lorawan-brdot-/v1.0.0/payload.js"
]
}
77 changes: 77 additions & 0 deletions decoders/connector/risinghf/rhf1s001/v1.0.0/payload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* This is an generic payload parser example.
** The code find the payload variable and parse it if exists.
**
** IMPORTANT: In most case, you will only need to edit the parsePayload function.
**
** Testing:
** You can do manual tests to this parse by using the Device Emulator. Copy and Paste the following code:
** [{ "variable": "payload", "value": "0109611395" }]
**
** The ignore_vars variable in this code should be used to ignore variables
** from the device that you don't want.
*/
// Add ignorable variables in this array.
const ignore_vars = ['fcnt', 'EUI', 'port', 'ts', 'freq', 'dr', 'cmd', 'ack'];

/**
* This is the main function to parse the payload. Everything else doesn't require your attention.
* @param {String} payload_raw
* @returns {Object} containing key and value to TagoIO
*/
function parsePayload(payload_raw) {
try {
// If your device is sending something different than hex, like base64, just specify it bellow.
const bytes = Buffer.from(payload_raw, 'hex');

const obj = {};

// temp
const tempEncoded = (bytes[2] << 8) | (bytes[1]);
const tempDecoded = (tempEncoded * 175.72 / 65536) - 46.85;
obj.temp = tempDecoded.toFixed(2);

// humidity
const humEncoded = (bytes[3]);
const humDecoded = (humEncoded * 125 / 256) - 6;
obj.hum = humDecoded.toFixed(2);

// period
const periodEncoded = (bytes[5] << 8) | (bytes[4]);
const periodDecoded = (periodEncoded * 2);
obj.period = `${periodDecoded}`;

// battery
const batteryEncoded = (bytes[8]);
const batteryDecoded = (batteryEncoded + 150) * 0.01;
obj.battery = batteryDecoded.toFixed(2);
console.log(obj);
const data = [
{ variable: 'temperature', value: Number(obj.temp), unit: '°C' },
{ variable: 'humidity', value: Number(obj.hum), unit: '%' },
{ variable: 'period', value: Number(obj.period), unit: 'sec' },
{ variable: 'battery', value: Number(obj.battery), unit: 'V' },
];
return data;
} catch (e) {
console.log(e);
// Return the variable parse_error for debugging.
return [{ variable: 'parse_error', value: e.message }];
}
}

// Remove unwanted variables.
payload = payload.filter(x => !ignore_vars.includes(x.variable));

// Payload is an environment variable. Is where what is being inserted to your device comes in.
// Payload always is an array of objects. [ { variable, value...}, {variable, value...} ...]
const payload_raw = payload.find(x => x.variable === 'payload_raw' || x.variable === 'payload' || x.variable === 'data');
if (payload_raw) {
// Get a unique serie for the incoming data.
const { value, serie, time } = payload_raw;

// Parse the payload_raw to JSON format (it comes in a String format)
if (value) {
payload = payload.concat(parsePayload(value).map(x => ({ ...x, serie, time: x.time || time })));
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "Seeed SenseCap Air Temperature and Humidity Sensor",
"images": {
"logo": "./assets/logo.png"
},
"versions": {
"v1.0.0": {
"src": "./v1.0.0/payload.js",
"manifest": "./v1.0.0/payload-config.jsonc"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Temperature and Humidity sensor over LoRaWAN™
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "../../../../../schema/connector_details.json",
"description": "../description.md",
"install_text": "SenseCAP Wireless Air Temperature & Humidity Sensor measures temperature and humidity in the atmosphere at the range of -40℃ to 85℃ and 0 to 100 %RH (non-condensing) respectively. With a high-precision measurement chip, this sensor features stability and reliability, making it widely applicable in industrial environmental sensing scenarios.\n\nThis device incorporates a built-in LoRa transmitter based on SX1276 for long-range transmission, a 2-in-1 sensor, and a custom battery. It is specifically designed and optimized for use cases powering end devices by batteries for years. To minimize the power consumption, the device wakes up, transmits the collected temperature and humidity data to the gateway, and then goes back to sleep.\n\n**Air Temperature Sensor Specifications**\n* range: -40 ℃ to +85 ℃\n* accuracy: ±0.2 ℃\n* Resolution: 0.1 ℃\n* Drift: <0.03 ℃/year\n\n**Air Humidity Sensor Specifications**\n* range: 0 to 100 %RH (non-condensing)\n* accuracy: ±1.5 %RH\n* Resolution: \t1 %RH\n* Drift: <0.25 %RH/year\n\nDocumentation:\nhttps://sensecap-docs.seeed.cc/pdf/SenseCAP%20LoRaWAN%20Sensor%20User%20Manual-V1.1.pdf",
"install_end_text": "",
"device_annotation": "",
"device_parameters": [],
"networks": [
"../../../../network/lorawan-actility/v1.0.0/payload.js",
"../../../../network/lorawan-chirpstack/v1.0.0/payload.js",
"../../../../network/lorawan-citykinect/v1.0.0/payload.js",
"../../../../network/lorawan-everynet/v1.0.0/payload.js",
"../../../../network/lorawan-kerlink/v1.0.0/payload.js",
"../../../../network/lorawan-loriot-/v1.0.0/payload.js",
"../../../../network/lorawan-machineq/v1.0.0/payload.js",
"../../../../network/lorawan-senet/v1.0.0/payload.js",
"../../../../network/lorawan-orbiwise/v1.0.0/payload.js",
"../../../../network/lorawan-senra/v1.0.0/payload.js",
"../../../../network/lorawan-swisscom/v1.0.0/payload.js",
"../../../../network/lorawan-tektelic/v1.0.0/payload.js",
"../../../../network/lorawan-ttittn-v3/v1.0.0/payload.js",
"../../../../network/lorawan-helium/v1.0.0/payload.js",
"../../../../network/lorawan-brdot-/v1.0.0/payload.js"
]
}
Loading

0 comments on commit 48cd3d5

Please sign in to comment.