DRAGINO - Lgt 92

Sensor

Codec Description

Codec for DRAGINO - Lgt-92 (v1.0.0).

Codec Preview

/* This is an example code for Everynet Parser. ** Everynet send several parameters to TagoIO. The job of this parse is to convert all these parameters into a TagoIO format. ** One of these parameters is the payload of your device. We find it too and apply the appropriate sensor parse. ** ** 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": "everynet_payload", "value": "{ \"params\": { \"payload\": \"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 = [ "device_addr", "port", "duplicate", "network", "packet_hash", "application", "device", "packet_id", ]; /** * 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 Decoder16(bytes, port) { // Decode an uplink message from a buffer // (array) of bytes to an object of fields. var latitude = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) / 1000000; //gps latitude,units: ° var longitude = ((bytes[4] << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]) / 1000000; //gps longitude,units: ° var alarm = bytes[8] & 0x40 ? "TRUE" : "FALSE"; //Alarm status var batV = (((bytes[8] & 0x3f) << 8) | bytes[9]) / 1000; //Battery,units:V var md = ""; //mode of motion var mode = bytes[10] >> 6; if (mode === 0x00) { md = "Disable"; } else if (mode === 0x01) { md = "Move"; } else if (mode === 0x02) { md = "Collide"; } else if (mode === 0x03) { md = "Custom"; } var led_updown = bytes[10] & 0x20 ? "ON" : "OFF"; //LED status for position,uplink and downlink var Firmware = 160 + (bytes[10] & 0x1f); // Firmware version; 5 bits var roll = ((bytes[11] << 8) | bytes[12]) / 100; //roll,units: ° var pitch = ((bytes[13] << 8) | bytes[14]) / 100; //pitch,units: ° var hdop = 0; if (bytes[15] > 0) { hdop = bytes[15] / 100; //hdop,units: ° } else { hdop = bytes[15]; } var altitude = ((bytes[16] << 8) | bytes[17]) / 100; //Altitude,units: ° var decoded = { lat: latitude, lng: longitude, roll: roll, pitch: pitch, batv: batV, alarm_status: alarm, md: md, lon: led_updown, fw: Firmware, hdop: hdop, altitude: altitude, }; if (decoded.lat && decoded.lng) { decoded.location = { value: `${decoded.lat},${decoded.lng}`, location: { lat: decoded.lat, lng: decoded.lng }, }; delete decoded.lat; delete decoded.lng; } return decoded; } function Decoder15(bytes, port) { const data = { // GPS coordinates; signed 32 bits integer, MSB; unit: ° // When power is low (<2.84v), GPS won’t be able to get location // info and GPS feature will be disabled and the location field // will be filled with 0x0FFFFFFF, 0x0FFFFFFF. lat: ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) / 1000000, lng: ((bytes[4] << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]) / 1000000, // Alarm status: boolean alarm_status: (bytes[8] & 0x40) > 0, // Battery; 14 bits; unit: V batv: (((bytes[8] & 0x3f) << 8) | bytes[9]) / 1000, // Motion detection mode; 2 bits md: { 0: "Disable", 1: "Move", 2: "Collide", 3: "Custom", }[bytes[10] >> 6], // LED status for position, uplink and downlink; 1 bit lon: bytes[10] & 0x20 ? "ON" : "OFF", // Firmware version; 5 bits fw: 150 + (bytes[10] & 0x1f), // Roll; signed 16 bits integer, MSB; unit: ° // Sign-extend to 32 bits to support negative values: shift 16 bytes // too far to the left, followed by sign-propagating right shift roll: (((bytes[11] << 24) >> 16) | bytes[12]) / 100, // Pitch: signed 16 bits integer, MSB, unit: ° pitch: (((bytes[13] << 24) >> 16) | bytes[14]) / 100, }; data.location = { value: `${data.lat},${data.lng}`, location: { lng: data.lng, lat: data.lat }, }; delete data.lng; delete data.lat; return data; } function Decoder14(bytes, port) { // Decode an uplink message from a buffer // (array) of bytes to an object of fields. const alarm = !!(bytes[6] & 0x40); // Alarm status value = ((bytes[6] & 0x3f) << 8) | bytes[7]; const battery = value / 1000; // Battery,units:Volts value = (bytes[8] << 8) | bytes[9]; if (bytes[8] & 0x80) { value |= 0xffff0000; } const roll = value / 100; // roll,units: ° value = (bytes[10] << 8) | bytes[11]; if (bytes[10] & 0x80) { value |= 0xffff0000; } const pitch = value / 100; // pitch,units: ° const json = { roll, pitch, battery, alarm, }; var value = (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]; if (bytes[0] & 0x80) { value |= 0xffffff000000; } let value2 = (bytes[3] << 16) | (bytes[4] << 8) | bytes[5]; if (bytes[3] & 0x80) { value2 |= 0xffffff000000; } if (value == 0x0fffff && value2 == 0x0fffff) { // gps disabled (low battery) } else if (value === 0 && value2 === 0) { // gps no position yet } else { const lat = value / 10000; // gps latitude,units: ° const lng = value2 / 10000; // gps longitude,units: ° json.location = { value: `${lat},${lng}`, location: { lat, lng } }; } return json; } //const device = { params: [{ key: "firmware_version", value: "1.6" }] }; // let payload = [{ variable: "payload", value: "02863D68FAC29BAF4B456004D2FB2E" }]; // { // variable: 'time', // value: 1571874770.422976, // serie: 1571874770524, // }, // { // variable: 'payload', // value: '0571e6f3f8bc0fe31672f934', // serie: 1571874770524, // }, // { // variable: 'port', // value: 2, // serie: 1571874770524, // }, // { // variable: 'duplicate', // value: false, // serie: 1571874770524, // }, // { // variable: 'counter_up', // value: 38, // serie: 1571874770524, // }, // { // variable: 'rx_time', // value: 1571874770.3568993, // serie: 1571874770524, // }, // { // variable: 'encrypted_payload', // value: 'c12oeBn03DxbfqcD', // serie: 1571874770524, // }, // ]; // Check if what is being stored is the ttn_payload. // Payload is an environment variable. Is where what is being inserted to your device comes in. //let payload = [{ variable: "payload", value: "AyF7+ADL+28O5mQ=" }]; // Payload always is an array of objects. [ { variable, value...}, {variable, value...} ...] const payload_raw = payload.find( (x) => x.variable === "payload" || x.variable === "payload_raw" || x.variable === "data" || x.variable === "frm_payload" ); if (payload_raw) { // Get a unique serie for the incoming data. const serie = payload_raw.serie || new Date().getTime(); let vars_to_tago = []; // Parse the payload from your sensor to function parsePayload try { const firmware_version = device.params.find( (param) => param.key === "firmware_version" ); let decoded = {}; if (firmware_version.value === "1.4") { decoded = Decoder14(Buffer.from(payload_raw.value, "hex")); } else if (firmware_version.value === "1.5") { decoded = Decoder15(Buffer.from(payload_raw.value, "hex")); } else { decoded = Decoder16(Buffer.from(payload_raw.value, "hex")); } vars_to_tago = vars_to_tago.concat(toTagoFormat(decoded, serie)); } catch (e) { // Catch any error in the parse code and send to parse_error variable. vars_to_tago = vars_to_tago.concat({ variable: "parse_error", value: e.message || e, }); } if (payload.find((x) => x.variable === "frm_payload")) { payload = payload.filter((x) => { if ( (x.location && x.value.includes("undefined")) || x.value === undefined || x.value === null ) { return false; } return true; }); const keys = []; for (const key in payload) { keys.push(payload[key].variable); } vars_to_tago = vars_to_tago.filter((y) => { if ( keys.includes(y.variable) || y.value === undefined || y.value === null ) { return false; } return true; }); } payload = payload.concat(vars_to_tago); } payload = payload.filter((item) => { if (item.variable === "lat") { if (item.value === 0) { console.error("Variable lat is ignored"); return false; } } if (item.variable === "lng") { if (item.value === 0) { console.error("Variable lng is ignored"); return false; } } return true; }); payload = payload.filter((item) => { if (item.location) { if (item.location.lat === 0 && item.location.lng === 0) { console.error("Variable Location is ignored"); return false; } } return true; }); 

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