Sensor
/* This is an generic payload parser example. ** The code find the payload variable and parse it if exists. ** ** IMPORTANT: In most case, you will only need to edit the parsePayload function. ** ** Testing: ** You can do manual tests to this parse by using the Device Emulator. Copy and Paste the following code: ** [{ "variable": "payload", "value": "0109611395" }] ** ** The ignore_vars variable in this code should be used to ignore variables ** from the device that you don't want. */ // Add ignorable variables in this array. const ignore_vars = []; /** * Convert an object to TagoIO object format. * Can be used in two ways: * toTagoFormat({ myvariable: myvalue , anothervariable: anothervalue... }) * toTagoFormat({ myvariable: { value: myvalue, unit: 'C', metadata: { color: 'green' }} , anothervariable: anothervalue... }) * * @param {Object} object_item Object containing key and value. * @param {String} serie Serie for the variables * @param {String} prefix Add a prefix to the variables name */ function toTagoFormat(object_item, serie, prefix = '') { const result = []; for (const key in object_item) { if (ignore_vars.includes(key)) continue; if (typeof object_item[key] === 'object') { result.push({ variable: object_item[key].variable || `${prefix}${key}`, value: object_item[key].value, serie: object_item[key].serie || serie, metadata: object_item[key].metadata, location: object_item[key].location, unit: object_item[key].unit, }); } else { result.push({ variable: `${prefix}${key}`, value: object_item[key], serie, }); } } return result; } function parsePayload(payload_raw) { // If your device is sending something different than hex, like base64, just specify it bellow. const bytes = Buffer.from(payload_raw, 'hex'); const params = { // battery_voltage: null, // reed_state: null, // light_detected: null, // temperature: null, // humidity: null, // impact_magnitude: null, // break_in: null, // acceleration_x: null, // acceleration_y: null, // acceleration_z: null, // reed_count: null, // moisture: null, // activity: null, // mcu_temperature: null, // impact_alarm: null, // activity_count: null, // external_input: null, // external_input_count: null, }; for (let i = 0; i < bytes.length; i++) { // Handle battery voltage if (bytes[i] === 0x00 && bytes[i + 1] === 0xFF) { params.battery_voltage = 0.01 * ((bytes[i + 2] << 8) | bytes[i + 3]); i += 3; } // Handle reed switch state if (bytes[i] === 0x01 && bytes[i + 1] === 0x00) { if (bytes[i + 2] === 0x00) { params.input = -1; } else if (bytes[i + 2] === 0xFF) { params.input = 0; } i += 2; } // Handle light detection if (bytes[i] === 0x02 && bytes[i + 1] === 0x00) { if (bytes[i + 2] === 0x00) { params.light_detected = 0; } else if (bytes[i + 2] === 0xFF) { params.light_detected = 1; } i += 2; } // Handle temperature if (bytes[i] === 0x03 && bytes[i + 1] === 0x67) { // Sign-extend to 32 bits to support negative values, by shifting 24 bits // (16 too far) to the left, followed by a sign-propagating right shift: params.temperature = (bytes[i + 2] << 24 >> 16 | bytes[i + 3]) / 10; i += 3; } // Handle humidity if (bytes[i] === 0x04 && bytes[i + 1] === 0x68) { params.humidity = 0.5 * bytes[i + 2]; i += 2; } // Handle impact magnitude if (bytes[i] === 0x05 && bytes[i + 1] === 0x02) { // Sign-extend to 32 bits to support negative values, by shifting 24 bits // (16 too far) to the left, followed by a sign-propagating right shift: params.impact_magnitude = (bytes[i + 2] << 24 >> 16 | bytes[i + 3]) / 1000; i += 3; } // Handle break-in if (bytes[i] === 0x06 && bytes[i + 1] === 0x00) { if (bytes[i + 2] === 0x00) { params.break_in = false; } else if (bytes[i + 2] === 0xFF) { params.break_in = true; } i += 2; } // Handle accelerometer data if (bytes[i] === 0x07 && bytes[i + 1] === 0x71) { // Sign-extend to 32 bits to support negative values, by shifting 24 bits // (16 too far) to the left, followed by a sign-propagating right shift: params.acceleration_x = (bytes[i + 2] << 24 >> 16 | bytes[i + 3]) / 1000; params.acceleration_y = (bytes[i + 4] << 24 >> 16 | bytes[i + 5]) / 1000; params.acceleration_z = (bytes[i + 6] << 24 >> 16 | bytes[i + 7]) / 1000; i += 7; } // Handle reed switch count if (bytes[i] === 0x08 && bytes[i + 1] === 0x04) { params.input_count = (bytes[i + 2] << 8) | bytes[i + 3]; i += 3; } // Handle moisture if (bytes[i] === 0x09 && bytes[i + 1] === 0x00) { i += 1; // check data if (bytes[i + 1] === 0x00) { params.moisture = false; i += 1; } else if (bytes[i + 1] === 0xFF) { params.moisture = true; i += 1; } } // Handle PIR activity // check the channel and type if (bytes[i] === 0x0A && bytes[i + 1] === 0x00) { i += 1; // check data if (bytes[i + 1] === 0x00) { params.motion_detected = 0; i += 1; } else if (bytes[i + 1] === 0xFF) { params.motion_detected = -1; i += 1; } } // Handle temperature if (bytes[i] === 0x0B && bytes[i + 1] === 0x67) { // Sign-extend to 32 bits to support negative values, by shifting 24 bits // (16 too far) to the left, followed by a sign-propagating right shift: params.mcu_temperature = (bytes[i + 2] << 24 >> 16 | bytes[i + 3]) / 10; i += 3; } // Handle impact alarm if (bytes[i] === 0x0C && bytes[i + 1] === 0x00) { if (bytes[i + 2] === 0x00) { params.impact_alarm = false; } else if (bytes[i + 2] === 0xFF) { params.impact_alarm = true; } i += 2; } // Handle motion (PIR activity) event count if (bytes[i] === 0x0D && bytes[i + 1] === 0x04) { params.motion_count = (bytes[i + 2] << 8) | bytes[i + 3]; i += 3; } // Handle external input state if (bytes[i] === 0x0E && bytes[i + 1] === 0x00) { if (bytes[i + 2] === 0x00) { params.external_input = true; } else if (bytes[i + 2] === 0xFF) { params.external_input = false; } i += 2; } // Handle external input count if (bytes[i] === 0x0F && bytes[i + 1] === 0x04) { params.external_input_count = (bytes[i + 2] << 8) | bytes[i + 3]; i += 3; } } return params; } // let payload = [{ variable: 'payload', value: '036700f204686000ff0129', serie: 122 }]; // Remove unwanted variables. payload = payload.filter(x => !ignore_vars.includes(x.variable)); // Payload is an environment variable. Is where what is being inserted to your device comes in. // Payload always is an array of objects. [ { variable, value...}, {variable, value...} ...] const data = payload.find(x => x.variable === 'payload_raw' || x.variable === 'payload' || x.variable === 'data'); if (data) { // Get a unique serie for the incoming data. const { value, serie } = data; // Parse the payload_raw to JSON format (it comes in a String format) if (value) { payload = payload.concat(toTagoFormat(parsePayload(value), serie)); } } // console.log(payload);
This codec is sourced from TagoIO Github. All rights belong to TagoIO Github.
This codec is licensed under the GNU General Public License v3 (GPL v3). Modifications, if any, are clearly marked. You are free to use, modify, and distribute the codec under the terms of GPL v3.