TRP-11 Electro
Last updated
Last updated
In the projects it has:
{
"cmd": "gw",
"seqno": 127364,
"EUI": "BE7A000000000019",
"ts": 1661429994737,
"fcnt": 20744,
"port": 3,
"freq": 868500000,
"toa": 1646,
"dr": "SF12 BW125 4/5",
"ack": false,
"gws": [{
"rssi": -63,
"snr": 4.2,
"ts": 1661429994737,
"time": "2022-08-25T12:19:54.703339Z",
"gweui": "9C65F9FFFF3CDE7F",
"ant": 0,
"lat": 47.3759744,
"lon": 8.5327872
}, {
"rssi": -111,
"snr": -0.2,
"ts": 1661429994745,
"time": "2022-08-25T12:19:54.681657Z",
"gweui": "9C65F9FFFF3CDDC3",
"ant": 0,
"lat": 47.3759744,
"lon": 8.5327872
}],
"bat": 255,
"data": "0180011cd5a3603d61008144b2328f",
"_id": "630768ea3184c84733e88996"
}
jso
{
"msg": {
"batteryVoltage": 3.63,
"mBusMeterStatus": 0,
"electricityMeterEnergy": 1425.5799560546875,
"ts": 1661262701281,
"rssi": -80,
"snr": 9.8,
"toa": 61,
"frequency": 867700000,
"dr": "SF7 BW125 4/5",
"bat": "External power source",
"hex": "0180011cd5a3603d61008144b2328f"
},
"metadata": {
"deviceType": "default",
"deviceName": "Test Device",
"ts": "1661430878088"
},
"msgType": "POST_TELEMETRY_REQUEST"
}
in manual | dataKey | dataType | dataFormat |
---|---|---|---|
Temperature
temperature
telemetry
integer
Relative Humidity
humidity
telemetry
integer
Oxygen concentration
oxygen
telemetry
CO2 concentration
co2
telemetry
Second temperature
temperature2
telemetry
integer
Pressure
pressure
telemetry
integer
analog channel #0
analogCurrent0
telemetry
analog channel #1
analogCurrent1
telemetry
analog channel #2
analogCurrent2
telemetry
analog channel #3
analogCurrent3
telemetry
digital inputs state
digitalInputsState
telemetry
relative pulse counter 0
relativePulseCounter0
telemetry
relative pulse counter 1
relativePulseCounter1
telemetry
relative pulse counter 2
relativePulseCounter2
telemetry
analog channel #0
analogVoltage0
telemetry
analog channel #1
analogVoltage1
telemetry
analog channel #2
analogVoltage2
telemetry
analog channel #3
analogVoltage3
telemetry
Main energy index
electricityMeterEnergy
telemetry
float
Main energy index
register0801
telemetry
float
Main energy index
register0802
telemetry
float
Main energy index
waterMeter
telemetry
float
Main energy index
gasMeterVolume
telemetry
float
Flow temperature
flowTemperature
telemetry
float
Power register
power
telemetry
float
Volume index
heatMeterVolume
telemetry
float
Return flow temperature
returnFlowTemperature
telemetry
float
VolumeFlow
flowrate
telemetry
float
floating point
heatMeterEnergy
telemetry
float
Battery
batteryVoltage
telemetry
M-BUS meter status byte
mBusMeterStatus
telemetry
// V1.0, 09.08.2021, DS
// V1.1, 11.03.2022, DS
if (msg.data) {
var decoded = decodeFromHex(parseHexString(msg.data));
if(decoded.register0801 != null && decoded.register0802 != null){
decoded.electricityMeterEnergy = decoded.register0801 + decoded.register0802;
}
decoded.ts = msg.ts;
decoded.rssi = msg.rssi;
decoded.snr = msg.snr;
decoded.toa = msg.toa;
decoded.frequency = msg.frequency;
decoded.dr = msg.dr;
decoded.bat = decodeBattery(msg.bat);
decoded.hex = msg.data;
return {
msg: decoded,
metadata: metadata,
msgType: msgType
};
} else {
return {
msg: msg,
metadata: metadata,
msgType: msgType
};
}
function decodeFromHex(bytes) {
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.
var telemetry = {};
// Get data length, main_header and initiate the counter
var sensorDataLength = bytes.length;
var counter = 1;
var main_header = bytes[0];
// Loop through the data and decode the chuncks. Add them to the telemetry
// immediatly
while (counter < sensorDataLength) {
var identifier = bytes[counter];
var chunkLength = 0;
var obj = {};
var subbytes = [];
if (identifier >= 01 && identifier <= 95) {
//identifierChunch = "ChunkTypeA";
chunkLength =
3; // Type A Chunk. Fixed size. 3 bytes
subbytes = bytes.slice(counter, counter +
chunkLength);
obj = parseChunkTypeA(subbytes);
} else if (identifier >= 96 && identifier <= 127) {
//identifierChunch = "ChunkTypeD";
chunkLength =
2; // Type D Chunk. Fixed size. 2 bytes
subbytes = bytes.slice(counter, counter +
chunkLength);
obj = parseChunkTypeD(subbytes);
} else if (identifier >= 128 && identifier <= 191) {
//identifierChunch = "ChunkTypeB";
chunkLength =
5; // Type B Chunk. Fixed size. 5 bytes
subbytes = bytes.slice(counter, counter +
chunkLength);
obj = parseChunkTypeB(subbytes);
} else if (identifier >= 192 && identifier <= 254) {
//identifierChunch = "ChunkTypeC";
chunkLength = bytes[counter + 1] +
2; // Type C Chunk. Variable size. Size + 2 (+ leading 2 bytes)
if (counter + chunkLength > sensorDataLength) {
chunkLength = sensorDataLength - counter;
}
// check if there already is a timesatmp present
var timestamp = msg.ts;
// if ('ts' in telemetry) {
// timestamp = telemetry[0].ts;
// }
subbytes = bytes.slice(counter, counter +
chunkLength);
// check if the payload already contained a timestamp
obj = parseChunkTypeC(subbytes, timestamp);
} else {
continue;
}
// Push the parsed data to the telemetry array and increment counter
// Check if it is an array, push the data if yes, otherwise concatenate
if (Array.isArray(obj)) {
telemetry.push(obj);
} else {
telemetry = Object.assign(telemetry, obj);
}
counter += chunkLength;
}
// check if the timestamp has been filled by the payload, otherwise use
// the timestamp of the uplink to loriot
if (!('ts' in telemetry)) {
telemetry.ts = msg.ts;
}
return telemetry;
}
function decodeBattery(byte) {
if (byte == 0) {
return 'External power source';
} else if (byte > 0 && byte < 255) {
return byte / 254 * 100;
} else {
return 'Unknown battery state'
}
}
function parseHexString(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
function decodeToString(payload) {
return String.fromCharCode.apply(String, payload);
}
function decodeToJson(payload) {
// covert payload to string.
var str = decodeToString(payload);
// parse string to JSON
var data = JSON.parse(str);
return data;
}
function twos_complement(input_value, num_bits) {
var mask = Math.pow(2, num_bits - 1);
return -(input_value & mask) + (input_value & ~mask);
}
function get_int(bytes) {
var length = bytes.length;
var int = 0;
var i;
for (i = 0; i < length; i++) {
int += bytes[length - i - 1] << (i * 8);
}
return int;
}
function get_float(bytes) {
var length = bytes.length;
var float = 0;
var int = get_int(bytes);
if (length == 4) {
var sign = (int & 0x80000000) ? -1 : 1;
var exponent = ((int >> 23) & 0xFF) - 127;
var significand = (int & ~(-1 << 23));
if (exponent == 128) {
float = sign * ((significand) ? Number.NaN :
Number.POSITIVE_INFINITY);
} else if (exponent == -127) {
if (significand == 0) {
float = sign * 0.0;
} else {
exponent = -126;
significand /= (1 << 22);
float = sign * significand * Math.pow(2,
exponent);
}
} else {
significand = (significand | (1 << 23)) / (1 <<
23);
float = sign * significand * Math.pow(2,
exponent);
}
} else if (length == 2) {
var left = (int >> 14) & 0x03;
var value0 = int & 0x3FFF;
float = value0;
if (left == 0) {
float = float * 0.001;
} else if (left == 1) {
float = float * 0.02;
float = float + 16.38;
} else if (left == 3) {
float = float * 5;
float = float + 16725;
} else if (left == 2) {
float = float + 344;
}
} else {
throw "Undefined floating point size";
}
return float;
}
function parseChunkTypeA(bytes) {
var telemetry = {};
var dataHeader = bytes[0];
var dataValue = get_int(bytes.slice(1));
if (dataHeader ==
1
) { // 1 = 0x01 Temperature. signed integer 16bits. 1 LSB = 0.01°C. 0: 0°C; 1: +0.01°C; 0xFFFF : -0.01°C
telemetry.temperature = twos_complement(dataValue,
16) / 100;
} else if (dataHeader ==
2
) { // 2 = 0x02 Relative Humidity. unsigned integer 16bits. 1 LSB = 0.01°RH
telemetry.humidity = twos_complement(dataValue,
16) / 100;
} else if (dataHeader ==
3
) { // 3 = 0x03 Oxygen concentration. 1 LSB = 0.001%
telemetry.oxygen = dataValue / 1000;
} else if (dataHeader ==
4) { // 4 = 0x04 CO2 concentration. 1 LSB = 0.001%
telemetry.co2 = dataValue / 1000;
} else if (dataHeader ==
5
) { // 5 = 0x05 Second temperature. signed integer 16bits. 1 LSB = 0.01°C. 0: 0°C; 1: +0.01°C; 0xFFFF : -0.01°C
telemetry.temperature2 = twos_complement(dataValue,
16) / 100;
} else if (dataHeader ==
6
) { // 6 = 0x06 Pressure. unsigned integer 16bits. 1 LSB = 0.5mbar
telemetry.pressure = dataValue / 2;
} else if (dataHeader ==
7) { // 7 = 0x07 analog channel #0. 1 LSB = 1 uA
telemetry.analogCurrent0 = dataValue;
} else if (dataHeader ==
8) { // 8 = 0x08 analog channel #1. 1 LSB = 1 uA
telemetry.analogCurrent1 = dataValue;
} else if (dataHeader ==
9) { // 9 = 0x09 analog channel #2. 1 LSB = 1 uA
telemetry.analogCurrent2 = dataValue;
} else if (dataHeader ==
10) { // 10 = 0x0A analog channel #3. 1 LSB = 1 uA
telemetry.analogCurrent3 = dataValue;
} else if (dataHeader ==
11) { // 11 = 0x0B digital inputs state
telemetry.digitalInputsState = dataValue;
} else if (dataHeader ==
12) { // 12 = 0x0C relative pulse counter 0
telemetry.relativePulseCounter0 = dataValue;
} else if (dataHeader ==
13) { // 13 = 0x0D relative pulse counter 1
telemetry.relativePulseCounter1 = dataValue;
} else if (dataHeader ==
14) { // 14 = 0x0E relative pulse counter 2
telemetry.relativePulseCounter2 = dataValue;
} else if (dataHeader ==
16) { // 16 = 0x10 analog channel #0. 1 LSB = 1 mV
telemetry.analogVoltage0 = dataValue;
} else if (dataHeader ==
17) { // 17 = 0x11 analog channel #1. 1 LSB = 1 mV
telemetry.analogVoltage1 = dataValue;
} else if (dataHeader ==
18) { // 18 = 0x12 analog channel #2. 1 LSB = 1 mV
telemetry.analogVoltage2 = dataValue;
} else if (dataHeader ==
19) { // 19 = 0x12 analog channel #3. 1 LSB = 1 mV
telemetry.analogVoltage3 = dataValue;
}
return telemetry;
}
function parseChunkTypeB(bytes) {
var telemetry = {};
var dataHeader = bytes[0];
var dataValue = bytes.slice(1);
// console.log(dataHeader)
if (dataHeader ==
128
) { // 128 = 0x80 timestamp of the measurement. unsigned integer 32 bits. UNIX timestamp
// console.log(dataValue)
// console.log(get_int(dataValue))
//telemetry.ts = twos_complement(get_int(dataValue), 32) *1000; // calculate it in miliseconds
} else if (dataHeader ==
129
) { // 129 = 0x81 Main energy index. IEEE754 floating point. Unit : kWh for electricity meters (register 1.8.0)
telemetry.electricityMeterEnergy = get_float(
dataValue);
} else if (dataHeader ==
131
) { // 129 = 0x81 Main energy index. IEEE754 floating point. Unit : kWh for electricity meters (register 1.8.0)
telemetry.register0801 = get_float(
dataValue);
} else if (dataHeader ==
132
) { // 129 = 0x81 Main energy index. IEEE754 floating point. Unit : kWh for electricity meters (register 1.8.0)
telemetry.register0802 = get_float(
dataValue);
} else if (dataHeader ==
133
) { // 133 = 0x85 Main energy index. IEEE754 floating point. Unit : m3 for water meter
telemetry.waterMeter = get_float(dataValue);
} else if (dataHeader ==
134
) { // 134 = 0x86 Main energy index. IEEE754 floating point. Unit : m3 for uncorrected gas meter
telemetry.gasMeterVolume = get_float(dataValue);
} else if (dataHeader ==
135
) { // 135 = 0x87 Flow temperature. IEEE754 floating point. Unit : °C
telemetry.flowTemperature = get_float(dataValue);
} else if (dataHeader ==
138
) { // 138 = 0x8a Power register. IEEE754 floating point. Unit W.
telemetry.power = get_float(dataValue);
} else if (dataHeader ==
139
) { // 139 = 0x8b Volume index. IEEE754 floating point. Unit: m3 for heat meter
telemetry.heatMeterVolume = get_float(dataValue);
} else if (dataHeader ==
140
) { // 140 = 0x8c Return flow temperature. IEEE754 floating point. Unit: °C
telemetry.returnFlowTemperature = get_float(
dataValue);
} else if (dataHeader ==
141
) { // 141 = 0x8d VolumeFlow = flowRate. IEEE754 floating point. Unit: m3/h
telemetry.flowRate = get_float(dataValue);
} else if (dataHeader ==
154
) { // 154 = 0x9A IEEE754 floating point. Unit : kWh for heat meters (register 1.8.0)
telemetry.heatMeterEnergy = get_float(dataValue);
}
return telemetry;
}
function parseChunkTypeC(bytes, timestamp) {
var telemetry = [];
var size = bytes.length;
var dataHeader = bytes[0];
var snr = get_int(bytes.slice(1, 5));
var status = bytes.slice(5, 6);
var interval =
900000; // accumulation interval in milliseconds
var lastReadIndex = get_float(bytes.slice(6, 10));
var idx = 10;
var counter = 1;
// Get the interval from the status
if ((status & 0x1c) == 0) {
interval = 3600000;
} else if ((status & 0x1c) == 0x4) {
interval = 900000;
} else if ((status & 0x1c) == 0x8) {
interval = 38400000;
}
// Loop through the deltas and change the timestamp accordingly
if (dataHeader ==
201
) { // 140 = 0x8c Return flow temperature. IEEE754 floating point. Unit: °C
telemetry.push({
//'ts': timestamp,
'waterMeterSNR': snr,
'waterMeterCounter': lastReadIndex,
'batteryError': Boolean(status &
0x2),
'otherError': Boolean(status & 1)
})
while (idx <= size) {
var slice = bytes.slice(idx, idx + 2);
if (!(get_int(slice) == 0xffff)) {
telemetry.push({
//'ts': timestamp - counter * interval,
'waterMeterCounter': lastReadIndex +
get_float(slice)
})
}
idx += 2;
counter++;
}
} else if (dataHeader ==
202
) { // 141 = 0x8d Volume flow. IEEE754 floating point. Unit: m3/h
telemetry.push({
//'ts': timestamp,
'gasMeterSNR': snr,
'gasMeterCounter': lastReadIndex,
'batteryError': Boolean(status &
0x2),
'otherError': Boolean(status & 1)
})
while (idx <= size) {
var slice = bytes.slice(idx, idx + 2);
if (!(get_int(slice) == 0xffff)) {
telemetry.push({
//'ts': timestamp - counter * interval,
'gasMeterCounter': lastReadIndex +
get_float(slice)
})
}
idx += 2;
counter++;
}
}
return telemetry;
}
function parseChunkTypeD(bytes) {
var telemetry = {};
var dataHeader = bytes[0];
var dataValue = get_int(bytes.slice(1));
if (dataHeader == 96) { // 96 = 0x60 Battery voltage
var volt = 0;
if (dataValue >= 81) {
volt = 4.2 + (dataValue - 80) * 0.1
} else {
volt = 1.8 + dataValue * 0.03
}
telemetry.batteryVoltage = volt;
} else if (dataHeader ==
97) { // 97 = 0x61 M-BUS meter status byte
telemetry.mBusMeterStatus = dataValue;
}
return telemetry;
}
function decodeBattery(byte) {
if (byte == 0) {
return 'External power source';
} else if (byte > 0 && byte < 255) {
return byte / 254 * 100;
} else {
return 'Unknown battery state';
}
}