ELSYS - Ers Lite

Sensor

Codec Description

Codec for ELSYS - Ers-Lite (v1.0.0).

Codec Preview

const TYPE_TEMP = 0x01; // temp 2 bytes -3276.8°C -->3276.7°C const TYPE_RH = 0x02; // Humidity 1 byte 0-100% const TYPE_ACC = 0x03; // acceleration 3 bytes X,Y,Z -128 --> 127 +/-63=1G const TYPE_LIGHT = 0x04; // Light 2 bytes 0-->65535 Lux const TYPE_MOTION = 0x05; // No of motion 1 byte 0-255 const TYPE_CO2 = 0x06; // Co2 2 bytes 0-65535 ppm const TYPE_VDD = 0x07; // VDD 2byte 0-65535mV const TYPE_ANALOG1 = 0x08; // VDD 2byte 0-65535mV const TYPE_GPS = 0x09; // 3bytes lat 3bytes long binary const TYPE_PULSE1 = 0x0A; // 2bytes relative pulse count const TYPE_PULSE1_ABS = 0x0B; // 4bytes no 0->0xFFFFFFFF const TYPE_EXT_TEMP1 = 0x0C; // 2bytes -3276.5C-->3276.5C const TYPE_EXT_DIGITAL = 0x0D; // 1bytes value 1 or 0 const TYPE_EXT_DISTANCE = 0x0E; // 2bytes distance in mm const TYPE_ACC_MOTION = 0x0F; // 1byte number of vibration/motion const TYPE_IR_TEMP = 0x10; // 2bytes internal temp 2bytes external temp -3276.5C-->3276.5C const TYPE_OCCUPANCY = 0x11; // 1byte data const TYPE_WATERLEAK = 0x12; // 1byte data 0-255 const TYPE_GRIDEYE = 0x13; // 65byte temperature data 1byte ref+64byte external temp const TYPE_PRESSURE = 0x14; // 4byte pressure data (hPa) const TYPE_SOUND = 0x15; // 2byte sound data (peak/avg) const TYPE_PULSE2 = 0x16; // 2bytes 0-->0xFFFF const TYPE_PULSE2_ABS = 0x17; // 4bytes no 0->0xFFFFFFFF const TYPE_ANALOG2 = 0x18; // 2bytes voltage in mV const TYPE_EXT_TEMP2 = 0x19; // 2bytes -3276.5C-->3276.5C const TYPE_EXT_DIGITAL2 = 0x1A; // 1bytes value 1 or 0 const TYPE_EXT_ANALOG_UV = 0x1B; // 4 bytes signed int (uV) const TYPE_DEBUG = 0x3D; // 4bytes debug function toTagoFormat(object_item, group, prefix = '', location_var) { 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, group: object_item[key].group || group, metadata: object_item[key].metadata, location: object_item[key].location || location_var, unit: object_item[key].unit, }); } else { result.push({ variable: `${prefix}${key}`, value: object_item[key], location: location_var, group, }); } } return result; } function bin16dec(bin) { let num = bin & 0xFFFF; if (0x8000 & num) num = -(0x010000 - num); return num; } function bin8dec(bin) { let num = bin & 0xFF; if (0x80 & num) num = -(0x0100 - num); return num; } function hexToBytes(hex) { for (var bytes = [], c = 0; c < hex.length; c += 2) bytes.push(parseInt(hex.substr(c, 2), 16)); return bytes; } function DecodeElsysPayload(data) { const obj = new Object(); for (i = 0; i < data.length; i++) { // console.log(data[i]); switch (data[i]) { case TYPE_TEMP: // Temperature var temp = (data[i + 1] << 8) | (data[i + 2]); temp = bin16dec(temp); obj.temperature = { value: temp / 10, unit: '°C' }; i += 2; break; case TYPE_RH: // Humidity var rh = (data[i + 1]); obj.humidity = { value: rh, unit: '%' }; i += 1; break; case TYPE_ACC: // Acceleration obj.x = bin8dec(data[i + 1]); obj.y = bin8dec(data[i + 2]); obj.z = bin8dec(data[i + 3]); i += 3; break; case TYPE_LIGHT: // Light obj.light = { value: (data[i + 1] << 8) | (data[i + 2]), unit: 'Lux' }; i += 2; break; case TYPE_MOTION: // Motion sensor(PIR) obj.motion = (data[i + 1]); i += 1; break; case TYPE_CO2: // CO2 obj.co2 = { value: (data[i + 1] << 8) | (data[i + 2]), unit: 'ppm' }; i += 2; break; case TYPE_VDD: // Battery level obj.vdd = { value: (data[i + 1] << 8) | (data[i + 2]), unit: 'mV' }; i += 2; break; case TYPE_ANALOG1: // Analog input 1 obj.analog1 = { value: (data[i + 1] << 8) | (data[i + 2]), unit: 'mV' }; i += 2; break; case TYPE_GPS: // gps const lat = (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3]); const lng = (data[i + 4] << 16) | (data[i + 5] << 8) | (data[i + 6]); obj.location = { value: `${lat},${lng}`, location: { lat, lng } }; i += 6; break; case TYPE_PULSE1: // Pulse input 1 obj.pulse1 = (data[i + 1] << 8) | (data[i + 2]); i += 2; break; case TYPE_PULSE1_ABS: // Pulse input 1 absolute value var pulseAbs = (data[i + 1] << 24) | (data[i + 2] << 16) | (data[i + 3] << 8) | (data[i + 4]); obj.pulseAbs = pulseAbs; i += 4; break; case TYPE_EXT_TEMP1: // External temp var temp = (data[i + 1] << 8) | (data[i + 2]); temp = bin16dec(temp); obj.externalTemperature = { value: temp / 10, unit: '°C' }; i += 2; break; case TYPE_EXT_DIGITAL: // Digital input obj.digital = (data[i + 1]); i += 1; break; case TYPE_EXT_DISTANCE: // Distance sensor input obj.distance = { value: (data[i + 1] << 8) | (data[i + 2]), unit: 'mm' }; i += 2; break; case TYPE_ACC_MOTION: // Acc motion obj.accMotion = (data[i + 1]); i += 1; break; case TYPE_IR_TEMP: // IR temperature var iTemp = (data[i + 1] << 8) | (data[i + 2]); iTemp = bin16dec(iTemp); var eTemp = (data[i + 3] << 8) | (data[i + 4]); eTemp = bin16dec(eTemp); obj.irInternalTemperature = { value: iTemp / 10, unit: '°C' }; obj.irExternalTemperature = { value: eTemp / 10, unit: '°C' }; i += 4; break; case TYPE_OCCUPANCY: // Body occupancy obj.occupancy = (data[i + 1]); i += 1; break; case TYPE_WATERLEAK: // Water leak obj.waterleak = (data[i + 1]); i += 1; break; case TYPE_GRIDEYE: // Grideye data var ref = data[i + 1]; i++; obj.grideye = []; for (let j = 0; j < 64; j++) { obj.grideye[j] = ref + (data[1 + i + j] / 10.0); } i += 64; break; case TYPE_PRESSURE: // External Pressure var temp = (data[i + 1] << 24) | (data[i + 2] << 16) | (data[i + 3] << 8) | (data[i + 4]); obj.pressure = { value: temp / 1000, unit: 'hPa' }; i += 4; break; case TYPE_SOUND: // Sound obj.soundPeak = data[i + 1]; obj.soundAvg = data[i + 2]; i += 2; break; case TYPE_PULSE2: // Pulse 2 obj.pulse2 = (data[i + 1] << 8) | (data[i + 2]); i += 2; break; case TYPE_PULSE2_ABS: // Pulse input 2 absolute value obj.pulseAbs2 = (data[i + 1] << 24) | (data[i + 2] << 16) | (data[i + 3] << 8) | (data[i + 4]); i += 4; break; case TYPE_ANALOG2: // Analog input 2 obj.analog2 = { value: (data[i + 1] << 8) | (data[i + 2]), unit: 'mV' }; i += 2; break; case TYPE_EXT_TEMP2: // External temp 2 var temp = (data[i + 1] << 8) | (data[i + 2]); temp = bin16dec(temp); obj.externalTemperature2 = { value: temp / 10, unit: '°C' }; i += 2; break; case TYPE_EXT_DIGITAL2: // Digital input 2 obj.digital2 = (data[i + 1]); i += 1; break; case TYPE_EXT_ANALOG_UV: // Load cell analog uV obj.analogUv = { value: (data[i + 1] << 24) | (data[i + 2] << 16) | (data[i + 3] << 8) | (data[i + 4]), unit: 'uV' }; i += 4; break; default: // somthing is wrong with data i = data.length; break; } } return obj; } function Decoder(bytes, port) { return DecodeElsysPayload(bytes); } // payload = [{ variable: 'payload', value: '0100e202290400270506060308070d62', group: '122a' }]; const data = payload.find(x => x.variable === 'data' || x.variable === 'payload'); if (data) { const group = String(data.group || Date.now()); const vars_to_tago = Decoder(Buffer.from(data.value, 'hex')); payload = [...payload, ...toTagoFormat(vars_to_tago, group, '', vars_to_tago.location)]; // payload = payload.filter(x => !ignore_vars.includes(x.variable)); } 

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.

Community Feedback