Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * SenseCAP & TTN (new v3) Converter
- *
- * @since 3.0
- * @return Object
- * @param Boolean valid Indicates whether the payload is a valid payload.
- * @param String err The reason for the payload to be invalid. 0 means valid, minus means invalid.
- * @param String payload Hexadecimal string, to show the payload.
- * @param Array messages One or more messages are parsed according to payload.
- * type // Enum:
- * // - "report_telemetry"
- * // - "upload_battery"
- * // - "upload_interval"
- * // - "upload_version"
- * // - "upload_sensor_id"
- * // - "report_remove_sensor"
- * // - "unknown_message"
- *
- *
- *
- *
- * @sample-1
- * var sample = Decoder(["00", "00", "00", "01", "01", "00", "01", "00", "07", "00", "64", "00", "3C", "00", "01", "20", "01", "00", "00", "00", "00", "28", "90"], null);
- * {
- * valid: true,
- * err: 0,
- * payload: '0000000101000100070064003C00012001000000002890',
- * messages: [
- * { type: 'upload_version',
- * hardwareVersion: '1.0',
- * softwareVersion: '1.1' },
- * { type: 'upload_battery', battery: 100 },
- * { type: 'upload_interval', interval: 3600 },
- * { type: 'report_remove_sensor', channel: 1 }
- * ]
- * }
- * @sample-2
- * var sample = Decoder(["01", "01", "10", "98", "53", "00", "00", "01", "02", "10", "A8", "7A", "00", "00", "AF", "51"], null);
- * {
- * valid: true,
- * err: 0,
- * payload: '01011098530000010210A87A0000AF51',
- * messages: [
- * { type: 'report_telemetry',
- * measurementId: 4097,
- * measurementValue: 21.4 },
- * { type: 'report_telemetry',
- * measurementId: 4098,
- * measurementValue: 31.4 }
- * ]
- * }
- * @sample-3
- * var sample = Decoder(["01", "01", "00", "01", "01", "00", "01", "01", "02", "00", "6A", "01", "00", "15", "01", "03", "00", "30", "F1", "F7", "2C", "01", "04", "00", "09", "0C", "13", "14", "01", "05", "00", "7F", "4D", "00", "00", "01", "06", "00", "00", "00", "00", "00", "4C", "BE"], null);
- * {
- * valid: true,
- * err: 0,
- * payload: '010100010100010102006A01001501030030F1F72C010400090C13140105007F4D0000010600000000004CBE',
- * messages: [
- * { type: 'upload_sensor_id', sensorId: '30F1F72C6A010015', channel: 1 }
- * ]
- * }
- */
- /**
- * Entry, decoder.js
- */
- function decodeUplink(input) {
- var bytes = input['bytes'];
- // init
- var bytesString = bytes2HexString(bytes).toLocaleUpperCase();
- var decoded = {
- // valid
- valid: true,
- err: 0,
- // bytes
- payload: bytesString,
- // messages array
- messages: [],
- };
- // CRC check
- if (!crc16Check(bytesString)) {
- decoded['valid'] = false;
- decoded['err'] = -1; // "crc check fail."
- return { data: decoded };
- }
- // Length Check
- if ((bytesString.length / 2 - 2) % 7 !== 0) {
- decoded['valid'] = false;
- decoded['err'] = -2; // "length check fail."
- return { data: decoded };
- }
- // Cache sensor id
- var sensorEuiLowBytes;
- var sensorEuiHighBytes;
- // Handle each frame
- var frameArray = divideBy7Bytes(bytesString);
- for (var forFrame = 0; forFrame < frameArray.length; forFrame++) {
- var frame = frameArray[forFrame];
- // Extract key parameters
- var channel = strTo10SysNub(frame.substring(0, 2));
- var dataID = strTo10SysNub(frame.substring(2, 6));
- var dataValue = frame.substring(6, 14);
- var realDataValue = isSpecialDataId(dataID) ? ttnDataSpecialFormat(dataID, dataValue) : ttnDataFormat(dataValue);
- if (checkDataIdIsMeasureUpload(dataID)) {
- // if telemetry.
- decoded.messages.push({
- type: 'report_telemetry',
- measurementId: dataID,
- measurementValue: realDataValue,
- });
- } else if (isSpecialDataId(dataID) || dataID === 5 || dataID === 6) {
- // if special order, except "report_sensor_id".
- switch (dataID) {
- case 0x00:
- // node version
- var versionData = sensorAttrForVersion(realDataValue);
- decoded.messages.push({
- type: 'upload_version',
- hardwareVersion: versionData.ver_hardware,
- softwareVersion: versionData.ver_software,
- });
- break;
- case 1:
- // sensor version
- break;
- case 2:
- // sensor eui, low bytes
- sensorEuiLowBytes = realDataValue;
- break;
- case 3:
- // sensor eui, high bytes
- sensorEuiHighBytes = realDataValue;
- break;
- case 7:
- // battery power && interval
- decoded.messages.push(
- {
- type: 'upload_battery',
- battery: realDataValue.power,
- },
- {
- type: 'upload_interval',
- interval: parseInt(realDataValue.interval) * 60,
- }
- );
- break;
- case 0x120:
- // remove sensor
- decoded.messages.push({
- type: 'report_remove_sensor',
- channel: 1,
- });
- break;
- default:
- break;
- }
- } else {
- decoded.messages.push({
- type: 'unknown_message',
- dataID: dataID,
- dataValue: dataValue,
- });
- }
- }
- // if the complete id received, as "upload_sensor_id"
- if (sensorEuiHighBytes && sensorEuiLowBytes) {
- decoded.messages.unshift({
- type: 'upload_sensor_id',
- channel: 1,
- sensorId: (sensorEuiHighBytes + sensorEuiLowBytes).toUpperCase(),
- });
- }
- // return
- return { data: decoded };
- }
- function crc16Check(data) {
- return true;
- }
- // util
- function bytes2HexString(arrBytes) {
- var str = '';
- for (var i = 0; i < arrBytes.length; i++) {
- var tmp;
- var num = arrBytes[i];
- if (num < 0) {
- tmp = (255 + num + 1).toString(16);
- } else {
- tmp = num.toString(16);
- }
- if (tmp.length === 1) {
- tmp = '0' + tmp;
- }
- str += tmp;
- }
- return str;
- }
- // util
- function divideBy7Bytes(str) {
- var frameArray = [];
- for (var i = 0; i < str.length - 4; i += 14) {
- var data = str.substring(i, i + 14);
- frameArray.push(data);
- }
- return frameArray;
- }
- // util
- function littleEndianTransform(data) {
- var dataArray = [];
- for (var i = 0; i < data.length; i += 2) {
- dataArray.push(data.substring(i, i + 2));
- }
- dataArray.reverse();
- return dataArray;
- }
- // util
- function strTo10SysNub(str) {
- var arr = littleEndianTransform(str);
- return parseInt(arr.toString().replace(/,/g, ''), 16);
- }
- // util
- function checkDataIdIsMeasureUpload(dataId) {
- return parseInt(dataId) > 4096;
- }
- // configurable.
- function isSpecialDataId(dataID) {
- switch (dataID) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 7:
- case 0x120:
- return true;
- default:
- return false;
- }
- }
- // configurable
- function ttnDataSpecialFormat(dataId, str) {
- var strReverse = littleEndianTransform(str);
- if (dataId === 2 || dataId === 3) {
- return strReverse.join('');
- }
- // handle unsigned number
- var str2 = toBinary(strReverse);
- var dataArray = [];
- switch (dataId) {
- case 0: // DATA_BOARD_VERSION
- case 1: // DATA_SENSOR_VERSION
- // Using point segmentation
- for (var k = 0; k < str2.length; k += 16) {
- var tmp146 = str2.substring(k, k + 16);
- tmp146 = (parseInt(tmp146.substring(0, 8), 2) || 0) + '.' + (parseInt(tmp146.substring(8, 16), 2) || 0);
- dataArray.push(tmp146);
- }
- return dataArray.join(',');
- case 4:
- for (var i = 0; i < str2.length; i += 8) {
- var item = parseInt(str2.substring(i, i + 8), 2);
- if (item < 10) {
- item = '0' + item.toString();
- } else {
- item = item.toString();
- }
- dataArray.push(item);
- }
- return dataArray.join('');
- case 7:
- // battery && interval
- return {
- interval: parseInt(str2.substr(0, 16), 2),
- power: parseInt(str2.substr(-16, 16), 2),
- };
- }
- }
- // util
- function ttnDataFormat(str) {
- var strReverse = littleEndianTransform(str);
- var str2 = toBinary(strReverse);
- if (str2.substring(0, 1) === '1') {
- var arr = str2.split('');
- var reverseArr = [];
- for (var forArr = 0; forArr < arr.length; forArr++) {
- var item = arr[forArr];
- if (parseInt(item) === 1) {
- reverseArr.push(0);
- } else {
- reverseArr.push(1);
- }
- }
- str2 = parseInt(reverseArr.join(''), 2) + 1;
- return parseFloat('-' + str2 / 1000);
- }
- return parseInt(str2, 2) / 1000;
- }
- // util
- function sensorAttrForVersion(dataValue) {
- var dataValueSplitArray = dataValue.split(',');
- return {
- ver_hardware: dataValueSplitArray[0],
- ver_software: dataValueSplitArray[1],
- };
- }
- // util
- function toBinary(arr) {
- var binaryData = [];
- for (var forArr = 0; forArr < arr.length; forArr++) {
- var item = arr[forArr];
- var data = parseInt(item, 16).toString(2);
- var dataLength = data.length;
- if (data.length !== 8) {
- for (var i = 0; i < 8 - dataLength; i++) {
- data = '0' + data;
- }
- }
- binaryData.push(data);
- }
- return binaryData.toString().replace(/,/g, '');
- }
- // Samples
- // var sample = Decoder(["00", "00", "00", "01", "01", "00", "01", "00", "07", "00", "64", "00", "3C", "00", "01", "20", "01", "00", "00", "00", "00", "28", "90"], null);
- // var sample = Decoder(["01", "01", "10", "98", "53", "00", "00", "01", "02", "10", "A8", "7A", "00", "00", "AF", "51"], null);
- // var sample = Decoder(["01", "01", "00", "01", "01", "00", "01", "01", "02", "00", "6A", "01", "00", "15", "01", "03", "00", "30", "F1", "F7", "2C", "01", "04", "00", "09", "0C", "13", "14", "01", "05", "00", "7F", "4D", "00", "00", "01", "06", "00", "00", "00", "00", "00", "4C", "BE"], null);
- // console.log(sample);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement