UNPKG

node-red-contrib-cayennelpp

Version:
263 lines (248 loc) 9.3 kB
// https://github.com/FIWARE-GEs/iot-agent.LoraWAN/blob/bfbb71bb24eedbde3beaa610d92c551aa3e12d2d/lib/dataModels/cayenneLpp.js 'use strict'; const CAYENNELPP_MAX_CHANNEL = 255; const CAYENNELPP_MIN_SIZE_BYTES = 3; const LPP_DIGITAL_INPUT = 0; const LPP_DIGITAL_OUTPUT = 1; const LPP_ANALOG_INPUT = 2; const LPP_ANALOG_OUTPUT = 3; const LPP_LUMINOSITY = 101; const LPP_PRESENCE = 102; const LPP_TEMPERATURE = 103; const LPP_RELATIVE_HUMIDITY = 104; const LPP_ACCELEROMETER = 113; const LPP_BAROMETRIC_PRESSURE = 115; const LPP_GYROMETER = 134; const LPP_GPS = 136; const LPP_DIGITAL_INPUT_NAME = 'digital_in'; const LPP_DIGITAL_OUTPUT_NAME = 'digital_out'; const LPP_ANALOG_INPUT_NAME = 'analog_in'; const LPP_ANALOG_OUTPUT_NAME = 'analog_out'; const LPP_LUMINOSITY_NAME = 'luminosity'; const LPP_PRESENCE_NAME = 'presence'; const LPP_TEMPERATURE_NAME = 'temperature'; const LPP_RELATIVE_HUMIDITY_NAME = 'relative_humidity'; const LPP_ACCELEROMETER_NAME = 'accelerometer'; const LPP_BAROMETRIC_PRESSURE_NAME = 'barometric_pressure'; const LPP_GYROMETER_NAME = 'gyrometer'; const LPP_GPS_NAME = 'gps'; const LPP_DIGITAL_INPUT_SIZE = 1; // 1 byte const LPP_DIGITAL_OUTPUT_SIZE = 1; // 1 byte const LPP_ANALOG_INPUT_SIZE = 2; // 2 bytes, 0.01 signed const LPP_ANALOG_OUTPUT_SIZE = 2; // 2 bytes, 0.01 signed const LPP_LUMINOSITY_SIZE = 2; // 2 bytes, 1 lux unsigned const LPP_PRESENCE_SIZE = 1; // 1 byte, 1 const LPP_TEMPERATURE_SIZE = 2; // 2 bytes, 0.1°C signed const LPP_RELATIVE_HUMIDITY_SIZE = 1; // 1 byte, 0.5% unsigned const LPP_ACCELEROMETER_SIZE = 6; // 2 bytes per axis, 0.001G const LPP_BAROMETRIC_PRESSURE_SIZE = 2; // 2 bytes 0.1 hPa Unsigned const LPP_GYROMETER_SIZE = 6; // 2 bytes per axis, 0.01 °/s const LPP_GPS_SIZE = 9; // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter function decodeCayenneLpp(payload) { var result = {}; var buffer = Buffer.from(payload, 'hex'); if (buffer && validateCayenneLppSize(buffer)) { var cursor = 0; var value; var propertyName; while (cursor < buffer.length) { var channel = buffer.readUInt8(cursor); if (validateCayenneLppChannel(channel)) { cursor++; var type = buffer[cursor]; cursor++; switch (type) { case LPP_DIGITAL_INPUT: if (cursor + LPP_DIGITAL_INPUT_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer[cursor]; cursor++; propertyName = LPP_DIGITAL_INPUT_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_DIGITAL_OUTPUT: if (cursor + LPP_DIGITAL_OUTPUT_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer[cursor]; cursor++; propertyName = LPP_DIGITAL_OUTPUT_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_ANALOG_INPUT: if (cursor + LPP_ANALOG_INPUT_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer.readInt16BE(cursor) / 100.0; cursor += 2; propertyName = LPP_ANALOG_INPUT_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_ANALOG_OUTPUT: if (cursor + LPP_ANALOG_OUTPUT_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer.readInt16BE(cursor) / 100.0; cursor += 2; propertyName = LPP_ANALOG_OUTPUT_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_LUMINOSITY: if (cursor + LPP_LUMINOSITY_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer.readInt16BE(cursor); cursor += 2; propertyName = LPP_LUMINOSITY_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_PRESENCE: if (cursor + LPP_PRESENCE_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer[cursor]; cursor++; propertyName = LPP_PRESENCE_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_TEMPERATURE: if (cursor + LPP_TEMPERATURE_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer.readInt16BE(cursor) / 10.0; cursor += 2; propertyName = LPP_TEMPERATURE_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_RELATIVE_HUMIDITY: if (cursor + LPP_RELATIVE_HUMIDITY_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer[cursor] / 2.0; cursor++; propertyName = LPP_RELATIVE_HUMIDITY_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_ACCELEROMETER: if (cursor + LPP_ACCELEROMETER_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { var varAccX = buffer.readInt16BE(cursor) / 1000.0; cursor += 2; var varAccY = buffer.readInt16BE(cursor) / 1000.0; cursor += 2; var varAccZ = buffer.readInt16BE(cursor) / 1000.0; cursor += 2; value = { x: varAccX, y: varAccY, z: varAccZ }; propertyName = LPP_ACCELEROMETER_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_BAROMETRIC_PRESSURE: if (cursor + LPP_BAROMETRIC_PRESSURE_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { value = buffer.readInt16BE(cursor) / 10.0; cursor += 2; propertyName = LPP_BAROMETRIC_PRESSURE_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_GYROMETER: if (cursor + LPP_GYROMETER_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { var varX = buffer.readInt16BE(cursor) / 100.0; cursor += 2; var varY = buffer.readInt16BE(cursor) / 100.0; cursor += 2; var varZ = buffer.readInt16BE(cursor) / 100.0; cursor += 2; value = { x: varX, y: varY, z: varZ }; propertyName = LPP_GYROMETER_NAME + '_' + channel.toString(); result[propertyName] = value; } break; case LPP_GPS: if (cursor + LPP_GPS_SIZE > buffer.length) { throw new Error('Invalid CayennLpp message'); } else { var latitude = readInt24BE(buffer, cursor) / 10000.0; cursor += 3; var longitude = readInt24BE(buffer, cursor) / 10000.0; cursor += 3; var altitude = readInt24BE(buffer, cursor) / 100.0; cursor += 3; value = { latitude: latitude, longitude: longitude, altitude: altitude }; propertyName = LPP_GPS_NAME + '_' + channel.toString(); result[propertyName] = value; } break; } } else { throw new Error('Invalid CayennLpp channel'); } } } else { throw new Error('Invalid CayennLpp buffer size'); } return result; } /** * It validates the size of a CayenneLpp message * * @param {<type>} buffer The buffer * @return {boolean} { description_of_the_return_value } */ function validateCayenneLppSize(buffer) { var result = false; if (buffer && buffer.length >= CAYENNELPP_MIN_SIZE_BYTES) { result = true; } return result; } /** * It validates the a CayenneLpp channel * * @param {<type>} buffer The buffer * @return {boolean} { description_of_the_return_value } */ function validateCayenneLppChannel(channel) { var result = true; if (channel > CAYENNELPP_MAX_CHANNEL) { result = false; } return result; } /** * It reads an integer represented using 24 bits * * @param {<type>} buf The buffer * @param {number} offset The offset * @return {<type>} { description_of_the_return_value } */ function readInt24BE(buf, offset) { return buf.readIntBE(offset, 3); } exports.decodeCayenneLpp = decodeCayenneLpp;