Skip to content

Commit

Permalink
feat: Add Browan/Digital Matter sensor decoders
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuscardosodeveloper committed Jun 3, 2024
1 parent 4d8c603 commit b9d0ddc
Show file tree
Hide file tree
Showing 55 changed files with 1,436 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/browan/ambient-light/connector.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "Browan Ambient Light",
"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/browan/ambient-light/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ambient Light Intensity 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": "The Tabs Ambient Light Sensor utilizes LoRaWAN connectivity to provide measurements of ambient light intensity which matches the human eye's response to light under a variety of lighting conditions.\n\n**Specifications**\n* Size: 50 x 20 x 50 mm\n* Weight: 30g without battery, 40g with battery\n* Sensors: Temperature, Humidity and Water leak detection\n* Temperature: 0°C to +50°C\n* IP Rating: IP 40 equivalent\n* Power Source: 3.6V 1/2 AA Li-SOCl2 1200mAh battery\n* Frequency: 863-870MHz for EU, 902-928MHz for North America\n* Tx Power: US: +19dBm, EU: +17dBm\n* Rx Sensitivity: -135dBm\n* Antenna Gain: -2dBi Peak, -5dBi Avg",
"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-helium/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-orbiwise/v1.0.0/payload.js",
"../../../../network/lorawan-senet/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-brdot-/v1.0.0/payload.js"
]
}
26 changes: 26 additions & 0 deletions decoders/connector/browan/ambient-light/v1.0.0/payload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function Decoder(bytes, port) {
const decoded = [];
if (port === 104) {
// STATUS
decoded.push({ variable: "darker", value: bytes[0] & 0x01 });
decoded.push({ variable: "lighter", value: (bytes[0] >> 1) & 0x01 });
decoded.push({ variable: "status_change", value: (bytes[0] >> 4) & 0x01 });
decoded.push({ variable: "keep_alive", value: (bytes[0] >> 5) & 0x01 });
// BATTERY
decoded.push({ variable: "battery", value: (25 + (bytes.readUInt8(1) & 0x0f)) / 10, unit: "V" });
// TEMPERATURE
decoded.push({ variable: "temperature", value: (bytes.readUInt8(2) & 0x7f) - 32, unit: "°C" });
// LUX
decoded.push({ variable: "lux", value: bytes.readUIntLE(3, 3) / 100, unit: "lux" });
}

return decoded;
}

const data = payload.find((x) => x.variable === "payload" || x.variable === "payload_raw" || x.variable === "data");
const port = payload.find((x) => x.variable === "port" || x.variable === "fport");
if (data && port) {
const serie = data.serie || new Date().getTime();
const bytes = Buffer.from(data.value, "hex");
payload = payload.concat(Decoder(bytes, Number(port.value))).map((x) => ({ ...x, serie }));
}
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/browan/door-and-window-sensor/connector.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "Browan Door and Window 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 @@
Tabs Door & Window sensor to communicate the proximity or not of a magnet 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": "**Door & Window Sensor**\n\n\n• EU, US, and Asia frequency supported\n\n\n• LoRaWAN 1.0.3\n\n\n• 0 to 50°C operation temperature range\n\n\n• Hall-Effect sensor\n\n\n• 1 cm detection range\n\n\n• IP50 equivalent",
"install_end_text": "",
"device_annotation": "",
"device_parameters": [],
"networks": [
"../../../../network/lorawan-everynet/v1.0.0/payload.js",
"../../../../network/lorawan-loriot-/v1.0.0/payload.js",
"../../../../network/lorawan-machineq/v1.0.0/payload.js",
"../../../../network/lorawan-orbiwise/v1.0.0/payload.js",
"../../../../network/lorawan-senet/v1.0.0/payload.js",
"../../../../network/lorawan-senra/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"
]
}
113 changes: 113 additions & 0 deletions decoders/connector/browan/door-and-window-sensor/v1.0.0/payload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/* eslint-disable camelcase */
/* This is an example code for Everynet Parser.
** Everynet send several parameters to TagoIO. The job of this parse is to convert all these parameters into a TagoIO format.
** One of these parameters is the payload of your device. We find it too and apply the appropriate sensor parse.
**
** 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": "everynet_payload", "value": "{ \"params\": { \"payload\": \"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 = [];


/**
* Convert an object to TagoIO object format.
* Can be used in two ways:
* toTagoFormat({ myvariable: myvalue , anothervariable: anothervalue... })
* toTagoFormat({ myvariable: { value: myvalue, unit: 'C', metadata: { color: 'green' }} , anothervariable: anothervalue... })
*
* @param {Object} object_item Object containing key and value.
* @param {String} serie Serie for the variables
* @param {String} prefix Add a prefix to the variables name
*/
function toTagoFormat(object_item, serie, prefix = '') {
const result = [];
for (const key in object_item) {
if (ignore_vars.includes(key)) continue;

if (typeof object_item[key] === 'object') {
result.push({
variable: object_item[key].variable || `${prefix}${key}`,
value: object_item[key].value,
serie: object_item[key].serie || serie,
metadata: object_item[key].metadata,
location: object_item[key].location,
unit: object_item[key].unit,
});
} else {
result.push({
variable: `${prefix}${key}`,
value: object_item[key],
serie,
});
}
}

return result;
}

