[{"id":"a89aedba.72c86","type":"websocket-listener","path":"/ws/location","wholemsg":"false"},{"id":"f2b8985e.2e1b38","type":"lora in","name":"lora","datatype":"bytes","x":139.79165649414062,"y":167.77777099609375,"z":"815521a7.8cc2f","wires":[["61ed00c5.a4e61"]]},{"id":"61ed00c5.a4e61","type":"function","name":"lora packet","func":"// track LoRa stats (number of mDots, total pkts, and total pkts for each mDot)\n// return msg, LoRa Stats\n\n// add data structures if they don't exist\ncontext.global.pkts = context.global.pkts || {};\ncontext.global.pkts[msg.eui] = context.global.pkts[msg.eui] || {};\ncontext.global.pkts[msg.eui].pktCount = context.global.pkts[msg.eui].pktCount || 0;\ncontext.global.lastEUI = msg.eui;\n\n//New in AEP 1.20 link status request. It has no payload.\n// (typeof msg.payload === 'undefined' || !msg.payload)\nif (msg.payload == null) {\n //console.log(\"A Null payload\");\n return [null, null];\n}\n\n//Count the packets\ncontext.global.pkts[msg.eui].pktCount = context.global.pkts[msg.eui].pktCount + 1;\n\nvar keys = Object.keys(context.global.pkts);\nvar totalPkts = 0\nkeys.forEach(function(element, index, array) {\n\ttotalPkts = totalPkts + context.global.pkts[element].pktCount;\n});\nvar payLoad = \"nMdot Cards \" + keys.length + \" Total Pkts(\" + totalPkts + \")\\n\";\nvar newMsg = JSON.parse(JSON.stringify(msg));\nnewMsg.payload = payLoad\n// raw msg output and modified msg on output3\nreturn [msg,newMsg];","outputs":"2","noerr":0,"x":300.5376434326172,"y":165.0317144393921,"z":"815521a7.8cc2f","wires":[["3a75a58d.11c20a","9b08a3fc.44a32"],["9bb5e4cd.52df58"]]},{"id":"9bb5e4cd.52df58","type":"debug","name":"mDotDeviceStatus","active":false,"console":"false","complete":"payload","x":530.8233489990234,"y":184.9920539855957,"z":"815521a7.8cc2f","wires":[]},{"id":"1031892b.8f06d7","type":"comment","name":"ReadMe","info":"MTDOT-BOX Send Receive\n\nThis flow can be used to gather information reported by an MTDOT-BOX. \nReceived packets are written to a csv file on the AEP, and packets with valid \nGPS information are sent to a Google Map page @ :1880/map. SMS Messages can be used to \nadd comments to the data captured and saved in the csv file. There are comment nodes\nplaced in the flow to help explain the funtionality of groups of nodes.\n\nThe Lora expansion card must be configured for the network.\nSetup | LoRa Network Server\n\nConduit key fields\n- Frequency Sub-Band\n- Network Name\n- Network Passphrase\n\nTo Use mDot-EVB defaults on the AEP Network Settings:\n- Name: mDot-EVB:MultiTtech \n- Passphrase: mDot-EVB:MultiTech\n- Subband: <1-7> mDot-EVB:1\n- Note: Sending survey data over the LoRa network is off by default (AT+DATA? +DATA 0).\n\nTo program the mDot-EVB for your AEP LoRa network:\n- The EVB is connected to a developer board via ribbon cable.\n - It is in configuration mode via the EVB Menu.\n - a tty is connected at 115200 8N1 (no flow control)\n- AT+FSB=<1> (use frequencySubBand value for your Conduit)\n- AT+NI=1, (value = Network Name for your Conduit)\n- AT+NK=1, (value = Network Passphrase for your Conduit)\n- AT+DATA=1 (tells the EVB to send survey data over the LoRa network.\n\nTo program an mDot for your AEP LoRa network:\n- AT+FSB=<1> (use frequencySubBand value for your Conduit)\n- AT+NI=1, (value = Network Name for your Conduit)\n- AT+NK=1, (value = Network Passphrase for your Conduit)\n- AT+ENC=1 (enable encryption)\n- AT+NJM=1 (enable OTA Join mode)\n- Save settings and restart\n-- AT&W (save settings)\n-- ATZ (reload settings)\n- AT+ACK=2 (optional force Conduit to Acknowledge received packets)\n- AT+JOIN (join the network)\n- AT+NLC (network status)\n- AT+SEND (will return a packet for the mDot and OK)\n- AT+SEND=packetData (send the payload to the Conduit, and return a packet if one is available).\n","x":130.64879608154297,"y":83.4761734008789,"z":"815521a7.8cc2f","wires":[]},{"id":"4b2749d3.18dc38","type":"comment","name":"GPS NEMA","info":"$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F\n- udp port \n- Example serial output (account/device/NEMA sentence)\n - //$GPRMC,181528.008,A,4505.9702,N,09311.7421,W,000.0,186.9,300414,,,A*75\n\nFields: $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh\n- UTC of position fix\n- Data status (V=navigation receiver warning)\n- Latitude of fix\n- N or S\n- Longitude of fix\n- E or W\n- Speed over ground in knots\n- Track made good in degrees True\n- UT date\n- Magnetic variation degrees (Easterly var. subtracts from true course)\n- E or W\n- Checksum\n","x":157.47023010253906,"y":342.9563102722168,"z":"815521a7.8cc2f","wires":[]},{"id":"d0b817fb.5a39d8","type":"http in","name":"","url":"/evbMonitor","method":"get","x":174.0297088623047,"y":669.4443473815918,"z":"815521a7.8cc2f","wires":[["3a135a46.ea4826"]]},{"id":"738e1045.5b16e","type":"http response","name":"Return page","x":819.124870300293,"y":636.2301826477051,"z":"815521a7.8cc2f","wires":[]},{"id":"a892e9fc.172408","type":"function","name":"Package data","func":"//Currently this is the data(global) we have collected, not the msg.\nmsg.topic = \"data\";\n//msg.payload = \"temp \" + msg.temperature;\nreturn msg;","outputs":1,"noerr":0,"x":168.88684844970703,"y":621.5872144699097,"z":"815521a7.8cc2f","wires":[["60d26d8f.1892b4","3a135a46.ea4826"]]},{"id":"5430ca32.d0c8e4","type":"comment","name":"EVB to Web Page (localhost:1880/evbMonitor)","info":"- :1880/evbMonitor\n- evbData is displayed on the evbMonitor page. The last non-zero value is saved \n- on this web page. ","x":268.5772933959961,"y":576.6190376281738,"z":"815521a7.8cc2f","wires":[]},{"id":"a93cfe98.2af25","type":"template","name":"evb Monitor Template","field":"payload","template":"\n
\n

EVB Packet Stats:

\n\n

ledRedGreen {{msg.ledRedGreen}} ledBackBlue {{msg.ledBackBlue}}

\n

lux {{msg.luxCurr}} Barometer {{msg.baroCurr}} kPa Temp {{msg.tempCurr}}C

\n

AcellCurr X:{{msg.accelCurrX}} Y:{{msg.accelCurrY}} Z:{{msg.accelCurrZ}}

\n\n

GPSLock {{msg.gpsLockStatus}} GPSSatellites {{msg.gpsNSatellites}}

\n

GPSLattitude {{msg.gpsLatDegree}} {{msg.gpsLatMin}} {{msg.gpsLatSec}} {{msg.gpsLatChar}}

\n

GPSLongitude {{msg.gpsLongDegree}} {{msg.gpsLongMin}} {{msg.gpsLongSec}} {{msg.gpsLongChar}}

\n

GPSDate {{msg.gpsDate}} GPSTime {{msg.gpsTime}}

\n\n\n

Margin: {{msg.margin}} Gateways: {{msg.nGateways}}

\n

Rssi: {{msg.qosDownlinkRssi}} snr: {{msg.qosDownlinkSnr}}

\n

TxPower: {{msg.rfPower}}

\n
","x":619.6489181518555,"y":637.9206123352051,"z":"815521a7.8cc2f","wires":[["738e1045.5b16e"]]},{"id":"f734d6c2.461488","type":"debug","name":"parseEVBData","active":true,"console":"false","complete":"true","x":657.3630599975586,"y":241.14680099487305,"z":"815521a7.8cc2f","wires":[]},{"id":"ff0e3e89.38ec5","type":"comment","name":"Parse EVB payload","info":"- parse the LoRa packet. msg.payload is evbData\nthe current payload is added to context.global.evbData, and passed on\nto the evbMonitor web page, csv output node, and the Google map data node.\n- if context.global.evbData has a StartMsg and StopMsg sequence, the msg is considered complete,\nand the message is passed out the second return. This return is used to handle packets that need to \nbe sent in multiple messages due to Spreading Factor data limits.\n","x":177.6131134033203,"y":250.8491916656494,"z":"815521a7.8cc2f","wires":[]},{"id":"a761af00.79e22","type":"comment","name":"node-RED log","info":"Tail messages sent to the node-RED log","x":142.61310577392578,"y":1086.4443912506104,"z":"815521a7.8cc2f","wires":[]},{"id":"677cb8a6.7b0f88","type":"comment","name":"Global Settings","info":"AEP Network Settings\n- Name: evbDefault:MultiTtech \n- Passphrase: evbDefault:MultiTech\n- Subband: <1-7> evbDefault:1\n\nData Web Monitor\n- Web Page: :1880/evbMonitor\n\nGoogle Map\n- Web Page: :1880/map\n\nTail Node (/var/log/app/node-red.log)\n- dumps messages sent to the Node-Red log to the debug tab.\n\ncsv Data\n- write all evb packet data to a csv file.\n- name: /media/card/evbCsv (if there is a media card present)\n- name: /var/evbCsv","x":283.2321548461914,"y":85.6111011505127,"z":"815521a7.8cc2f","wires":[]},{"id":"40b429bc.72e128","type":"tail","name":"","split":true,"filename":"/var/log/app/node-red.log","x":340.96376037597656,"y":1087.4854679107666,"z":"815521a7.8cc2f","wires":[["7d457f51.25317"]]},{"id":"7d457f51.25317","type":"debug","name":"node-REDLog","active":true,"console":"false","complete":"payload","x":597.1758041381836,"y":1091.0873832702637,"z":"815521a7.8cc2f","wires":[]},{"id":"5c5293a7.98b6dc","type":"debug","name":"Google Map Data","active":true,"console":"false","complete":"payload","x":829.6128158569336,"y":455.1110649108887,"z":"815521a7.8cc2f","wires":[]},{"id":"7a799458.09492c","type":"websocket out","name":"","server":"a89aedba.72c86","x":887.4106750488281,"y":385.53968811035156,"z":"815521a7.8cc2f","wires":[]},{"id":"4b18aea2.d4c62","type":"http response","name":"Return page","x":581.0772933959961,"y":455.1111259460449,"z":"815521a7.8cc2f","wires":[]},{"id":"f75bb137.7668a","type":"http in","name":"","url":"/map","method":"get","x":171.8392791748047,"y":453.8730278015137,"z":"815521a7.8cc2f","wires":[["e960ac6b.c3ed7"]]},{"id":"60d26d8f.1892b4","type":"debug","name":"packageDataMsg","active":false,"console":"false","complete":"true","x":611.3153305053711,"y":580.5158500671387,"z":"815521a7.8cc2f","wires":[]},{"id":"150efa2e.684886","type":"debug","name":"gatheredGPSMessage (if valid)","active":true,"console":"false","complete":"true","x":707.3630828857422,"y":287.4920425415039,"z":"815521a7.8cc2f","wires":[]},{"id":"e960ac6b.c3ed7","type":"template","name":"EVB Map Template","field":"payload","format":"handlebars","template":"\n\n \n \n \n \n mDot Box/EVB Data\n \n \n \n
\n \n \n \n
\n
\n \n \n \n","x":369.3154525756836,"y":454.8729667663574,"z":"815521a7.8cc2f","wires":[["4b18aea2.d4c62"]]},{"id":"f1a8bb3a.b94cf8","type":"comment","name":"EVB to Google Map (localhost:1880/map)","info":"- :1880/map\n- plot EVB data points on a google map.\n- Only EVB data with valid GPS data is sent on to the map.\n","x":407.60115814208984,"y":340.8730278015137,"z":"815521a7.8cc2f","wires":[]},{"id":"3a75a58d.11c20a","type":"debug","name":"debug LoRa Packet","active":true,"console":"false","complete":"true","x":528.1726531982422,"y":137.01586151123047,"z":"815521a7.8cc2f","wires":[]},{"id":"dcb95c2d.c4d96","type":"function","name":"Google Map Data","func":"//Google Maps is DD format\n// Degrees + ((Minutes*60) + Seconds)/3600)\nif (msg.sendEvbArray) {\n console.log(\"Send Saved data\");\n return msg;\n}\nvar lattitude = msg.gpsLatDegree + (((msg.gpsLatMin * 60) + msg.gpsLatSec) / 3600);\nif (msg.gpsLatChar == \"S\") {\n lattitude = lattitude * -1;\n} \nvar longitude = msg.gpsLongDegree + (((msg.gpsLongMin * 60) + msg.gpsLongSec) / 3600);\nif (msg.gpsLongChar == \"W\") { \n longitude = longitude * -1;\n} \n\nif ((longitude === 0 || longitude === null) && (lattitude === 0 || lattitude === null)) {\n //console.log(\"No GPS Data\");\n if (context.global.sendOnlyValidData === true) {\n console.log(\"No GPS Data Don't send to Google Map\");\n return null;\n }\n}\n//If we pass in an Array\n//msg.payload = [{ lat:lattitude, lng:longitude }];\nvar evbdata = { \n lat:lattitude, lng:longitude,\n nGateways:msg.nGateways,\n margin:msg.margin,\n dnrssi:msg.qosDownlinkRssi,\n dnsnr:msg.qosDownlinkSnr,\n rfPower:msg.rfPower,\n datr:msg.datr,\n freq:msg.freq,\n};\n\n//console.log(\"GMD Session \" + JSON.stringify(msg._session));\nif (context.global.gMapReady === false) {\n console.log(\"Map Page is Not Open\");\n context.global.evbArray.push(evbdata);\n return null;\n} else {\n msg.payload = JSON.stringify([evbdata]);\n // not sure about this. kill the msg.session makes it \"go\" \n // to any listener?\n // console.log(\"Session \" + JSON.stringify(msg._session));\n //msg._session=\"\";\n return msg;\n}","outputs":1,"noerr":0,"x":649.4521713256836,"y":385.8571891784668,"z":"815521a7.8cc2f","wires":[["7a799458.09492c","5c5293a7.98b6dc"]]},{"id":"9b08a3fc.44a32","type":"function","name":"parse EVB Packet","func":"// LoRa Packet input\n// msg.chan 3 msg.cls 0 msg.codr \"4/5\" msg.modu \"LORA\" \n// msg.seqn 0 msg.size 20 msg.rfch 0\n// msg.datar=SF9BW125 Spread factor, BandWidth k\n// msg.freq=\"902.3\"\n// msg.lsnr \"12.2\"\n// msg.port 1\n// msg.rssi = -53\n// msg.payload = EVBData\n// return (current evbData, msg(if it is complete)\n// Note: LoRa demo mode doesn't use start/stop data, so it is never complete!\n\nvar data_type = {\n\tnone : 0,\n\tledRedGreen : 1,\n\tledBackBlue : 2,\n\tluxMax : 3,\n\tluxMin : 4,\n\tluxCurr : 5,\n\tbaroMax : 6,\n\tbaroMin : 7,\n\tbaroCurr : 8,\n\ttempMax : 9,\n\ttempMin : 10,\n\ttempCurr : 11,\n\taccelMax : 12,\n\taccelMin : 13,\n\taccelCurr : 14,\n\tconfiguration : 15,\n\tgpioInput : 16,\n\tgpioOutput : 17,\n\tampsMax : 18,\n\tampsMin : 19,\n\tampsCurr : 20,\n\tgpsLattitude : 21,\n\tgpsLongitude : 22,\n\tgpsTime : 23,\n\tgpsDate : 24,\n\tgpsLockStatus : 25,\n\tQOSUplink : 26,\n\tQOSDownlink : 27,\n\trfPower : 28,\n\tdataStartStop : 29,\n};\n\nvar data_out = {\n\tledRedGreen : 0,\n\tledBackBlue : 0,\n\n //demo mode passes these\n luxCurr : 0,\n baroCurr : 0,\n tempCurr : 0,\n accelCurrX : 0,\n\taccelCurrY : 0,\n\taccelCurrZ : 0,\n\t\n/* Not implemented yet\t\n\tluxMax : 0,\n\tluxMin : 0,\n\tluxCurr : 0,\n\n\tbaroMax : 0,\n\tbaroMin : 0,\n\tbaroCurr : 0,\n\n\ttempMax : 0,\n\ttempMin : 0,\n\ttempCurr : 0,\n\n\taccelMaxX : 0,\n\taccelMaxY : 0,\n\taccelMaxZ : 0,\n\taccelMinX : 0,\n\taccelMinY : 0,\n\taccelMinZ : 0,\n\taccelCurrX : 0,\n\taccelCurrY : 0,\n\taccelCurrZ : 0,\n\t\t\n\tconfiguration : 0,\n\t\tpkt_timer :0,\n\n\tgpioInput : 0,\n\tgpioOutput : 0,\n\n\tampsMax : 0,\n\tampsMin : 0,\n\tampsCurr : 0,\n*/\n\tgpsLockStatus : 0,\n\tgpsNSatellites : 0,\n\tgpsLatDegree : 0,\n\tgpsLatMin : 0,\n\tgpsLatSec : 0,\n\tgpsLattitude : \"\",\n\tgpsLatChar : \"\",\n\t\n\tgpsLongDegree : 0,\n\tgpsLongMin : 0,\n\tgpsLongSec : 0,\n\tgpsLongitude : \"\",\n\tgpsLongChar : \"\",\n\tgpsTime : 0,\n\tgpsDate : 0,\n\n\tnGateways : 0, //was qosUplinkRssi\n\tmargin : 0, // Was qosUplinkSnr\n\tqosDownlinkRssi : 0,\n\tqosDownlinkSnr : 0,\n\trfPower : 0, //change to txPower\n\tdataStartStop : 0,\n\tblock_start : 0,\n};\n\n// evbData is the latest values\ncontext.global.evbDataOut = context.global.evbDataOut || data_out;\nvar msg_pntr = -1;\nvar msgType = 0;\nvar pData = context.global.evbDataOut;\n\n//// clear saved data after it's logged\n//if (pData.dataStartStop == 2) {\n//\tconsole.log(\"Not Clear Data\");\n////\tcontext.global.evbDataOut = data_out;\n////\tconsole.log(\"Back from clear Data\"); //I've seen block_start undefined!\n//\tpData.dataStartStop = 0;\n//\tpData.block_start = 0;\n//}\n\n// Until I pass the entire message out, I will save some of the LoRa\n// info in the data.\n\npData.timestamp = msg.timestamp;\npData.seqn = msg.seqn;\npData.eui = msg.eui;\npData.datr = msg.datr;\npData.freq = msg.freq;\npData.lsnr = msg.lsnr;\npData.rssi = msg.rssi;\n\nwhile (msg_pntr < msg.payload.length-1){\n\tmsg_pntr++;\n\t//console.log(\"Key \" + msg.payload[msg_pntr]);\n\tmsgType = msg.payload[msg_pntr];\n\tswitch (msgType){\n\tcase data_type.ledRedGreen:\n\t\t// 0 – RED LED On, Green LED off\n\t\t// 1 – Green LED On, Red LED off\n\t\tpData.ledRedGreen = msg.payload[++msg_pntr];\n\t\tbreak;\n\tcase data_type.ledBackBlue:\n\t\t// 1-on, 0-off\n\t\tpData.ledBackBlue = msg.payload[++msg_pntr];\n\t\tbreak;\n\t\n\tcase data_type.luxMax:\n\tcase data_type.luxMin:\n\tcase data_type.luxCurr:\n\t\t// 2 bytes Lux Value (unsigned, MSB)\n // lux illumination per square metere\n // Should we convert to foot Candles?\n // footCandles is approximately lux/10\n\t\tvar lux = msg.payload[++msg_pntr] << 8; \n\t\tlux |= msg.payload[++msg_pntr];\n\t\tlux = lux * 0.24;\n\t\tif (msgType == data_type.luxMax) {\n\t\t\tpData.luxMax = lux;\n\t\t} else if (msgType == data_type.luxMin) {\n\t\t\tpData.luxMin = lux;\n\t\t} else {\n\t\t\tpData.luxCurr = lux;\n\t\t}\n\t\t//console.log(\"Lux \" + lux);\n\t\tbreak;\n\tcase data_type.baroMax:\n\tcase data_type.baroMin:\n\tcase data_type.baroCurr:\n\t\t// 3 bytes 0.25 Pascals (signed, MSB)\n\t\tvar baroPressure = msg.payload[++msg_pntr]<<16;\n\t\tbaroPressure |= msg.payload[++msg_pntr]<<8;\n\t\tbaroPressure |= msg.payload[++msg_pntr];\n\t\tbaroPressure = baroPressure * 0.00025; //kPa\n\t\tif (msgType == data_type.baroMax) {\n\t\t\tpData.baroMax = baroPressure;\n\t\t} else if (msgType == data_type.baroMin) {\n\t\t\tpData.baroMin = baroPressure;\n\t\t} else {\n\t\t\tpData.baroCurr = baroPressure;\n\t\t}\n\t\t//console.log(\"baroPressure \" + baroPressure);\n\t\tbreak;\n\tcase data_type.accelMax:\n\tcase data_type.accelMin:\n\tcase data_type.accelCurr:\n\t\t// 3 bytes(X, Y, Z) 0.0625 g (signed)\n\t\tvar x_pos = ((msg.payload[++msg_pntr] << 24) >> 24) * 0.0625;\n\t\tvar y_pos = ((msg.payload[++msg_pntr] << 24) >> 24) * 0.0625;\n\t\tvar z_pos = ((msg.payload[++msg_pntr] << 24) >> 24) * 0.0625;\n\t\tif (msgType == data_type.accelMax) {\n\t\t\tpData.accelMaxX = x_pos;\n\t\t\tpData.accelMaxY = y_pos;\n\t\t\tpData.accelMaxZ = z_pos;\n\t\t} else if (msgType == data_type.accelMin) {\n\t\t\tpData.accelMinX = x_pos;\n\t\t\tpData.accelMinY = y_pos;\n\t\t\tpData.accelMinZ = z_pos;\n\t\t} else {\n\t\t\tpData.accelCurrX = x_pos;\n\t\t\tpData.accelCurrY = y_pos;\n\t\t\tpData.accelCurrZ = z_pos;\n\t\t}\n\t\t//console.log(\"accelX \" + x_pos);\n\t\t//console.log(\"accelY \" + y_pos);\n\t\t//console.log(\"accelZ \" + z_pos);\n\t\tbreak;\n\tcase data_type.tempMin:\n\tcase data_type.tempMax:\n\tcase data_type.tempCurr:\n\t\t// 2 bytes 0.0625 Degrees C (signed, MSB)\n\t\tvar temperature = msg.payload[++msg_pntr] << 24;\n\t\ttemperature |= msg.payload[++msg_pntr] << 16;\n\t\ttemperature = (temperature >> 16) * .0625;\n\t\tif (msgType == data_type.tempMin) {\n\t\t\tpData.tempMin = temperature;\n\t\t} else if (msgType == data_type.tempMax) {\n\t\t\tpData.tempMax = temperature;\n\t\t} else {\n\t\t\tpData.tempCurr = temperature;\n\t\t}\n\t\t//console.log(\"Temp \" + temperature + \"C\");\n\t\tbreak;\n\tcase data_type.configuration:\n\t\t// 2 bytes Report Rate milliseconds (< 50 ms disables automated reporting)\n\t\t// n keys to report\n\t\tpData.pkt_timer = msg.payload[++msg_pntr];\n\t\tmsg_pntr++;\n\t\tbreak;\n\tcase data_type.gpioInput:\n\t\t// 1 byte 0 is low, 1 is high\n\t\tpData.gpioInput = msg.payload[++msg_pntr];\n\tbreak;\n\tcase data_type.gpioOutput:\n\t\t// 1 byte 0 is low, 1 is high\n\t\tpData.gpioInput = msg.payload[++msg_pntr];\n\tbreak;\n\tcase data_type.ampsMax:\n\tcase data_type.ampsMin:\n\tcase data_type.ampsCurr:\n\t\t// 2 bytes TBD\n\t\tvar amps = msg.payload[++msg_pntr] << 24;\n\t\tamps |= msg.payload[++msg_pntr] << 16;\n\t\tamps = (amps >> 16) * .0625;\n\t\tif (msgType == data_type.ampsMax) {\n\t\t\tpData.ampsMax = amps;\n\t\t} else if (msgType == data_type.ampsMin) {\n\t\t\tpData.ampsMin = amps;\n\t\t} else {\n\t\t\tpData.amspCurr = amps;\n\t\t}\n\t\tbreak;\n\tcase data_type.gpsLongitude:\n\t\t//console.log(\"gpsLongitude\");\n\t\t//12309.57,W Destination waypoint longitude 123 deg. 09.57 min. W\n\t\t//2 bytes Degrees - negative is West(signed, MSB)\n\t\tpData.gpsLongDegree = msg.payload[++msg_pntr] << 24;\n\t\tpData.gpsLongDegree |= (msg.payload[++msg_pntr] << 16);\n\t\tpData.gpsLongDegree = (pData.gpsLongDegree >> 16);\n\t\tif (pData.gpsLongDegree > 0) {\n\t\t\tpData.gpsLongChar = \"E\";\n\t\t} else {\n\t\t\tpData.gpsLongChar = \"W\";\n\t\t\tpData.gpsLongDegree = pData.gpsLongDegree * -1;\n\t\t}\n\t\t//console.log(\"gpsLongDegree\" + pData.gpsLongDegree + pData.gpsLongChar);\n\t\n\t// --1 byte Minutes (unsigned)\n\t\tpData.gpsLongMin = msg.payload[++msg_pntr];\n\t\ttemp = msg.payload[++msg_pntr] << 8 \n\t\ttemp |= msg.payload[++msg_pntr];\n\t\tpData.gpsLongSec = temp * 0.006;\n\t\t// for GTS Map Data\n\t\t//pData.gpsLongMin = pData.gpsLongMin + (temp * 0.0001);\n//\t\tconsole.log(\"gpsLongDegree\" + pData.gpsLongDegree);\n//\t\tconsole.log(\"gpsLongMin\" + pData.gpsLongMin);\n//\t\tconsole.log(\"gpsLongSec\" + pData.gpsLongSec);\n\n//\t// --2 bytes 0.006 Seconds (unsigned, MSB)\n//\t\t//console.log(\"Byte:\" + msg.payload[msg_pntr]);\n//\t\tpData.gpsLongSec = msg.payload[++msg_pntr]<<8;\n//\t\tpData.gpsLongSec |= msg.payload[++msg_pntr];\n\t\t//console.log(\"gpsLongSec\" + pData.gpsLongSec);\n\t//gpsLongitude\n//\t\tpData.gpsLongitude = \"\" + pData.gpsLongDegree;\n//\t\tpData.gpsLongitude = pData.gpsLongitude + (\"00\" + pData.gpsLongMin).slice(-2);\n//\t\tpData.gpsLongitude = pData.gpsLongitude + \".\" + pData.gpsLongSec;\n//\t\tpData.gpsLongitude = pData.gpsLongitude + pData.gpsLongMin;\n\t\t\tpData.gpsLongitude = \"\" + ((pData.gpsLongDegree * 100) + pData.gpsLongMin + (pData.gpsLongSec *.01));\n\n\t\t//console.log(\"gpsLongitude \" + pData.gpsLongitude + pData.gpsLongChar);\n\t\tbreak;\n\n\tcase data_type.gpsLattitude:\n\t\t//2? bytes (looks like 1!)Degrees - negative is South(signed, MSB)\n\t\tpData.gpsLatDegree = (msg.payload[++msg_pntr] << 24) >> 24;\n\t\tif (pData.gpsLatDegree > 0) {\n\t\t\tpData.gpsLatChar = \"N\";\n\t\t} else {\n\t\t\tpData.gpsLatChar = \"S\";\n\t\t\tpData.gpsLatDegree = pData.gpsLatDegree * -1;\n\t\t}\n\t// --1 byte Minutes (unsigned)\n\t\tpData.gpsLatMin = msg.payload[++msg_pntr];\n\n\t\t// --2 bytes 0.006 Seconds (unsigned, MSB)\n\t\ttemp = msg.payload[++msg_pntr] << 8 \n\t\ttemp |= msg.payload[++msg_pntr];\n\t\tpData.gpsLatSec = temp * 0.006;\n\t\t//pData.gpsLatMin = pData.gpsLatMin + (temp * 0.0001);\n\t\t//console.log(\"gpsLatDegree\" + pData.gpsLatDegree);\n\t\t//console.log(\"gpsLatMin\" + pData.gpsLatMin);\n\t\t//console.log(\"gpsLatSec\" + pData.gpsLatSec);\n\t//gpsLattitude\n//\t\tpData.gpsLattitude = \"\" + pData.gpsLatDegree;\n//\t\tpData.gpsLattitude = pData.gpsLattitude + (\"00\" + pData.gpsLatMin).slice(-2);\n//\t\tpData.gpsLattitude = pData.gpsLattitude + \".\" + pData.gpsLatSec;\n\t\tpData.gpsLattitude = pData.gpsLatDegree + pData.gpsLatMin + (pData.gpsLatSec * 0.01);\n\t\tpData.gpsLattitude = \"\" + ((pData.gpsLatDegree * 100) + pData.gpsLatMin + (pData.gpsLatSec * 0.01));\n\t//console.log(\"gpsLattitude \" + pData.gpsLattitude + pData.gpsLatChar);\n\t\tbreak;\n\n\tcase data_type.gpsTime:\n\t\t// 3 bytes HOurs, Minutes, Seconds (unsigned)\n\t\tmsg_pntr++;\n\t\tpData.gpsTime = (\"00\" + msg.payload[msg_pntr]).slice(-2);\n\t\tmsg_pntr++;\n\t\tpData.gpsTime = pData.gpsTime + (\"00\" + msg.payload[msg_pntr]).slice(-2);\n\t\tmsg_pntr++;\n\t\tpData.gpsTime = pData.gpsTime + (\"00\" + msg.payload[msg_pntr]).slice(-2);\n\t\tbreak;\n\tcase data_type.gpsDate:\n\t\t// 3 bytes Month, Day, Year(from 2000) (unsigned)\n\t\tmsg_pntr++;\n\t\tpData.gpsDate = (\"00\" + msg.payload[msg_pntr]).slice(-2);\n\t\tmsg_pntr++;\n\t\tpData.gpsDate = pData.gpsDate + (\"00\" + msg.payload[msg_pntr]).slice(-2);\n\t\tmsg_pntr++;\n\t\tpData.gpsDate = pData.gpsDate + (\"00\" + msg.payload[msg_pntr]).slice(-2);\n\t\tbreak;\n\tcase data_type.gpsLockStatus:\n\t\t//Bits 0-3 – lock status \n\t\t//0 = no GPS device detected\n\t\t//1 = no fix\n\t\t//2 = 2D fix - latitude, longitude, time only valid\n\t\t//3 = 3D fix - all data valid\n\t\t//Bits 4-7 – number of satellites seen\n\t\tmsg_pntr++;\n\t\t//console.log(\"gpsLock: \" + msg.payload[msg_pntr]);\n\t\tpData.gpsLockStatus = (msg.payload[msg_pntr] & 0x0F);\n\t\tpData.gpsNSatellites = (msg.payload[msg_pntr] >> 4);\n//\t\tconsole.log(\" nSatellites: \" + pData.gpsNSatellites + \"gpsLock: \" + pData.gpsLockStatus);\t\t\n\t\tbreak;\n\tcase data_type.QOSUplink:\n\t // The number of gateways that saw the link check request, \n\t // the signal margin above the demodulation floor, \n\t // and the TX power.\n\n\t\t// 0-1\tnGateways (signed, MSB) was RSSI Value\n\t\tvar rssi = msg.payload[++msg_pntr] << 24;\n\t\trssi |= (msg.payload[++msg_pntr] << 16);\n\t\tpData.nGateways = (rssi >> 16);\n\t\t// 2 margin above demodulation floor (signed) (was SNR Value)\n\t\tpData.margin = ((msg.payload[++msg_pntr] << 24) >> 24);\n\t\t// 3 RF Power level Value dBm (signed)\n\t\tpData.rfPower = ((msg.payload[++msg_pntr] << 24) >> 24);\n\t\tbreak;\n\tcase data_type.QOSDownlink:\n\t\t// 0-1\tRSSI Value (signed, MSB)\n\t\tvar rssi = msg.payload[++msg_pntr] << 24;\n\t\trssi |= (msg.payload[++msg_pntr] << 16);\n\t\tpData.qosDownlinkRssi = (rssi >> 16);\n\t\t// 2\tSNR Value (signed) 1/4 DB\n\t\tvar snr = ((msg.payload[++msg_pntr] << 24) >> 24);\n\t\t// Documentation may be wrong it says 1/4 dB\n\t\t//pData.qosDownlinkSnr = snr * 0.25;\n\t\tpData.qosDownlinkSnr = snr;\n\t\tbreak;\n\tcase data_type.rfPower:\n\t\t// 1 byte RF Power level Value dBm (signed)\n\t\tpData.rfPower = ((msg.payload[++msg_pntr] << 24) >> 24);\n\t\tbreak;\n\tcase data_type.dataStartStop:\n\t\t//console.log(\"dataStartStop: \" + pData.dataStartStop + \" byte? \" + msg_pntr);\n//\t\tif (pData.dataStartStop == 0) {\n//\t\t\tpData.dataStartStop\t= 1; //start sending data\n//\t\t} else if (pData.dataStartStop == 1) {\n//\t\t\tpData.dataStartStop\t= 2; // forward the packet;\n//\t\t}\n\t\t//Tim's Code ---\n\t\tif (msg_pntr === 0) {\n\t\t\t//console.log(\"Begin Block: \" + pData.dataStartStop);\n\t\t\t// Doesn't seem to work here!\n//\t\t\tconsole.log(\"Clear Data\");\n//\t\t\tcontext.global.evbDataOut = data_out;\n\t\t\tpData.dataStartStop\t= 1; //start sending data\n//\t\t\tpData = data_out;\n//\t\t\tblock_start = 1;\n\t\t\tpData.block_start = 1;\n//\t\t\tconsole.log(\"Begin Block: \" + pData.dataStartStop);\n\t\t}\n//\t\telse if (msg_pntr == (msg.payload.length - 1) && (pData.block_start = 1)) {\n\t\telse if (msg_pntr == (msg.payload.length - 1) && (pData.block_start == 1)) {\n//\t\t\tconsole.log(\"End Block: \" + pData.dataStartStop);\n\t\t\tpData.data_valid = 1;\n\t\t\tpData.dataStartStop\t= 2; // forward the packet;\n\t\t}\n\t\telse {\n\t\t\tconsole.log(\"BAD Block: \" + pData.dataStartStop + \" Bstrt:\" + pData.block_start + \" bLen:\" + (msg.payload.length - 1) + \" ptr:\" + msg_pntr);\n//\t\t\tconsole.log(\"BAD Block: \" + pData.dataStartStop);\n//\t\t\tpData.block_start = 0;\n//\t\t\tpData = data_out;\n//\t\t\tmsg_pntr = msg.payload.length;\n\t\t}\n\t\t\n\t\tbreak;\n\tdefault:\n\t\tconsole.log(\"Undefined type or pkt out of sync: \" + msg.payload[msg_pntr]);\n\t}\n}\n//console.log(\"pData BacklightBlue: \" + pData.ledBackBlue + \" RedGreen: \" + pData.ledRedGreen);\n\n// Currently not sending time and date!\n//if (pData.gpsDate == 0) {\n\tvar currentDate = new Date();\n\tvar day = (\"00\" + currentDate.getUTCDate()).slice(-2);\n\tvar month = (\"00\" + (currentDate.getUTCMonth() + 1)).slice(-2);\n\tvar year = currentDate.getUTCFullYear() - 2000;\n\tpData.gpsDate = \"\" + day + month + year;\n\t//console.log(\"gpsDate \" + pData.gpsDate);\n//}\n//if (pData.gpsTime == 0) {\n\tvar currentDate = new Date();\n\tvar hour = (\"00\" + currentDate.getUTCHours()).slice(-2);\n\tvar min = (\"00\" + currentDate.getUTCMinutes()).slice(-2);\n\tvar sec = (\"00\" + currentDate.getUTCSeconds()).slice(-2);\n\tpData.gpsTime = \"\" + hour + min + sec;\n\t//console.log(\"gpsTime \" + pData.gpsTime);\n//}\n\n//Don't think this works! msg.evbDataOut = pData;\nif (pData.dataStartStop == 2) {\n // complete packet\n\t//console.log(\"Send GPS Data\");\n\t//Clearing a large Global data structure seems to cause \n\t//Some timeing problems. Data comes in before it is completely cleared\n\t//console.log(\"Not Clear Data\");\n\t//\tcontext.global.evbDataOut = data_out;\n\t//\tconsole.log(\"Back from clear Data\"); //I've seen block_start undefined!\n\tpData.dataStartStop = 0;\n\tpData.block_start = 0;\n\t//console.log(\"pData,msg dataStartStop=2\");\n\treturn [pData,msg]; \n} else {\n // partial packet (no stop data at the end)\n\t//console.log(\"partial packet pData,null\");\n\treturn [pData,null];\n}","outputs":"2","noerr":0,"x":380.59525299072266,"y":251.42853927612305,"z":"815521a7.8cc2f","wires":[["dcb95c2d.c4d96","a892e9fc.172408","f734d6c2.461488","531701d5.6f5ca"],["150efa2e.684886"]]},{"id":"e59d98bf.feb0b8","type":"function","name":"Clear evbDataOut","func":"//context.global.location = msg.payload;\ncontext.global.evbDataOut = null;\ncontext.global.evbArray = [];\nreturn null;\n","outputs":1,"noerr":0,"x":606.0536117553711,"y":1041.9841232299805,"z":"815521a7.8cc2f","wires":[[]]},{"id":"4479f765.f642f8","type":"inject","name":"Clear evbData","topic":"","payload":"","payloadType":"none","repeat":"","crontab":"","once":false,"x":367.8393249511719,"y":1042.5554733276367,"z":"815521a7.8cc2f","wires":[["e59d98bf.feb0b8"]]},{"id":"fa23da36.eec588","type":"comment","name":"clear evbMonitor data","info":"clear the saved evbData used to show the \nlast value received on the evbMonitor web page.\nAlso, clear the captured data with valid GPS data.","x":165.16666412353516,"y":1037.9365367889404,"z":"815521a7.8cc2f","wires":[]},{"id":"1083bb4a.623785","type":"comment","name":"EVB to csvFile","info":"csv Data\n- write all evb packet data to a csv file.\n- name: /media/card/evbCsv (if there is a media card present)\n- name: /var/evbCsv\n- timestamp of the LoRa packet\n - datr Data Rate (Spread Factor and Band Width)\n - rfPower \n- freq \n- lsnr\n- rssi\n- seqn LoRa packet Sequence number\n- eui EVB Device Id\n- ledRedGreen \n- ledBackBlue\n- luxCurr Light level\n- baroCurr\n- tempCurr\n- accelCurrX,accelCurrY,accelCurrZ\n- ID (not reported)\n- Status (not reported)\tSpecifies if the survey was a success or failure\n- Lock\tGPS lock (# of satellites)\n - gpsLockStatus\tGPS lock status \n - gpsNSatellites(# of satellites)\n- Lat GPS latitude\n- Long GPS longitude\n- Alt gpsAltitude (not reported)\n- Time GPS timestamp (UTC format)\n- nGateways\tHow many gateways heard the link check request\n- Margin\tSignal margin above the demodulation floor (in dBm)\n- RSSIdown\tDownlink signal strength (RSSI)\n- SNRdown\tDownlink signal-to-noise ratio (SNR)\n- DataRate\t(Spread Factor and Band Width)\n- Power TX power used\n","x":160.87796020507812,"y":764.7778129577637,"z":"815521a7.8cc2f","wires":[]},{"id":"b9fe88f6.2b2148","type":"comment","name":"Survey Data File ","info":"- Survey Data File (on the EVB) This file can be extracted from the MTDOT-BOX via the ribbon cable.\n - http://www.multitech.net/developer/software/dot-box-and-evb-software/survey-data-file/ \n - ID\t(not reported) Identifies the line as a single survey or part of a sweep and contains the corresponding index\n - Status (not reported) Specifies if the survey was a success or failure.\n - Lock GPS lock (# of satellites)\n - Lat\tGPS latitude\n - Long GPS longitude\n - Alt\tGPS altitude\n - Time GPS timestamp (UTC format)\n - Gateways How many gateways heard the link check request\n - Margin Signal margin above the demodulation floor (in dBm)\n - The value is > 0.\n - The demodulation floor is static and depends on the data rate (Spread Factor and Band Width).\n - The noise floor depends on conditions, and is the value below which the LoRa card can not distinguish betwwen the noise and packet data. \n - RSSIdown Downlink signal strength (RSSI)\n - SNRdown\tDownlink signal-to-noise ratio (SNR)\n - DataRate TX datarate used\n - Power TX power used","x":167.87796783447266,"y":804.0000419616699,"z":"815521a7.8cc2f","wires":[]},{"id":"531701d5.6f5ca","type":"function","name":"To csv","func":"// Write the csv file header and pass formatted data to a file node \n// \n//\ncontext.global.csvFileOpened = context.global.csvFileOpened || false;\nvar pCsvPath = context.global.csvPath || \"/media/card/evbCsv\";\n//var pCsvPath = context.global.csvPath || \"/var/evbCsv\";\n\nvar pCsvFileOpened = context.global.csvFileOpened;\nvar pData = context.global.evbDataOut;\nvar messages = [];\nvar newpayload = \"timestamp,DataRate,Power,freq,lsnr,rssi,seqn,eui\";\nmsg.filename = pCsvPath;\n\nif (pCsvFileOpened === false) {\n\tpCsvFileOpened = true;\n\tcontext.global.csvFileOpened = true;\n\tnewpayload = newpayload + \",ledRedGreen,ledBackBlue\";\n\tnewpayload = newpayload + \",luxCurr\";\n\tnewpayload = newpayload + \",baroCurr\";\n\tnewpayload = newpayload + \",tempCurr\";\n\tnewpayload = newpayload + \",accelCurrX,accelCurrY,accelCurrZ\";\n\t\n\tnewpayload = newpayload + \",Lock,Lat,Long\"\n\tnewpayload = newpayload + \",gpsTime,gpsDate\";\n\n\tnewpayload = newpayload + \",nGateways,margin,RSSIdown,SNRdown\";\n//\tnewpayload = newpayload + \"\\n\";\n\tmsg.payload = newpayload;\n\tmessages.push(JSON.parse(JSON.stringify(msg)));\n}\nnewpayload = \"\";\ncontext.global.evbDataOut = context.global.evbDataOut || data_out;\nvar pData = context.global.evbDataOut;\n\n\t//gpsLatDegree\n\t//gpsLatMin\n\t//gpsLatSec\n\t//gpsLatChar\n\t\n\t//gpsLongDegree\n\t//gpsLongMin\n\t//gpsLonSec\n\t//gpsLongitude\n\t//gpsLongChar\n\nnewpayload = newpayload + msg.timestamp + \",\" + msg.datr + \",\";\nnewpayload = newpayload + pData.rfPower + \",\";\nnewpayload = newpayload + msg.freq + \",\" + msg.lsnr + \",\";\nnewpayload = newpayload + msg.rssi + \",\" + msg.seqn + \",\";\nnewpayload = newpayload + msg.eui + \",\";\n\nnewpayload = newpayload + pData.ledRedGreen + \",\" + pData.ledBackBlue + \",\";\nnewpayload = newpayload + pData.luxCurr + \",\";\nnewpayload = newpayload + pData.baroCurr + \",\";\nnewpayload = newpayload + pData.tempCurr + \",\";\nnewpayload = newpayload + pData.accelCurrX + \",\" + pData.accelCurrY + \",\" + pData.accelCurrZ + \",\";\n\n// Lock GPS Lock (# of satellites)\n//newpayload = newpayload + pData.gpsLockStatus + \",\" + pData.gpsNSatellites + \",\";\nnewpayload = newpayload + pData.gpsNSatellites + \",\"\n\nnewpayload = newpayload + pData.gpsLattitude + pData.gpsLatChar + \",\";\nnewpayload = newpayload + pData.gpsLongitude + pData.gpsLongChar + \",\";\nnewpayload = newpayload + pData.gpsTime + \",\" + pData.gpsDate + \",\";\n\nnewpayload = newpayload + pData.nGateways + \",\" + pData.margin + \",\";\nnewpayload = newpayload + pData.qosDownlinkRssi + \",\" + pData.qosDownlinkSnr + \",\";\n\nmsg.payload = newpayload;\nmessages.push(JSON.parse(JSON.stringify(msg)));\nreturn [messages];","outputs":1,"noerr":0,"x":359.87792205810547,"y":796.1111259460449,"z":"815521a7.8cc2f","wires":[["1f848ad9.7e0f45","a56509d6.32b858"]]},{"id":"1f848ad9.7e0f45","type":"debug","name":"evbCsv lines","active":false,"console":"false","complete":"payload","x":585.0325546264648,"y":798.0753593444824,"z":"815521a7.8cc2f","wires":[]},{"id":"a56509d6.32b858","type":"file","name":"Append to evbCsv","filename":"","appendNewline":true,"createDir":false,"overwriteFile":"false","x":602.3659896850586,"y":851.0754814147949,"z":"815521a7.8cc2f","wires":[]},{"id":"d733d785.654e18","type":"sms in","name":"","x":137.47519302368164,"y":888.4443874359131,"z":"815521a7.8cc2f","wires":[["1b619355.03b94d"]]},{"id":"1b619355.03b94d","type":"function","name":"Start of Test","func":"// Add timestamp and SMS message to evbCsv file\nvar pCsvPath = context.global.csvPath || \"/media/card/evbCsv\";\n//var pCsvPath = context.global.csvPath || \"/var/evbCsv\";\n\nvar newpayload = \"\";\nnewpayload = newpayload + msg.timestamp + \",\" + msg.payload + \",\";\n\nmsg.payload = newpayload;\nmsg.filename = pCsvPath;\n\nreturn [msg];","outputs":"1","noerr":0,"x":298.04668045043945,"y":889.3492546081543,"z":"815521a7.8cc2f","wires":[["fe13a3ff.7354","a56509d6.32b858"]]},{"id":"fe13a3ff.7354","type":"debug","name":"","active":true,"console":"false","complete":"true","x":562.9274826049805,"y":906.1348686218262,"z":"815521a7.8cc2f","wires":[]},{"id":"2ffc7c84.93dfb4","type":"inject","name":"Init global settings","topic":"","payload":"","payloadType":"none","repeat":"","crontab":"","once":true,"x":490.80855560302734,"y":82.59257698059082,"z":"815521a7.8cc2f","wires":[["2b69c574.920fba"]]},{"id":"2b69c574.920fba","type":"function","name":"Init global data","func":"//lora packet\ncontext.global.pkts = context.global.pkts || {};\ncontext.global.lastEUI = null;\n//tocsv\ncontext.global.csvFileOpened = context.global.csvFileOpened || false;\ncontext.global.csvPath = context.global.csvPath || \"/media/card/evbCsv\";\n//context.global.csvPath = context.global.csvPath || \"/var/evbCsv\";\n\n//evbMonitor\ncontext.global.evbDataOut = context.global.evbDataOut || null;\n\n///map\ncontext.global.gMapReady = false;\ncontext.global.evbArray = context.global.evbArray || [];\n\n// Don't send packets with invalid GPS Data to the google map\ncontext.global.sendOnlyValidData = true;\nreturn null;\n","outputs":1,"noerr":0,"x":680.8085250854492,"y":82.59257698059082,"z":"815521a7.8cc2f","wires":[[]]},{"id":"3a135a46.ea4826","type":"function","name":"Store || retrieve data","func":"// Save the latest values from the current packet\n// if they are != 0\nif (msg.topic === \"data\") {\n // new data saved to be displayed\n // console.log(\"context.msg\" + JSON.stringify(context.msg));\n context.data = msg.payload;\n if (typeof(context.msg) === \"undefined\") {\n // first time, we save what ever we received.\n //console.log(\"null context.msg\");\n\tcontext.msg = msg;\n\treturn null;\n }\n // context.msg = msg;\n //could passs it in this way\n //context.data_out = msg.data_out;\n \n //console.log(\"New data \" + JSON.stringify(msg));\n\n\n //Currently not passed along!\n //if (msg.timestamp != 0) {context.msg.timestamp = msg.timestamp};\n ////if (msg.loRaPayload != 0) {context.msg.loRaPayload = msg.loRaPayload};\n //if (msg.datr != 0) { context.msg.datr = msg.datr };\n //if (msg.freq != 0) { context.msg.freq = msg.freq };\n //if (msg.lsnr != 0) { context.msg.lsnr = msg.lsnr };\n //if (msg.rssi != 0) { context.msg.rssi = msg.rssi };\n //if (msg.seqn != 0) { context.msg.seqn = msg.seqn };\n //if (msg.eui != 0) { context.msg.eui = msg.eui };\n\n if (msg.ledRedGreen !== 0) { context.msg.ledRedGreen = msg.ledRedGreen }\n if (msg.ledBackBlue !== 0) { context.msg.ledBackBlue = msg.ledBackBlue }\n //if (msg.luxMax != 0) { context.msg.luxMax = msg.luxMax };\n //if (msg.luxMin != 0) { context.msg.luxMin = msg.luxMin };\n if (msg.luxCurr !== 0) { context.msg.luxCurr = msg.luxCurr }\n //if (msg.baroMax != 0) { context.msg.baroMax = msg.baroMax };\n //if (msg.baroMin != 0) { context.msg.baroMin = msg.baroMin };\n if (msg.baroCurr !== 0) { context.msg.baroCurr = msg.baroCurr }\n //if (msg.tempMax != 0) { context.msg.tempMax = msg.tempMax };\n //if (msg.tempMin != 0) { context.msg.tempMin = msg.tempMin };\n if (msg.tempCurr !== 0) { context.msg.tempCurr = msg.tempCurr }\n //if (msg.accelMaxX != 0) { context.msg.accelMaxX = msg.accelMaxX };\n //if (msg.accelMaxY != 0) { context.msg.accelMaxY = msg.accelMaxY };\n //if (msg.accelMaxZ != 0) { context.msg.accelMaxZ = msg.accelMaxZ };\n //if (msg.accelMinX != 0) { context.msg.accelMinX = msg.accelMinX };\n //if (msg.accelMinY != 0) { context.msg.accelMinY = msg.accelMinY };\n //if (msg.accelMinZ != 0) { context.msg.accelMinZ = msg.accelMinZ };\n if (msg.accelCurrX !== 0) { context.msg.accelCurrX = msg.accelCurrX }\n if (msg.accelCurrY !== 0) { context.msg.accelCurrY = msg.accelCurrY }\n if (msg.accelCurrZ !== 0) { context.msg.accelCurrZ = msg.accelCurrZ }\n //if (msg.accelMinX != 0) { context.msg.accelMinY = msg.accelMinZ };\n //if (msg.accelCurrX != 0) { context.msg.accelCurrY = msg.accelCurrZ };\n //if (msg.configuration != 0) { context.msg.configuration = msg.configuration };\n //if (msg.pkt_timer != 0) { context.msg.pkt_timer = msg.pkt_timer };\n //if (msg.ampsMax != 0) { context.msg.ampsMax = msg.ampsMax };\n //if (msg.ampsMin != 0) { context.msg.ampsMin = msg.ampsMin };\n //if (msg.ampsCurr != 0) { context.msg.ampsCurr = msg.ampsCurr };\n //if (msg.gpioInput != 0) { context.msg.gpioInput = msg.gpioInput };\n //if (msg.gpioOutput != 0) { context.msg.gpioOutput = msg.gpioOutput };\n\n if (msg.gpsLockStatus !== 0) { context.msg.gpsLockStatus = msg.gpsLockStatus }\n if (msg.gpsNSatellites !== 0) { context.msg.gpsNSatellites = msg.gpsNSatellites }\n if (msg.gpsLattitude !== 0) { context.msg.gpsLattitude = msg.gpsLattitude }\n if (msg.gpsLatDegree !== 0) { context.msg.gpsLatDegree = msg.gpsLatDegree }\n if (msg.gpsLatMin !== 0) { context.msg.gpsLatMin = msg.gpsLatMin }\n if (msg.gpsLatSec !== 0) { context.msg.gpsLatSec = msg.gpsLatSec }\n if (msg.gpsLatChar !== 0) { context.msg.gpsLatChar = msg.gpsLatChar }\n if (msg.gpsLongitude !== 0) { context.msg.gpsLongitude = msg.gpsLongitude }\n if (msg.gpsLongDegree !== 0) { context.msg.gpsLongDegree = msg.gpsLongDegree }\n if (msg.gpsLongMin !== 0) { context.msg.gpsLongMin = msg.gpsLongMin }\n if (msg.gpsLongSec !== 0) { context.msg.gpsLongSec = msg.gpsLongSec }\n if (msg.gpsLongChar !== 0) { context.msg.gpsLongChar = msg.gpsLongChar }\n if (msg.gpsTime !== 0) { context.msg.gpsTime = msg.gpsTime }\n if (msg.gpsDate !== 0) { context.msg.gpsDate = msg.gpsDate }\n if (msg.nGateways !== 0) { context.msg.nGateways = msg.nGateways }\n if (msg.margin !== 0) { context.msg.margin = msg.margin }\n if (msg.qosDownlinkRssi !== 0) { context.msg.qosDownlinkRssi = msg.qosDownlinkRssi }\n if (msg.qosDownlinkSnr !== 0) { context.msg.qosDownlinkSnr = msg.qosDownlinkSnr }\n if (msg.rfPower !== 0) { context.msg.rfPower = msg.rfPower }\n \n return null; // the web page will request it.\n} else {\n // web page looks for the previous data to display\n msg.payload = context.data || \"Nothing :]\";\n msg.msg = context.msg;\n //msg.data_out = context.msg.data_out;\n //console.log(\"topic \" + msg.topic + \"Current Data \" + msg.payload)\n return msg;\n}","outputs":1,"noerr":0,"x":385.0549545288086,"y":638.1666450500488,"z":"815521a7.8cc2f","wires":[["a93cfe98.2af25"]]},{"id":"597923cf.13aa4c","type":"websocket in","name":"","server":"a89aedba.72c86","client":"","x":160.31548309326172,"y":392.4444389343262,"z":"815521a7.8cc2f","wires":[["3d4d50ec.37ab5"]]},{"id":"3d4d50ec.37ab5","type":"function","name":"webSocket Receive","func":"//{ \"payload\": \"Ping!\", \n//\"_session\": { \"type\": \"websocket\", \"id\": \"998b01e6.6675\" }, \n//\"_msgid\": \"c098c5b7.3f6738\" }\n// console.log(\"evbArray Len \" + context.global.evbArray.length);\nif (msg.payload == \"Ping!\") {\n console.log(\"gMap Ready\");\n if (context.global.gMapReady === false) {\n // Got the \"ready\" response. Send any pending data to the window.\n context.global.gMapReady = true;\n console.log(\"Send Saved Data nPkts \" + context.global.evbArray.length);\n if (context.global.evbArray.length > 0) {\n msg.sendEvbArray = true;\n msg.payload = JSON.stringify(context.global.evbArray);\n return [msg,msg];\n }\n }\n} else if (msg.payload == \"clearMarkers!\") {\n console.log(\"clearMarkers!\");\n} else if (msg.payload == \"showMarkers!\") {\n console.log(\"showMarkers!\");\n} else if (msg.payload == \"deleteMarkers!\") {\n console.log(\"deleteMarkers!\"); \n}\n\nreturn [null,msg];","outputs":"2","noerr":0,"x":399.24996185302734,"y":389.3968620300293,"z":"815521a7.8cc2f","wires":[["dcb95c2d.c4d96"],["e679c03f.81a6b"]]},{"id":"e679c03f.81a6b","type":"debug","name":"Received Message","active":true,"console":"false","complete":"true","x":835.3927230834961,"y":499.4444389343262,"z":"815521a7.8cc2f","wires":[]},{"id":"220e5718.d779c8","type":"comment","name":"SMS comments","info":"A received SMS message will be added to the csvData file. This can be used to \nadd comments to the csvData file when doing a sweep where GPS informatoin is not available.\nex. Sweep at South West corner of shipping.\n ","x":162.65575408935547,"y":851.8888969421387,"z":"815521a7.8cc2f","wires":[]}]