How to make an IoT protocol (parsing, answering)?

This will stick it on a map for you (if you install node-red-contrib-web-worldmap

[{"id":"26c0f014.0fc39","type":"inject","z":"2199fe7c.1785a2","name":"TEST IWAP01+LBS","topic":"","payload":"IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97&Home3|74-DE-2B-44-88-8C|97# ","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":127,"y":282.9999942779541,"wires":[["2670c959.4e4c26"]]},{"id":"2670c959.4e4c26","type":"switch","z":"2199fe7c.1785a2","name":"SORT INCOMING","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"^IWAP01","vt":"str","case":false},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":350,"y":252.00000715255737,"wires":[["5ecb3abd.973c04"],[]]},{"id":"ac8a221d.d78b3","type":"inject","z":"2199fe7c.1785a2","name":"TEST IWAP01","topic":"","payload":"IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":108,"y":238,"wires":[["2670c959.4e4c26"]]},{"id":"5ecb3abd.973c04","type":"function","z":"2199fe7c.1785a2","name":"split IWAP01","func":"// flag A\n//IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#\n// flag V\n//IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97&Home3|74-DE-2B-44-88-8C|97# \nmsg.payload = msg.payload.split(\",\",6)\nreturn msg;\n","outputs":1,"noerr":0,"x":555.0000076293945,"y":252.20000457763672,"wires":[["30ef9e91.77b2d2","fe394d63.3d719"]]},{"id":"30ef9e91.77b2d2","type":"debug","z":"2199fe7c.1785a2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":590,"y":140,"wires":[]},{"id":"fe394d63.3d719","type":"function","z":"2199fe7c.1785a2","name":"Handle location","func":"// flag A\n//IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#\n// flag V\n//IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97&Home3|74-DE-2B-44-88-8C|97# \n\n// just take the first part with the location in and remove the IWAP01\nvar p = msg.payload[0].substr(6);\nvar hr = p.substr(0,2);\nvar mn = p.substr(2,2);\nvar se = p.substr(4,2);\nvar valid = p.charAt(6);\n\nconsole.log(hr,mn,se,valid);\nif (valid === \"V\") { return null; }  // ignore if not valid\n\nvar la = parseInt(p.substr(7,2)) + (p.substr(9,7)/60);\nvar lo = parseInt(p.substr(17,3)) + (p.substr(20,7)/60);\nvar n = p.substr(16,1);\nvar e = p.substr(27,1);\n\nif (n === \"S\") { la = -la; }\nif (e === \"W\") { lo = -lo; }\n\nmsg.payload = {name:\"Fred\", lat:la, lon:lo, hour:hr, min:mn, sec:se}\nreturn msg;\n","outputs":1,"noerr":0,"x":560,"y":320,"wires":[["2c22de96.58a042","34b39429.91c36c"]]},{"id":"2c22de96.58a042","type":"worldmap","z":"2199fe7c.1785a2","name":"","lat":"45.512794","lon":"-122.679565","zoom":"12","layer":"OSM","cluster":"0","maxage":"","usermenu":"show","layers":"show","panit":"false","panlock":"false","zoomlock":"false","path":"/worldmap","x":580,"y":400,"wires":[]},{"id":"34b39429.91c36c","type":"debug","z":"2199fe7c.1785a2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":300,"wires":[]}]

Thanks... I will try it.

Hi dceejay. Of course the final project is to display the tracking in real time in worldmap. I already installed it!

Is it possible to find a solution for LBS and WiFi base locating When needed? There are case I need to compare coordinates from base station which would give me the real address...

Where is that information?

version with bearing and speed (and timestamp more correct) - even if the data says 2008.

[{"id":"83bdc3df.1fe62","type":"inject","z":"82738787.0e0338","name":"TEST IWAP01+LBS","topic":"","payload":"IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97&Home3|74-DE-2B-44-88-8C|97# ","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":1000,"wires":[["6c4b67a5.eaad28"]]},{"id":"6c4b67a5.eaad28","type":"switch","z":"82738787.0e0338","name":"SORT INCOMING","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"^IWAP01","vt":"str","case":false},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":433,"y":969.0000128746033,"wires":[["9b067603.e34b68"],[]]},{"id":"f6f27432.125cd8","type":"inject","z":"82738787.0e0338","name":"TEST IWAP01","topic":"","payload":"IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":191,"y":955.0000057220459,"wires":[["6c4b67a5.eaad28"]]},{"id":"9b067603.e34b68","type":"function","z":"82738787.0e0338","name":"split IWAP01","func":"// flag A\n//IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#\n// flag V\n//IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97&Home3|74-DE-2B-44-88-8C|97# \nmsg.payload = msg.payload.split(\",\",6)\nreturn msg;\n","outputs":1,"noerr":0,"x":638.0000076293945,"y":969.2000102996826,"wires":[["60d18e1a.eaa45","b60e5c9b.fda48"]]},{"id":"60d18e1a.eaa45","type":"debug","z":"82738787.0e0338","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":750,"y":900,"wires":[]},{"id":"b60e5c9b.fda48","type":"function","z":"82738787.0e0338","name":"Handle location","func":"// flag A\n//IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#\n// flag V\n//IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97&Home3|74-DE-2B-44-88-8C|97# \n\n// just take the first part with the location in and remove the IWAP01\nvar p = msg.payload[0].substr(6);\nvar yr = parseInt(p.substr(0,2));\nvar mo = parseInt(p.substr(2,2));\nvar da = parseInt(p.substr(4,2));\nvar dt = new Date(yr+2000, mo-1, da)\n\nvar valid = p.charAt(6);\n\nconsole.log(yr,mo,da,dt,valid);\nif (valid === \"V\") { return null; }  // ignore if not valid\n\nvar la = parseInt(p.substr(7,2)) + (p.substr(9,7)/60);\nvar lo = parseInt(p.substr(17,3)) + (p.substr(20,7)/60);\nvar n = p.substr(16,1);\nvar e = p.substr(27,1);\n\nif (n === \"S\") { la = -la; }\nif (e === \"W\") { lo = -lo; }\n\nvar sp = parseFloat(p.substr(28,5))\nvar h  = parseInt(p.substr(33,2))\nvar m  = parseInt(p.substr(35,2))\nvar s  = parseInt(p.substr(37,2))\nvar hdg = parseFloat(p.substr(39,6))\n\nvar ts = new Date(yr+2000, mo-1, da, h, m, s)\n\nmsg.payload = {name:\"Fred\", lat:la, lon:lo, speed:sp, bearing:hdg, timestamp:ts}\nreturn msg;\n","outputs":1,"noerr":0,"x":643,"y":1037.000005722046,"wires":[["178a2f44.519101","f8259fef.08bc6"]]},{"id":"178a2f44.519101","type":"worldmap","z":"82738787.0e0338","name":"","lat":"45.512794","lon":"-122.679565","zoom":"12","layer":"OSM","cluster":"0","maxage":"","usermenu":"show","layers":"show","panit":"false","panlock":"false","zoomlock":"false","path":"/worldmap","x":700,"y":1120,"wires":[]},{"id":"f8259fef.08bc6","type":"debug","z":"82738787.0e0338","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":873,"y":1017.0000057220459,"wires":[]}]

Colin,
I'm not really sure to understand clearly this points.

For me, this is directly induced for :

  • IWAP01 / When there is no GPS coordinates provided by the watch, then it will get LBS data. Wrote in my previous post about IWAP01 as : "... If state in GPS package is V (for invalid datas) or latitude and longitude are 0000.0000N00000.0000E, it will get only additional LBS data."

Here, what I understand from that is the aiblity to get the correct positions only with the LBS additional bases when GPS positions are 0000.0000N00000.0000E or flag = V... I should probably find a way to use LBS system dicrectly in worldmap. I sent a mail to the manufacturer, to know more about...

  • IWAP02 : I wrote in a previous post "0:reply flag, the server doesn’t reply address when it’s 0,and replies address when it’s 1" and we made split rules to qualify when flag = 0 or flag =1

But here, there are 2 possible answers. Or flag = 0 and the answer is only IWBP02# or flag is 1, and in this case, the server has to answer:
IWBP02F16D3357025E5753715C3A535753776D27595390310030003700390
0F753# UNICODE encoded reply message from server which contains address(深圳市南山区
南海大道1079 号)