// Function to convert decimal numbers to binary
function dec2bin(dec) {
const binary = (dec >>> 0).toString(2);
return '00000000'.substr(binary.length) + binary;
}

// Decode an uplink message from an array of bytes to an object of fields
function Decoder(bytes, port) {
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.
const decoded = {};

if (bytes == null) { return null; }

if (port === 100) {
// parse status
decoded.status = {
value: parseInt(dec2bin(bytes[0]).substr(7, 1), 2),
};

// parse battery voltage
decoded.battery_voltage = {
value: Number((25 + parseInt(dec2bin(bytes[1]).substr(0, 4), 2)) / 10).toFixed(1),
unit: 'V',
};

// parse battery capacity
decoded.battery_capacity = {
value: Number(100 * parseInt(dec2bin(bytes[1]).substr(4), 2) / 15).toFixed(1),
unit: '%',
};

// parse temperature
decoded.temperature = {
value: bytes.readUInt8(2) - 32,
unit: '°C',
};

decoded.time_elapsed = bytes.readUInt16LE(3);

decoded.count = bytes.readUIntLE(5, 3);
} else {
return null;
}

return decoded;
}

let data = payload.find(x => x.variable === 'data' || x.variable === 'payload');
let port = payload.find(x => x.variable === 'port');
if (data && port) {
port = Number(port.value);
const serie = data.serie || new Date().getTime();
data = data.value;
const vars_to_tago = Decoder(Buffer.from(data, 'hex'), port);

payload = [...payload, ...toTagoFormat(vars_to_tago, serie)];
payload = payload.filter(x => !ignore_vars.includes(x.variable));
}
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/browan/healthy-home-sensor-iaq/connector.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "Browan Healthy Home Sensor IAQ",
"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, Relative Humidity and Volatile Organic Compound level 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": "The Healthy Home Indoor Air Quality sensor utilizes LoRaWAN connectivity to communicate the Temperature, Relative Humidity and Volatile Organic Compound levels of the surrounding environment. The intended use is to place the sensor within a room to determine if the air quality, temperature, and humidity are ideal.\n\n**Specifications**\n* Dimensions: 50 x 20 x 50 mm\n* Weight: 30g without battery / 40g with battery\n* Sensors: Temperature & Relative Humidity, Indoor Air Quality\n* Operating Temperature: 0°C to +50°C\n* IP Rating: IP 40 equivalent\n* Frequency: 863-870MHz for EU / 902-928MHz for North America\n* Tx Power: US: +19dBm / EU: +17dBm\n* Rx Sensitivity: -135dBm\n* Antenna Gain: -2dBi Peak, -5dBi Avg\n* Power Source: 3.6V 1/2 AA Li-SOCl2 1200mAh battery\n",
"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-helium/v1.0.0/payload.js",
"../../../../network/lorawan-kerlink/v1.0.0/payload.js",
"../../../../network/lorawan-swisscom/v1.0.0/payload.js",
"../../../../network/lorawan-tektelic/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"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
function Decoder(bytes, port) {
const decoded = [];
// status message
if (port !== 103) return [{ variable: "parse_error", value: "Parser error: Port must be 103" }];
if (bytes.length !== 11) return [{ variable: "parse_error", value: "Parser error: Bytes length doesn't match" }];
// status -- byte 0
decoded.push({ variable: "status_event", value: bytes[0] & 0x01 });
decoded.push({ variable: "status_type", value: ((bytes[0] >> 3) & 0x01) ? "Temperature and Humidity sensor" : "IAQ Sensor" });
decoded.push({ variable: "status_temperature_change", value: (bytes[0] >> 4) & 0x01 });
decoded.push({ variable: "status_humidity_change", value: (bytes[0] >> 5) & 0x01 });
decoded.push({ variable: "status_iaq_change", value: (bytes[0] >> 6) & 0x01 });
// battery -- byte 1 (1 to 14)
if ([0, 15].includes(bytes[1] & 0x0F)) return [{ variable: "parse_error", value: "Parser error: Battery must be between 2.6 and 3.9 V" }];
decoded.push({ variable: "battery", value: (25 + (bytes[1] & 0x0F)) / 10, unit: "V" });
// temp (pcb) -- byte 2
decoded.push({ variable: "board_temperature", value: (bytes[2] & 0x7F) - 32, unit: "°C" });
// rh -- byte 3 (max 100)
if ((bytes[3] & 0x7F) > 100) return [{ variable: "parse_error", value: "Parser error: Max value for humidity is 100%" }];
decoded.push({ variable: "humidity", value: bytes[3] & 0x7F, unit: "%" });
// co2 -- bytes 4, 5
decoded.push({ variable: "eco2", value: bytes.readUInt16BE(4), unit: "ppm" });
// voc -- bytes 6, 7
decoded.push({ variable: "voc", value: bytes.readUInt16BE(6), unit: "ppm" });
// iaq -- bytes 8, 9 (0 to 500)
if (bytes.readUInt16BE(8) > 500) return [{ variable: "parse_error", value: "Parser error: Max value for IAQ is 500" }];
decoded.push({ variable: "iaq", value: bytes.readUInt16BE(8) });
// environment temp -- byte 10
decoded.push({ variable: "environment_temperature", value: (bytes[10] & 0x7F) - 32, unit: "°C" });


return decoded;
}

