MTKcoder
The MTKcoder measures even the smallest flow rates. Perfect areas of application are measuring points that are difficult to access, such as in manholes or in the automation of fixed network readout.
Last updated
The MTKcoder measures even the smallest flow rates. Perfect areas of application are measuring points that are difficult to access, such as in manholes or in the automation of fixed network readout.
Last updated
in manual | dataKey | dataType | dataFormat |
---|---|---|---|
Hauswasserzähler | waterMeter | telemetry | float |
{
"cmd": "gw",
"seqno": 114935,
"EUI": "10CE45FFFE00AAAD",
"ts": 1660726181716,
"fcnt": 4198,
"port": 2,
"freq": 867300000,
"toa": 97,
"dr": "SF7 BW125 4/5",
"ack": false,
"gws": [{
"rssi": -41,
"snr": 9.8,
"ts": 1660726181716,
"time": "2022-08-17T08:49:41.585149Z",
"gweui": "9C65F9FFFF386C4F",
"ant": 0,
"lat": 46.8076885,
"lon": 7.100528
}],
"bat": 0,
"data": "230400681b1b6808007200375316e61e3c07040000000c78003753160c13580319173316",
"_id": "62fcaba53184c84733df3296"
}
// V3.0 10.05.2022, DS
// V4.0, 06.07.2022, FU
// V5.0 , 11.07.2022, PA
//var medium_table = {
// "Gas": "03",
// "Electricity": "02",
// "Heat: Outlet": "04",
// "Heat: Inlet": "0C",
// "Water": "07",
// "Cold water": "16",
// "Other": "00",
// "Warm water (30-90ðC)": "06",
//};
//Code entry
if (msg.data) {
var decoded = decodeFromHex(msg.data.toString());
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(data) {
// Decode uplink message
var decoded = {};
//Parse string as bytes
var bytes = parseHexString(data);
//scale to manage the different scales with none, one or more decimals on the meter.
var scale = metadata.ss_scale;
//various info that can be extracted
var length = bytes[0];
var msgType = bytes[1];
var slaveCount = bytes[2];
var startCharacter1 = bytes[3];
var length1 = bytes[4];
var length2 = bytes[5];
var startCharacter2 = bytes[6];
var c = bytes[7];
var a = bytes[8];
//72 or 76 -> variable; 73 or 77 -> fixed
var ciField = bytes[9];
var medium = data.substr(34, 2);
var checkSum = bytes[36];
//Different medium IDs, register positions vary
if (medium == "02") {
var volume = data.substr(72, 2) + data.substr(70,
2) + data.substr(68, 2) + data.substr(66, 2);
decoded.electricityMeterEnergyHt = parseInt(volume,
16) * scale;
volume = data.substr(88, 2) + data.substr(86, 2) +
data.substr(84, 2) + data.substr(82, 2);
decoded.electricityMeterEnergyNt = parseInt(volume,
16) * scale;
}
if (medium == "03") {
var volume = data.substr(66, 2) + data.substr(64,
2) + data.substr(62, 2) + data.substr(60, 2);
decoded.gasMeterVolume = parseInt(volume) * scale;
}
if (medium == "16") {
var volume = data.substr(54, 2) + data.substr(52,
2) + data.substr(50, 2) + data.substr(48, 2);
decoded.waterMeter = parseInt(volume, 16) * scale;
}
/* PA
if (medium == "07") {
var volume = data.substr(54, 2) + data.substr(52,
2) + data.substr(50, 2) + data.substr(48, 2);
decoded.waterMeter = parseInt(volume, 16) * scale;
}
*/
if (medium == "07") {
var volume = data.substr(66, 2) + data.substr(64,
2) + data.substr(62, 2) + data.substr(60, 2);
var gwf_scale = 1;
switch (data.substr(58, 2)) {
case "13":
gwf_scale = 0.001;
break;
case "14":
gwf_scale = 0.01;
break;
case "15":
gwf_scale = 0.1;
break;
case "16":
gwf_scale = 1;
break;
case "17":
gwf_scale = 10;
break;
default:
break;
}
decoded.waterMeter = volume * gwf_scale;
}
if (medium == "04") {
var volume = data.substr(54, 2) + data.substr(52,
2) + data.substr(50, 2) + data.substr(48, 2);
decoded.waterMeter = parseInt(volume, 16) * scale;
}
return decoded;
}
//Helper functions
function parseHexString(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
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 parseFloat(str) {
var float = 0,
sign, order, mantissa, exp,
int = 0,
multi = 1;
if (/^0x/.exec(str)) {
int = parseInt(str, 16);
} else {
for (var i = str.length - 1; i >= 0; i -= 1) {
if (str.charCodeAt(i) > 255) {
console.log('Wrong string parameter');
return false;
}
int += str.charCodeAt(i) * multi;
multi *= 256;
}
}
sign = (int >>> 31) ? -1 : 1;
exp = (int >>> 23 & 0xff) - 127;
mantissa = ((int & 0x7fffff) + 0x800000).toString(2);
for (i = 0; i < mantissa.length; i += 1) {
float += parseInt(mantissa[i]) ? Math.pow(2, exp) :
0;
exp--;
}
return float * sign;
}
//V1.0, 20.12.2021,DS
if (msg.data) {
var decoded = decodeFromHex(msg.data);
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(data) {
var telemetry = {};
//var batteryStatus = BatteryStatus.CalculateBatterStatus((int) rawMessageSection.bat);
// Unstring input payload according to the specification
//string protocolType = sensorData.Substring(0, 2);
//string meterManufacturerID = sensorData.Substring(2, 4);
//string meterID = sensorData.Substring(6, 8);
var meterMedium = data.substr(14, 2);
//telemetry.meterMedium = meterMedium;
var stateMbus = data.substr(16, 2);
//telemetry.stateMbus = stateMbus;
//string actualityDuration = sensorData.Substring(18, 4);
var volumeVIF = data.substr(22, 2);
//telemetry.volumeVIF = volumeVIF;
var volumeValue = data.substr(24, 8);
//telemetry.volumeValue = volumeValue;
//string additionalFunctions = sensorData.Substring(32, 2);
//string batteryLifetime = sensorData.Substring(34, 2);
//string checksum = sensorData.Substring(36, 4);
telemetry.unit = "m3";
if (meterMedium == "07" && (stateMbus == "00" |
stateMbus == "04")) {
telemetry.waterMeter =
GetMeterReadingWarmWater(volumeVIF,
volumeValue);
}
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';
}
}
// Decode Payload for the meter reading warm water
function GetMeterReadingWarmWater(volumeVIF, volumeValue) {
var volumeValueLSB = volumeValue.substr(6, 2) +
volumeValue.substr(4, 2) + volumeValue.substr(2,
2) + volumeValue.substr(0, 2);
var measurementResult = parseInt(volumeValueLSB,
16);
switch (volumeVIF) {
case "10":
measurementResult *=
0.000001; // (10 ^ (-6));
break;
case "11":
measurementResult *=
0.00001; // (10 ^ (-5));
break;
case "12":
measurementResult *= 0.0001; // (10 ^ (-4));
break;
case "13":
measurementResult *= 0.001; // (10 ^ (-3));
break;
case "14":
measurementResult *= 0.01; // (10 ^ (-2));
break;
case "15":
measurementResult *= 0.1; // (10 ^ (-1));
break;
default:
break;
}
return measurementResult;
}