Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AM103 decoder #84

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/milesight/am103/connector.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../../schema/connector.json",
"name": "Milesight AM103",
"images": {
"logo": "./assets/logo.png"
},
"versions": {
"v1.0.0": {
"src": "./v1.0.0/payload.js",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must be in typescript, so payload.ts

"manifest": "./v1.0.0/payload-config.jsonc"
}
}
}
1 change: 1 addition & 0 deletions decoders/connector/milesight/am103/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The AM103 is a sensor for indoor ambience monitoring over LoRaWAN®
25 changes: 25 additions & 0 deletions decoders/connector/milesight/am103/v1.0.0/payload-config.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "../../../../../schema/connector_details.json",
"description": "../description.md",
"install_text": "AM103 is a compact indoor ambience monitoring sensor for measurement of temperature, humidity, light, CO2 concentration. Apart from screen display, sensor data is also transmitted using LoRaWAN® technology.\n\n** Features**\n\n* Integrated with multiple sensors like humidity, temperature, CO2, etc.\n* Visual display via E-ink screen \n* Standard AA batteries\n* One year work without replacing batteries\n* Equipped with NFC and type-C port for easy configuration\n* Compliant with standard LoRaWAN®gateways and network servers",
"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"
]
}
92 changes: 92 additions & 0 deletions decoders/connector/milesight/am103/v1.0.0/payload.js
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code appears to be the manufacturer decoder, it lacks the following details:

  • The decoder must be in Typescript.
  • Data that should be stored in TagoIO must be in the TagoIO Data Format and stored within the payload global variable.
  • The code must contain unit tests proving the decoder works as expected.

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Milesight AM103 Payload Decoder
*
*/


/* ******************************************
* bytes to number
********************************************/
function readUInt16LE(bytes) {
var value = (bytes[1] << 8) + bytes[0];
return value & 0xffff;
}

function readInt16LE(bytes) {
var ref = readUInt16LE(bytes);
return ref > 0x7fff ? ref - 0x10000 : ref;
}

function readUInt32LE(bytes) {
var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0];
return (value & 0xffffffff) >>> 0;
}

// function readInt32LE(bytes) {
// var ref = readUInt32LE(bytes);
// return ref > 0x7fffffff ? ref - 0x100000000 : ref;
// }


function Decoder(bytes) {
var decoded = {};

for (var i = 0; i < bytes.length; ) {
var channel_id = bytes[i++];
var channel_type = bytes[i++];
// BATTERY
if (channel_id === 0x01 && channel_type === 0x75) {
decoded.battery = bytes[i];
i += 1;
}
// TEMPERATURE
else if (channel_id === 0x03 && channel_type === 0x67) {
// ℃
decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10;
i += 2;

// ℉
// decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32;
// i +=2;
}
// HUMIDITY
else if (channel_id === 0x04 && channel_type === 0x68) {
decoded.humidity = bytes[i] / 2;
i += 1;
}
// CO2
else if (channel_id === 0x07 && channel_type === 0x7d) {
decoded.co2 = readUInt16LE(bytes.slice(i, i + 2));
i += 2;
}
// HISTORY DATA
else if (channel_id === 0x20 && channel_type === 0xce) {
var data = {};
data.timestamp = readUInt32LE(bytes.slice(i, i + 4));
data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10;
data.humidity = bytes[i + 6] / 2;
data.co2 = readUInt16LE(bytes.slice(i + 7, i + 9));
i += 9;

decoded.history = decoded.history || [];
decoded.history.push(data);
} else {
break;
}
}

return decoded;

}

// let payload = [{ variable: "payload", value: "0175640367180104686D077DC501" }];

const data = payload.find((x) => x.variable === "payload_raw" || x.variable === "payload" || x.variable === "data");
if (data) {
const buffer = Buffer.from(data.value, "hex");
const serie = new Date().getTime();
payload = payload.concat(Decoder(buffer)).map((x) => ({ ...x, serie }));
}

// console.log(payload);