8 years, 3 months ago.

Parsing MTDOT-EVB Data in Node-Red

We are demoing a MTCDT-H5 and are attempting to Parse MTDOT-EVB data in Node-Red to a msg.payload.

Has anyone done this?

Question relating to:

Demonstration program for Multitech System MTDOT-EVB an evaluation board for the mDot LoRa module MTDOT, MTDOT-EVB

2 Answers

8 years, 3 months ago.

Here is a copy of code I use in a function node to parse data from the EVB using the data structure defined in the EVB code. Just copy this code to a function node in Node Red and make sure your lora node is set to binary mode. /media/uploads/falingtrea/evbparser.txt

Thanks so much for posting a reply to this question! My apology for getting back to you so late. (We're doing a "whole lot of stuff.") Cheers!

posted by Patrick Phillips 19 Feb 2016
8 years, 3 months ago.

Patrick, Here's a complete Node Red flow with the following structure:

LoRa Input Node -> Function Node -> Debug Node

Note that the LoRa Input Node must have the Data Type field set to "Bytes" and the Debug Node should have the Output field set to "complete msg object."

[{"id":"cfde92a0.3e1d68","type":"lora in","name":"","datatype":"bytes","x":196,"y":222,"z":"d10bbe5.35418c","wires":[["6683447f.753ae4"]]},{"id":"6683447f.753ae4","type":"function","name":"","func":"var data_type = {\n\tnone : 0x00,\n\tled1 : 0x01,\n\tled2 : 0x02,\n\tlux_max : 0x03,\n\tlux_min : 0x04,\n\tlux_curr : 0x05,\n\tbaro_max : 0x06,\n\tbaro_min : 0x07,\n\tbaro_curr : 0x08,\n\ttemp_max : 0x09,\n\ttemp__min : 0x0A,\n\ttemp_curr : 0x0B,\n\taccel_max : 0x0C,\n\taccel_min : 0x0D,\n\taccel_curr : 0x0E,\n\tconfiguration : 0x0F,\n\tgpio_in : 0x10,\n\tgpio_out : 0x11,\n\tcurrent_max : 0x12,\n\tcurrent_min : 0x13,\n\tcurrent_curr : 0x14,\n\tgps_latitude : 0x15,\n\tgps_longitude : 0x16,\n\tgps_time : 0x17,\n\tgps_date : 0x18,\n\tgps_lock : 0x19,\n\tqos_up : 0x1A,\n\tqos_dwn : 0x1B,\n\trf_out : 0x1C,\n\tdata_mark : 0x1D,\n};\n\nvar data_struc = {\n\tdata_valid : 0,\n\tblock_start :0,\n\ttemperature : 0,\n\tx_pos : 0,\n\ty_pos : 0,\n\tz_pos : 0,\n\tbaro_pressure : 0,\n\tlux : 0,\n\tpkt_timer :0,\n\trf_pwr : 0,\n\tsf_val : 0,\n\tgateways : 0,\n\tmargin_up : 0,\n\trssi_dwn : 0,\n\tsnr_dwn :0 ,\n\tlat_deg : 0 ,\n\tlat_min : 0,\n\tlong_deg : 0,\n\tlong_min : 0,\n\tnum_sats : 0 ,\n\tgps_status : 0,\n};\n\ncontext.global.data_out = context.global.data_out || data_struc;\nvar pData = context.global.data_out;\n\nvar msg_pntr = 0;\nvar temp = 0;\n\nwhile (msg_pntr < msg.payload.length){\n\tswitch (msg.payload[msg_pntr]){\n\tcase data_type.lux_max:\n\tcase data_type.lux_min:\n\tcase data_type.lux_curr:\n\t\tpData.lux = msg.payload[++msg_pntr] << 8 \n\t\tpData.lux |= msg.payload[++msg_pntr];\n\t\tpData.lux = pData.lux * 0.24;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.baro_max:\n\tcase data_type.baro_min:\n\tcase data_type.baro_curr:\n\t\tpData.baro_pressure = msg.payload[++msg_pntr]<<16;\n\t\tpData.baro_pressure |= msg.payload[++msg_pntr]<<8;\n\t\tpData.baro_pressure |= msg.payload[++msg_pntr];\n\t\tpData.baro_pressure = pData.baro_pressure * 0.25;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.accel_max:\n\tcase data_type.accel_min:\n\tcase data_type.accel_curr:\n\t\tpData.x_pos = ((msg.payload[++msg_pntr] << 24) >> 24) * 0.0625;\n\t\tpData.y_pos = ((msg.payload[++msg_pntr] << 24) >> 24) * 0.0625;\n\t\tpData.z_pos = ((msg.payload[++msg_pntr] << 24) >> 24) * 0.0625;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.temp_min:\n\tcase data_type.temp_max:\n\tcase data_type.temp_curr:\n\t\tpData.temperature = msg.payload[++msg_pntr] << 24;\n\t\tpData.temperature |= msg.payload[++msg_pntr] << 16;\n\t\tpData.temperature = (pData.temperature >> 16) * .0625;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.configuration:\n\t\tpData.pkt_timer = msg.payload[++msg_pntr];\n\t\tmsg_pntr++\n\t\tbreak;\n\tcase data_type.current_max:\n\tcase data_type.current_min:\n\tcase data_type.current_curr:\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.gps_latitude:\n\t\tpData.lat_deg = (msg.payload[++msg_pntr] << 24) >> 24;\n\t\tpData.lat_min = msg.payload[++msg_pntr];\n\t\ttemp = msg.payload[++msg_pntr] << 8 \n\t\ttemp |= msg.payload[++msg_pntr];\n\t\tpData.lat_min = pData.lat_min + (temp * 0.0001);\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.gps_longitude:\n\t\tpData.long_deg = (msg.payload[++msg_pntr] << 24);\n\t\tpData.long_deg |= (msg.payload[++msg_pntr] << 16);\n\t\tpData.long_deg = pData.long_deg >> 16;\n\t\tpData.long_min = msg.payload[++msg_pntr];\n\t\ttemp = msg.payload[++msg_pntr] << 8 \n\t\ttemp |= msg.payload[++msg_pntr];\n\t\tpData.long_min = pData.long_min + (temp * 0.0001);\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.gps_time:\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.gps_date:\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.gps_lock:\n\t\tmsg_pntr++;\n\t\tpData.gps_status = msg.payload[msg_pntr] & 0x0F;\n\t\tpData.num_sats = msg.payload[msg_pntr++] >> 4;\n\t\tbreak;\n\tcase data_type.qos_up:\n\t\tpData.gateways = msg.payload[++msg_pntr] << 24;\n\t\tpData.gateways |= msg.payload[++msg_pntr] << 16;\n\t\tpData.gateways = pData.gateways >> 16;\n\t\tpData.margin_up = (msg.payload[++msg_pntr] << 24) >> 24;\n\t\tpData.rf_pwr = (msg.payload[++msg_pntr] << 24) >> 24;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.qos_dwn:\n\t\tpData.rssi_dwn = msg.payload[++msg_pntr] << 24;\n\t\tpData.rssi_dwn |= msg.payload[++msg_pntr] << 16;\n\t\tpData.rssi_dwn = pData.rssi_dwn >> 16;\n\t\tpData.snr_dwn = ((msg.payload[++msg_pntr] << 24) >> 24);\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.rf_out:\n\t\tpData.rf_pwr = (msg.payload[++msg_pntr] << 24) >> 24;\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.data_mark:\n\t\tif (msg_pntr == 0) {\n\t\t\tpData = data_struc;\n\t\t\tpData.block_start = 1;\n\t\t\tmsg_pntr++;\n\t\t}\n\t\telse if (msg_pntr == (msg.payload.length - 1) && (pData.block_start === 1)) {\n\t\t\t\tpData.data_valid = 1;\n\t\t\t\tmsg_pntr++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpData = data_struc;\n\t\t\t\tmsg_pntr = msg.payload.length;\n\t\t\t\t}\n\t\tbreak;\n\tdefault:\n\t\tpData = data_struc;\n\t\tmsg_pntr = msg.payload.length;\n\t}\n}\n\npData.sf_val = parseInt(msg.datr.replace(\"SF\",\"  \"),10);\n\ncontext.global.data_out = pData;\n\nreturn pData;","outputs":1,"x":429,"y":220,"z":"d10bbe5.35418c","wires":[["3c18f05c.5fa09"]]},{"id":"3c18f05c.5fa09","type":"debug","name":"","active":true,"console":"false","complete":"true","x":700,"y":220,"z":"d10bbe5.35418c","wires":[]}]

Hope this helps.

-Mike

Thank you, Mike! We will take a look at this! My apology for the very late response. We're developing so much stuff, and I just plain missed this! — Patrick

posted by Patrick Phillips 19 Feb 2016