That means the server has to setup the watch by providing the
approximate position with the telecoms position (LAC+WIFI), as I understand...

dceejay,
Thanks ! I just tested your code/nodes... It is really ok to convert the alphanumeric encoded longitude and latitude from the string... to worldmap... But, but... in case I click on inject string from TEST IWAP01+LBS, I'm pretty sure I have to verify with a LBS system like OpenCelliD and the WIFI base station infos I'm receiving.

I have to investigate more about this point...

Thanks Colin!!! Your code is perfect!! How to get the additional WIFI bases in case of invalid datas (valid: false) ??

Here they are talking about this...

Hi Colin,
I just saw an error I don't know how to correct in this code. If it flag = 0 then the last object is including # (If flag = 1 no problem)... How can I exclude this ?

I've made some tests.
There are a few errors in your code:

  • the result is always including the last character # How do you suppress this?
  • the worldmap node does not run... It does not diplay the correct GPS positions lat: 22.549676666666667
    lon: 114.08225833333333
    How to fix this?

Thanks

I don't understand what you mean, if I click on the 'Invalid' inject I just get
image

Sorry Colin, I'm talking about message IWAP02 when flag = 0

Here are the png. Issue happens when flag = 0

When flag = 1, no issue...

Is it also possible to split the additional WIFI base infos needed when flag = 1 as I tried with your code below... but whitout succes :smile: :