// let payload = [{ variable: "payload", value: "790a2a5f2744274427442a" }, { variable: "port", value: "103" }];
// let payload = [{ variable: "payload", value: "79ffffffffffffffffffff" }, { variable: "port", value: "103" }];

const data = payload.find((item) => item.variable === "data" || item.variable === "payload" || item.variable === "payload_raw" );
const port = payload.find((item) => item.variable === "port" || item.variable === "fport" );

if (data) {
const bytes = Buffer.from(data.value, "hex");
const serie = new Date().getTime();
payload = payload.concat(Decoder(bytes, Number(port.value))).map((x) => ({ ...x, serie }));
}

// console.log(payload);
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/browan/industrial-tracker/connector.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "Browan Industrial Tracker",
"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 @@
Tracking with GPS and 3-axis accelerometer 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": "The Industrial Tracker is a general-purpose tracker, designed for GPS tracking on various applications: bicycles, cars, or pets. It is equipped with GPS and 3-axis accelerometer, that provides a much more cost-effective way for service providers to deploy this for tracking applications than to use the GPRS network. \n\n**Specifications**\n* Size: 107 x 52 x 27 mm\n* Weight: 35g without battery, 45g with battery\n* Sensors: GNSS module, 3D MEMs accelerometer, Hall-effect\n* Temperature: -20°C to +70°C\n* IP Rating: IP 66 equivalent\n* Power Source: 3.6V 1/2 AA Li/SOCl2 1200 mAh battery (2)\n* Frequency: 863-870MHz for EU, 902-928MHz for North America\n* Tx Power: +19dBm conducted\n* Rx Sensitivity: -138dBm conducted\n* Antenna Gain: 0dBi Peak, -3dBi Avg",
"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-helium/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-orbiwise/v1.0.0/payload.js",
"../../../../network/lorawan-senet/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-brdot-/v1.0.0/payload.js"
]
}
Loading

0 comments on commit b9d0ddc

Please sign in to comment.