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

**URL:** <https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691>\
**Category:** General\
**Created:** [7 February 2019 07:41 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691 "2019-02-07T07:41:14Z")\
**Posts on this page:** 20\
**Page:** 5

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [15 February 2019 10:20 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/81 "2019-02-15T10:20:53Z")

</div>

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

```auto
[{"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":[]}]

```

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 11:07 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/82 "2019-02-15T11:07:21Z")

</div>

Thanks... I will try it.

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 11:28 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/83 "2019-02-15T11:28:42Z")

</div>

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...

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [15 February 2019 11:35 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/84 "2019-02-15T11:35:01Z")

</div>

> [@jycemea](#):
>
> Is it possible to find a solution for LBS and WiFi base locating When needed?

Where is that information?

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [15 February 2019 12:27 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/85 "2019-02-15T12:27:53Z")

</div>

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

```auto
[{"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":[]}]

```

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 12:53 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/86 "2019-02-15T12:53:46Z")

</div>

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...

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 13:09 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/87 "2019-02-15T13:09:43Z")

</div>

**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...

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 13:16 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/88 "2019-02-15T13:16:26Z")

</div>

> [@Colin](#):
>
> ```auto
> [{"id":"cf907e47.07511","type":"inject","z":"bae6d5e2.bea09","name":"Invalid IWAP01","topic":"","payload":"IWAP01190215V0000.0000N00000.0000E000.1061830323.8706000908000102,460,0,9520,3671,Home|74-DE-2B-44-88-8C|97&amp;Home1|74-DE-2B-44-88-8C|97&amp;Home2|74-DE-2B-44-88-8C|97&amp;Home3|74-DE-2B-44-88-8C|97#","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":124.5,"y":221,"wires":[["4ecc3207.8feb4c"]]},{"id":"4ecc3207.8feb4c","type":"function","z":"bae6d5e2.bea09","name":"Split IWAP01","func":"let answer = {}\nlet elements = msg.payload.split(\",\") // this gives an array containing the bits\n// elements[0] is the long string starting IWAP01\nlet dateStr = elements[0].substr(6,6) // eg \"190215\" 15th Feb 2019\nanswer.date = new Date(Number(dateStr.substr(0,2))+2000, Number(dateStr.substr(2,2))-1, dateStr.substr(4,2))\nanswer.valid = (elements[0].substr(12,1) === \"A\") // true or false\nif (answer.valid) {\n let degreesN = Number(elements[0].substr(13,2))\n let minutesN = Number(elements[0].substr(15,7))\n let ns = elements[0].substr(22,1) // N or S\n let degreesE = Number(elements[0].substr(23,3))\n let minutesE = Number(elements[0].substr(26,7))\n let ew = elements[0].substr(33,1) // E or W\n node.warn(`${degreesN} ${minutesN} ${ns} ${degreesE} ${minutesE} ${ew}`)\n answer.latitude = degreesN + minutesN/60\n if (ns === \"S\") answer.latitude = -answer.latitude\n answer.longitude = degreesE + minutesE/60\n if (ew === \"W\") answer.longitude = -answer.longitude\n} else {\n answer.latitude = 0\n answer.longitude = 0\n}\n\nmsg.payload = answer\nreturn msg","outputs":1,"noerr":0,"x":310.5,"y":162,"wires":[["c5195512.cf66e"]]},{"id":"c5195512.cf66e","type":"debug","z":"bae6d5e2.bea09","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":489.5,"y":161,"wires":[]},{"id":"9d29ac9c.9ba0f","type":"inject","z":"bae6d5e2.bea09","name":"Valid IWAP01","topic":"","payload":"IWAP01190215A2232.9806N11404.9355E000.1061830323.8706000908000102,460,0,9520,3671#","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":116,"y":124,"wires":[["4ecc3207.8feb4c"]]}]
> 
> ```

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

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 13:41 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/89 "2019-02-15T13:41:24Z")

</div>

Here they are talking about this...

 ![Watch%20Communication%20Protocol_Page_1](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/0/0aeb8aa04c7b044bdee3c2aa1d70425e9f4d4d9e.png) ![Watch%20Communication%20Protocol_Page_2](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/b/b9ac6791a9a64a1542fe3a90485977de05d1c51c.png) ![Watch%20Communication%20Protocol_Page_3](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/2/2b43882c9dde7063572b1324013532138923afff.png)

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 16:57 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/90 "2019-02-15T16:57:24Z")

</div>

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 ?

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [15 February 2019 17:00 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/91 "2019-02-15T17:00:18Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [16 February 2019 09:50 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/92 "2019-02-16T09:50:41Z")

</div>

> [@jycemea](#):
>
> If it flag = 0 then the last object is including **#** (If flag = 1 no problem)... How can I exclude this ?

I don't understand what you mean, if I click on the 'Invalid' inject I just get  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/b/b2b8aee2394a0c01407f303dd429f459fbeb8e9a.png)

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [17 February 2019 08:39 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/93 "2019-02-17T08:39:11Z")

</div>

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

Here are the png. Issue happens when flag = 0

 ![IWAP02_flag0_%23](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/1/118dbf90adddbc416bc40dd7083a385c5a37e7a6.png)

When flag = 1, no issue...

 ![IWAP02_flag1_%23](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/a/a2b0eadfcb4ed0554c312c37458f9c3b1e8b9233.png)

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 😄 :

// 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

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [17 February 2019 09:00 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/94 "2019-02-17T09:00:21Z")

</div>

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

```auto
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.

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [17 February 2019 09:32 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/95 "2019-02-17T09:32:19Z")

</div>

> [@Colin](#):
>
> msg.payload = msg.payload.replace(/#$/, ""); // remove trailing #

Nice ! Solved. Thanks.

Here are the datas :

```auto
[{"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 🙂

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [17 February 2019 10:14 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/96 "2019-02-17T10:14:40Z")

</div>

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

```auto
[{"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"]]}]

```

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [17 February 2019 11:55 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/97 "2019-02-17T11:55:39Z")

</div>

You did it perfect! Thanks!

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [17 February 2019 15:56 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/98 "2019-02-17T15:56:24Z")

</div>

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.000 **Z** )
- 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](https://IWAP01080524A2232.9806N11404.9355E000.1061830323.8706000908000102),460,0,9520,3671#**  
**// flag V**  
**[//IWAP01080524V0000.0000N00000.0000E000.1061830323.8706000908000102](https://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**

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [17 February 2019 22:02 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/99 "2019-02-17T22:02:04Z")

</div>

> [@jycemea](#):
>
> only if V is transmited and/or longitude = 0 and/or latitude = 0

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?

---

<div class="post-metadata">

**Author:** ![jycemea](https://avatars.discourse-cdn.com/v4/letter/j/f475e1/32.png) [@jycemea](https://discourse.nodered.org/u/jycemea)\
**Post date:** [18 February 2019 00:55 UTC](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691/100 "2019-02-18T00:55:17Z")

</div>

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...

[Previous page](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691.md?page=4)

[Next page](https://discourse.nodered.org/t/how-to-make-an-iot-protocol-parsing-answering/7691.md?page=6)