// flag = 0
//IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7#
// flag = 1
// IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65#
let answer = {}
let elements = msg.payload.split(",") // this gives an array containing the bits
answer.command = elements[0] // IWAP02
answer.languageNotice = elements[1] // zh_cn
answer.flag = elements[2] // 0
node.warn(flag is: ${answer.flag})
// switching answer if flag is 0/1
answer.baseCount = Number(elements[3]) // 7
// you can work out how to put the node.warn statements in yourself
answer.mcc = elements[4] // 460
answer.mnc = elements[5] // 0
// now need to get the bases
let i;
answer.basesGSM =
for (i=6; i<6+answer.baseCount; i++) {
let baseElements = elements[i].split("|")
answer.basesGSM.push({lac: baseElements[0], cid: baseElements[1], dbm: baseElements[2]}) // 9520|3671|10
}
// now need to get the bases
let e;
answer.basesWIFI =
for (e=7; e<6+answer.basesGSM; i++) {
let baseElements = elements[e].split("&")
answer.basesWIFI.push({ssid: baseElements[0], macAddres: baseElements[1], signal: baseElements[2]}) // 4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65
}
msg.payload = answer
return msg

To get rid of the trailing '#' insert this line before the split on comma
msg.payload = msg.payload.replace(/#$/, "");
So now you have

msg.payload = msg.payload.replace(/#$/, "");  // remove trailing #
let elements = msg.payload.split(",")

Just looking at the other problem...

[Edit] Can you post your test flow for the second one so I can make sure I am working on exactly the same data and have the same functions as you.

Nice ! Solved. Thanks.

Here are the datas :

[{"id":"38fd6d46.07d862","type":"tab","label":"IWAP02","disabled":false,"info":""},{"id":"4a330da4.5ac7b4","type":"inject","z":"38fd6d46.07d862","name":"TEST IWAP02#","topic":"","payload":"IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7#","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":114,"y":132.7999906539917,"wires":[["b13eed31.409e9"]]},{"id":"b13eed31.409e9","type":"switch","z":"38fd6d46.07d862","name":"SORT INCOMING","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"^IWAP02","vt":"str","case":false}],"checkall":"true","repair":false,"outputs":1,"x":381.00000381469727,"y":143.8000030517578,"wires":[["97b7209d.3d45"]]},{"id":"168c17f3.e614a8","type":"comment","z":"38fd6d46.07d862","name":"INCOMING MESSAGES FROM THE WATCH","info":"","x":177.3000030517578,"y":22,"wires":[]},{"id":"e6d39b5d.4017e8","type":"comment","z":"38fd6d46.07d862","name":"OUTGOING MESSAGES TO THE WATCH","info":"","x":184.00000762939453,"y":355.8000297546387,"wires":[]},{"id":"f8900c11.a7614","type":"change","z":"38fd6d46.07d862","name":"IWBP02# ","rules":[{"t":"set","p":"payload","pt":"msg","to":"IWBP02# ","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":97.00000762939453,"y":428.80000591278076,"wires":[["2817006d.81197"]]},{"id":"2817006d.81197","type":"debug","z":"38fd6d46.07d862","name":"outgoing debug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":864.3000106811523,"y":354.2000045776367,"wires":[]},{"id":"21466e3.35e1792","type":"change","z":"38fd6d46.07d862","name":"IWBP02 LBS ADDRESS","rules":[{"t":"set","p":"payload","pt":"msg","to":"ADDRESS NEEDED","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":152.00000762939453,"y":492.0000057220459,"wires":[["2817006d.81197"]]},{"id":"9cd8efdf.edd82","type":"inject","z":"38fd6d46.07d862","name":"TEST IWAP02_ADDRESS","topic":"","payload":"IWAP02,zh_cn,1,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65#","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":143,"y":211.00000381469727,"wires":[["b13eed31.409e9"]]},{"id":"97b7209d.3d45","type":"function","z":"38fd6d46.07d862","name":"AP02 split flag 0/1","func":"// flag = 0 \n//IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7#\n// flag = 1\n// IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65#\nlet answer = {} \nmsg.payload = msg.payload.replace(/#$/, \"\");       // remove trailing #\nlet elements = msg.payload.split(\",\")              // this gives an array containing the bits\nanswer.command = elements[0]                       // IWAP02\nanswer.languageNotice = elements[1]                // zh_cn\nanswer.flag = elements[2]                          // 0\nnode.warn(`flag is: ${answer.flag}`)\n// switching answer if flag is 0/1\nanswer.baseCount = Number(elements[3])             // 7\n// you can work out how to put the node.warn statements in yourself\nanswer.mcc = elements[4]                           // 460\nanswer.mnc = elements[5]                           // 0\n// now need to get the bases\nlet i;\nanswer.basesGSM = []\nfor (i=6; i<6+answer.baseCount; i++) {\n  let baseElements = elements[i].split(\"|\")\n  answer.basesGSM.push({lac: baseElements[0], cid: baseElements[1], dbm: baseElements[2]})  // 9520|3671|10\n}\n// now need to get the bases\nlet e;\nanswer.basesWIFI = []\nfor (e=7; e<6+answer.basesGSM; i++) {\n  let baseElements = elements[e].split(\"&\")\n  answer.basesWIFI.push({ssid: baseElements[0], macAddres: baseElements[1], signal: baseElements[2]})  // 4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65\n}\nmsg.payload = answer\nreturn msg\n","outputs":1,"noerr":0,"x":614.3000106811523,"y":144.20001411437988,"wires":[["4abce473.7edcfc"]]},{"id":"343e90e6.de5b1","type":"debug","z":"38fd6d46.07d862","name":"incoming debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":863.0000076293945,"y":267.00000381469727,"wires":[]},{"id":"4abce473.7edcfc","type":"switch","z":"38fd6d46.07d862","name":"Answer option","property":"payload.flag","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":603.3000106811523,"y":187.40001392364502,"wires":[["f8900c11.a7614","343e90e6.de5b1"],["21466e3.35e1792","343e90e6.de5b1"]]},{"id":"8f5bfaf1.3b9f48","type":"function","z":"38fd6d46.07d862","name":"Colin - AP02 split flag 0/1","func":"// flag = 0 \n//IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7#\n// flag = 1\n// IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65#\nlet answer = {}  \nmsg.payload = msg.payload.replace(/#$/, \"\");       // remove trailing #\nlet elements = msg.payload.split(\",\")              // this gives an array containing the bits\nanswer.command = elements[0]                       // IWAP02\nanswer.languageNotice = elements[1]                // zh_cn\nanswer.flag = elements[2]                          // 0\nnode.warn(`flag is: ${answer.flag}`)\n// switching answer if flag is 0/1\nanswer.baseCount = Number(elements[3])             // 7\n// you can work out how to put the node.warn statements in yourself\nanswer.mcc = elements[4]                           // 460\nanswer.mnc = elements[5]                           // 0\n// now need to get the bases\nlet i;\nanswer.basesGSM = []\nfor (i=6; i<6+answer.baseCount; i++) {\n  let baseElements = elements[i].split(\"|\")\n  answer.basesGSM.push({lac: baseElements[0], cid: baseElements[1], dbm: baseElements[2]})  // 9520|3671|10\n}\n// the rest needs to go in here\nmsg.payload = answer\nreturn msg\n","outputs":1,"noerr":0,"x":637.0000534057617,"y":79,"wires":[[]]}]

I won't be online tomorrow. I'm going to take a lesson for WIFI positionning system (fingerprinting datas) and LBS tracking. I hope to come on tuesday with the solution for missing parts here.

The system is working like this :
in LBS or WIFI tracking algorithm, the datas sent by the watch have to be converted by a special request made on the web and probablly sent back in a worldmap node with an API... So when the GPS can't send the watch position as the device can't be reachable inside a building or when there are big clouds or storms, the WIFI positioning system (WIFI triangulation) will take this operation in charge... and when GPS or WIFI tracking are not able to send a position, the LBS (telecoms positioning system triangulation) will solve this.
So for the the IWAP01, it is a full position coordinates sent together as : GPS+WIFI+LBS+STATUS bases... And for IWAP02 : only the LBS+WIFI tracking sytem are operating... Complicate but really efficient :slight_smile:

Try this. You weren't far off, as I said the way they have organised the data is horrible.

[{"id":"f257dfbd.c86b68","type":"function","z":"1da18bb0.e9336c","name":"AP02 split flag 0/1","func":"// flag = 0 \n//IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7#\n// flag = 1\n// IWAP02,zh_cn,0,7,460,0,9520|3671|13,9520|3672|12,9520|3673|11,9520|3674|10,9520|3675|9,9520|3676|8,9520|3677|7,4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65#\nlet answer = {} \nmsg.payload = msg.payload.replace(/#$/, \"\");       // remove trailing #\nlet elements = msg.payload.split(\",\")              // this gives an array containing the bits\nanswer.command = elements[0]                       // IWAP02\nanswer.languageNotice = elements[1]                // zh_cn\nanswer.flag = elements[2]                          // 0\n// switching answer if flag is 0/1\nanswer.baseCount = Number(elements[3])             // 7\n// you can work out how to put the node.warn statements in yourself\nanswer.mcc = elements[4]                           // 460\nanswer.mnc = elements[5]                           // 0\n// now need to get the bases\nlet i;\nanswer.basesGSM = []\nfor (i=6; i<6+answer.baseCount; i++) {\n  let baseElements = elements[i].split(\"|\")\n  answer.basesGSM.push({lac: baseElements[0], cid: baseElements[1], dbm: baseElements[2]})  // 9520|3671|10\n}\n// are there any WIFI bases?\nanswer.baseCountWIFI = Number(elements[i] || 0)  // this will be zero if there aren't any\nanswer.basesWIFI = []\nif (answer.baseCountWIFI > 0) {\n    i = i+1                 // move on to wifi bases\n    let basesWIFIStrings = elements[i].split(\"&\")\n    let j;\n    for (j=0; j<basesWIFIStrings.length; j++) {\n        let baseElements = basesWIFIStrings[j].split(\"|\")\n        answer.basesWIFI.push({ssid: baseElements[0], macAddres: baseElements[1], signal: baseElements[2]})  // 4,1|D8-24-BD-79-FA-1F|59&2|3C-46-D8-6D-CE-01|81&3|0C-4C-39-1A-7C-65|69&4|70-A8-E3-5D-D7-C0|65\n    }\n    // adjust baseCountWIFI just in case the number actually there didn't match that expexted\n    answer.baseCountWIFI = answer.basesWIFI.length\n}\n\nmsg.payload = answer\nreturn msg\n","outputs":1,"noerr":0,"x":614.3000106811523,"y":144.20001411437988,"wires":[["2a24640f.4d9ebc"]]}]

You did it perfect! Thanks!

Colin,
if you get time tomorrow... should it possible to solve request for IWAP01? I've tried but here there are 2 additional criterias : | and & ... only if V is transmited and/or longitude = 0 and/or latitude = 0
But you wrote in your code that if (answer.valid) { is not A .. then the result is latitude = 0 and longitude = 0
I think this is not true... cause we need to split if any one of this 3 conditions is filled :

Spliting these infos are necessary :

  • speed is missing as after 2232.9806N11404.9355E 000.1 is the speed in km/h (necessary to calculate a fall)
  • 061830 = GMT 06:18:30 (necessary to get the trace of event as date is already in your code with hour but i cant' undertstand the form => date: 2019-02-14T22:00:00.000Z)
  • 323.87 = direction angle is 323.87° (necessary to calculate a fall)

For the necessary LBS datas to collect :
060 is GSM signal,
009 is the number of satellites,
080 is battery level,
0 is remaining space,
01 is fortification state,
02 is working mode, (it shows none setting if fortification and working mode
are 00)
460 is mcc,
0 is mnc,
9520 is lac
3671 is cid

  • we will have to split additional infos for Home|74-DE-2B-44-88-8C|97& Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97& Home3|74-DE-2B-44-88-8C|97
    as Home|74-DE-2B-44-88-8C|97 : one set of WIFI information,Home is SSID, 74-DE-2B-44-88-8C is MAC
    address,97 is signal strength,variables are separated by“|”,wifi information can be multiple sets
    and are separated by “&”.

Here is your code for this function node :

// flag A
//IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#
// flag V
//IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&Home1|74-DE-2B-44-88-8C|97&Home2|74-DE-2B-44-88-8C|97&Home3|74-DE-2B-44-88-8C|97# **
let answer = {}
let elements = msg.payload.split(",") // this gives an array containing the bits
// elements[0] is the long string starting IWAP01
let dateStr = elements[0].substr(6,6) // eg "190215" 15th Feb 2019
answer.date = new Date(Number(dateStr.substr(0,2))+2000, Number(dateStr.substr(2,2))-1, dateStr.substr(4,2)) // 080524
answer.valid = (elements[0].substr(12,1) === "A") // true or false - A or V
if (answer.valid) {
** let degreesN = Number(elements[0].substr(13,2))

** let minutesN = Number(elements[0].substr(15,7))**
** let ns = elements[0].substr(22,1) // N or S**
** let degreesE = Number(elements[0].substr(23,3))**
** let minutesE = Number(elements[0].substr(26,7))**
** let ew = elements[0].substr(33,1) // E or W**
** node.warn(${degreesN} ${minutesN} ${ns} ${degreesE} ${minutesE} ${ew})**
** answer.latitude = degreesN + minutesN/60 // 2232.9806N**
** if (ns === "S") answer.latitude = -answer.latitude**
** answer.longitude = degreesE + minutesE/60**
** if (ew === "W") answer.longitude = -answer.longitude // 11404.9355E**
} else {
** answer.latitude = 0**
** answer.longitude = 0**
}

msg.payload = answer
return msg

How can it be that a longitude or latitude of 0 indicates not valid? Does that mean it does not work if on the Meridian or the Equator?

I saw this problem with the watch inside a software like Tracar. The watch is recognized but the map displays the device at long. = 0, lat. = 0 as the IWAP01 package is never transmitted. This is certainly the reason the watch has an additional IWAP02 package, only sending separate LBS and WIFI coordinates...