function reverse(str) { return str.match(/[a-fA-F0-9]{2}/g).reverse().join(''); } function parseDate(payload) { const bin2 = Number(`0x${reverse(payload)}`).toString(2).padStart(32, '0'); const year = parseInt(bin2.substring(0, 7), 2) + 2000; const month = parseInt(bin2.substring(7, 11), 2) - 1; const day = parseInt(bin2.substring(11, 16), 2); const hour = parseInt(bin2.substring(16, 21), 2); const minute = parseInt(bin2.substring(21, 27), 2); const second = parseInt(bin2.substring(27, 32), 2) * 2; return new Date(year, month, day, hour, minute, second, 0).toISOString(); } function parseTimeSync(payload, serie) { // Parse all data and format to TagoIO JSON format. const sync_id = { variable: 'sync_id', serie, value: payload.substring(2, 10) }; const sync_version = { variable: 'sync_version', serie, value: payload.substring(10, 16) }; const application_type = { variable: 'application_type', serie, value: payload.substring(16, 20) }; const rfu = { variable: 'rfu', serie, value: payload.substring(20) }; // Return an array with the content. return [ sync_id, sync_version, application_type, rfu, ]; } function parseMetering(payload) { const time = parseDate(payload.substring(2, 10)); const serie = time; const date = { variable: 'date', value: time, time, serie }; var activeEnergy = parseSignedInt(payload.substring(10, 18)); var reactiveEnergy = parseSignedInt(payload.substring(18, 26)); var apparentEnergy = parseSignedInt(payload.substring(26, 34)); const activeEnergyConst = { variable: 'activeEnergy', value: activeEnergy, unit: 'Wh', time, serie }; const reactiveEnergyConst = { variable: 'reactiveEnergy', value: reactiveEnergy, unit: 'VARh', time, serie }; const apparentEnergyConst = { variable: 'apparentEnergy', value: apparentEnergy, unit: 'VAh', time, serie }; if (payload.length <= 42) { var activation = parseUnsignedInt(payload.substring(34, 42)); const activationConst = { variable: 'activation', value: activation, time, unit: 's', serie }; return [ date, activeEnergyConst, reactiveEnergyConst, apparentEnergyConst, activationConst ]; } else { var activePower = parseSignedShort(payload.substring(34, 38)); var reactivePower = parseSignedShort(payload.substring(38, 42)); var apparentPower = parseSignedShort(payload.substring(42, 46)); var voltage = parseUnsignedShort(payload.substring(46, 50)); var current = parseUnsignedShort(payload.substring(50, 54)); var period = parseUnsignedShort(payload.substring(54, 58)); const activePowerConst = { variable: 'activePower', value: activePower, unit: 'W', time, serie }; const reactivePowerConst = { variable: 'reactivePower', value: reactivePower, unit: 'VAR', time, serie }; const apparentPowerConst = { variable: 'apparentPower', value: apparentPower, unit: 'VA', time, serie }; const voltageConst = { variable: 'voltage', value: voltage, time, unit: 'dv RMS', serie }; const currentConst = { variable: 'current', value: current, time, unit: 'mA RMS', serie }; const periodConst = { variable: 'period', value: period, time, unit: 'us', serie }; if (payload.length > 58) { activation = parseUnsignedInt(payload.substring(58, 66)); const activationConst = { variable: 'activation', value: activation, time, unit: 's', serie }; return [ date, activeEnergyConst, reactiveEnergyConst, apparentEnergyConst, activePowerConst, reactivePowerConst, apparentPowerConst, voltageConst, currentConst, periodConst, activationConst ]; } return [ date, activeEnergyConst, reactiveEnergyConst, apparentEnergyConst, activePowerConst, reactivePower, apparentPowerConst, voltageConst, currentConst, periodConst ]; } } function parseIO(payload) { const time = parseDate(payload.substring(2, 10)); const serie = time; const date = { variable: 'date', value: time, time, serie }; var firstByte = []; var secondByte = []; var thirdByte = []; var fourthByte = []; var k = 0; for (var i = 0; i < 3; i++) { firstByte[i] = parseInt(payload.substring(k + 10, k + 10 + 2), 16); secondByte[i] = parseInt(payload.substring(k + 10 + 2, k + 10 + 4), 16); thirdByte[i] = parseInt(payload.substring(k + 10 + 4, k + 10 + 6), 16); fourthByte[i] = parseInt(payload.substring(k + 10 + 6, k + 10 + 8), 16); k = k + 8; } const input_status8_1 = { variable: 'input_status8_1', value: firstByte[0].toString(2).padStart(8, 0), time, serie }; const input_status9_16 = { variable: 'input_status9_16', value: secondByte[0].toString(2).padStart(8, 0), time, serie }; const input_status17_24 = { variable: 'input_status17_24', value: thirdByte[0].toString(2).padStart(8, 0), time, serie }; const input_status25_32 = { variable: 'input_status25_32', value: fourthByte[0].toString(2).padStart(8, 0), time, serie }; const output_status8_1 = { variable: 'output_status8_1', value: firstByte[1].toString(2).padStart(8, 0), time, serie }; const output_status9_16 = { variable: 'output_status9_16', value: secondByte[1].toString(2).padStart(8, 0), time, serie }; const output_status17_24 = { variable: 'output_status17_24', value: thirdByte[1].toString(2).padStart(8, 0), time, serie }; const output_status25_32 = { variable: 'output_status25_32', value: fourthByte[1].toString(2).padStart(8, 0), time, serie }; const input_trigger8_1 = { variable: 'input_trigger8_1', value: firstByte[2].toString(2).padStart(8, 0), time, serie }; const input_trigger9_16 = { variable: 'input_trigger9_16', value: secondByte[2].toString(2).padStart(8, 0), time, serie }; const input_trigger17_24 = { variable: 'input_trigger17_24', value: thirdByte[2].toString(2).padStart(8, 0), time, serie }; const input_trigger25_32 = { variable: 'input_trigger25_32', value: fourthByte[2].toString(2).padStart(8, 0), time, serie }; return [ date, input_status8_1, input_status9_16, input_status17_24, input_status25_32, output_status8_1, output_status9_16, output_status17_24, output_status25_32, input_trigger8_1, input_trigger9_16, input_trigger17_24, input_trigger25_32 ]; } function parseSignedInt(substring) { substring = switchByte(substring); var rno = hexStringToByteArray(substring); var n = 0; if (rno.length === 4) { n = (rno[0] << 24) & 0xff000000 | (rno[1] << 16) & 0x00ff0000 | (rno[2] << 8) & 0x0000ff00 | (rno[3] << 0) & 0x000000ff; } return n; } function parseUnsignedInt(substring) { substring = switchByte(substring); var rno = hexStringToByteArray(substring); var l; if (rno.length === 4) { l = (rno[0] << 24) & 0x00000000ff000000 | (rno[1] << 16) & 0x0000000000ff0000 | (rno[2] << 8) & 0x000000000000ff00 | (rno[3] << 0) & 0x00000000000000ff; } return l; } function parseSignedShort(substring) { substring = switchByte(substring); var rno = hexStringToByteArray(substring); var i = 0; if (rno.length === 2) { i = ((rno[0] << 8) & 0x0000ff00 | (rno[1] << 0) & 0x000000ff); } return i; } function parseUnsignedShort(substring) { substring = switchByte(substring); var rno = hexStringToByteArray(substring); var i = 0; if (rno.length === 2) { i = (rno[0] << 8) & 0x0000ff00 | (rno[1] << 0) & 0x000000ff; } return i; } function switchByte(bytes) { var mirrored = bytes; if (bytes.length % 2 === 0) { mirrored = ""; for (var starting = 0; starting + 2 <= bytes.length; starting += 2) { mirrored = bytes.substring(starting, starting + 2) + mirrored; } } return mirrored; } function hexStringToByteArray(s) { for (var bytes = [], c = 0; c < s.length; c += 2) bytes.push(parseInt(s.substr(c, 2), 16)); return bytes; } /* function getStatus(imageFromSensor) { var inputMask = (switchByte(imageFromSensor), 16); var status = []; for (var i = 0; i < 32; i++) { status[i] = getBit(inputMask, i); } return status; } */ function getStatus(imageFromSensor) { var inputMask = (imageFromSensor); var status = inputMask; return status; } function getBit(n, k) { return ((n >> k) & 1) == 1; } // Check if the incoming data is from TTN. const data = payload.find(x => x.variable === 'payload_raw' || x.variable === 'payload'); if (data) { // Get a unique serie for the incoming data. const serie = data.serie ? `${new Date().getTime()}-${data.serie}` : new Date().getTime(); // Parse the data to JSON format (it comes in a String format) const raw_payload = data.value; // Get the Payload ID. const uplinkId = raw_payload.substring(0, 2); // Apply different parsers for each ID. let content; switch (uplinkId.toUpperCase()) { case '01': content = parseTimeSync(raw_payload, serie); break; case '09': content = parseMetering(raw_payload, serie); break; case '0A': content = parseIO(raw_payload); break; default: break; } // Change the payload to the parsed variables. payload = content; }