# Splitting text string into array

**URL:** <https://discourse.nodered.org/t/splitting-text-string-into-array/18025>\
**Category:** General\
**Created:** [15 November 2019 22:30 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025 "2019-11-15T22:30:50Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![aidan](https://avatars.discourse-cdn.com/v4/letter/a/c5a1d2/32.png) [@aidan](https://discourse.nodered.org/u/aidan)\
**Post date:** [15 November 2019 22:30 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/1 "2019-11-15T22:30:51Z")

</div>

I need to split parts of a fixed length string of serial GPS data into an array by vehicle ID (bold in example below). Chrs 4,5 are degs Lat, 6,7 mins...and so on...

I have 18 different values in the string, (some are just flags) and 100 vehicle ID's

> **0310** 53232928001261244220023WNGN27S01003000000000003

I do know that I can do this with a function node and slice() - but the coding is beyond me despite reading through examples.

Once I have the data sorted I can manipulate it and present on NodeRed dash-board or even populate a map.. 🙂

Hope someone can assist.

---

<div class="post-metadata">

**Author:** ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)\
**Post date:** [16 November 2019 05:34 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/2 "2019-11-16T05:34:14Z")

</div>

To give you a hint for a function node, inject your string into this node:

```auto
let m = msg.payload

let vid = m.substr(0,4)
let lat = m.substr(4,2);
let mins = m.substr(6,2)
//etc...
return {payload:{vehicleid:vid,lat:lat,mins:mins}}

```

In this case `substr` takes arguments: `start position, number of characters`, with a zero based index (ie. start position of character minus 1).

Output example:

```auto
{"vehicleid":"0310","lat":"53","mins":"23"}

```

---

<div class="post-metadata">

**Author:** ![aidan](https://avatars.discourse-cdn.com/v4/letter/a/c5a1d2/32.png) [@aidan](https://discourse.nodered.org/u/aidan)\
**Post date:** [16 November 2019 08:37 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/3 "2019-11-16T08:37:12Z")

</div>

That is straight-forward - I need to understand how to manupulate the output into an array, and overwrite stale data but first I will help myself and then if stuck ask again.

---

<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:** [16 November 2019 08:42 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/4 "2019-11-16T08:42:53Z")

</div>

No. At that point it is then already parsed. Just need to turn degrees and minutes into decimal degrees ready for map

---

<div class="post-metadata">

**Author:** ![aidan](https://avatars.discourse-cdn.com/v4/letter/a/c5a1d2/32.png) [@aidan](https://discourse.nodered.org/u/aidan)\
**Post date:** [16 November 2019 16:30 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/5 "2019-11-16T16:30:40Z")

</div>

I should explain a bit more. This is about trams. GPS data is transmitted over a private radio system and then passed onto operator and passenger stop display systems which acceptcurrent format it 'as is'. I have the job of re engineering the radios and new ones will use a slightly different gps protocol presented on a separate serial port. So task is to read both streams of location data in and then back out in the original protocol to give a seamless customer experience. The radios will swapped over a period of months. I have the job of doing everything...I have ideas and a node red UI showing Gps status during the transition will be very useful. Mapping is actually not really needed.  
Hope that is clear

---

<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:** [16 November 2019 16:45 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/6 "2019-11-16T16:45:49Z")

</div>

Sounds like a good project - hopefully you can share some details once done (or photos etc). But yes - if you use node-red-contrib-web-worldmap node(s) - you just need a name lat and long property and it'll start working... so should only take about 10 mins 🙂

If you can share what the other fields are I'm sure someone would help.  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/e/ec099ce5185a053587893a415a101a5fb869e023.jpeg)

Here's the flow for that

```auto
[{"id":"953664c0.4a4b38","type":"inject","z":"bac0960.1c51468","name":"","topic":"","payload":"031053232928001261244220023WNGN27S01003000000000003","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":120,"wires":[["14f3cdd2.8266b2","6cb16a68.8a48f4"]]},{"id":"b8d9b24c.ce47d","type":"debug","z":"bac0960.1c51468","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":470,"y":180,"wires":[]},{"id":"44e1acd2.d7f844","type":"worldmap","z":"bac0960.1c51468","name":"","lat":"","lon":"","zoom":"","layer":"","cluster":"","maxage":"","usermenu":"show","layers":"show","panit":"true","panlock":"false","zoomlock":"false","hiderightclick":"false","coords":"none","showgrid":"false","path":"/worldmap","x":460,"y":120,"wires":[]},{"id":"14f3cdd2.8266b2","type":"function","z":"bac0960.1c51468","name":"","func":"\n//0310 53 23 2928 001 26 1244 220023 WNGN27S01003000000000003\n\nlet m = msg.payload\n\nlet name = m.substr(0,4)\n\nlet lat = m.substr(4,2)\nlet ma = m.substr(6,2)\nlet sa = m.substr(8,4)\n\nlet lon = m.substr(12,3)\nlet mo = m.substr(15,2)\nlet so = m.substr(17,4)\n\nlet hr = m.substr(21,2)\nlet mn = m.substr(23,2)\nlet se = m.substr(25,2)\n\nlet e = (m.substr(27,1) === \"E\") ? 1 : -1\nlet n = (m.substr(28,1) === \"N\") ? 1 : -1\n\nlat = (lat*1 + ma/60 + sa/360000) * n\nlon = (lon*1 + mo/60 + so/360000) * e\n\nlet icon = \"bus\";\n\nlet time = hr+\":\"+mn+\":\"+se\n\nreturn {payload:{name:name,lat:lat,lon:lon,time:time,icon:icon}}\n","outputs":1,"noerr":0,"x":270,"y":120,"wires":[["b8d9b24c.ce47d","44e1acd2.d7f844"]]}]

```

---

<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:** [16 November 2019 17:20 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/7 "2019-11-16T17:20:09Z")

</div>

For the actual project I would probably use the node-red-contrib-binary node as that can be configured to slice up things - but once set - will also work the other way - so could help with the recombine as well. The syntax is a bit weird so is harder to get your head around than the simple function, but again happy to help.

---

<div class="post-metadata">

**Author:** ![aidan](https://avatars.discourse-cdn.com/v4/letter/a/c5a1d2/32.png) [@aidan](https://discourse.nodered.org/u/aidan)\
**Post date:** [17 November 2019 20:37 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/8 "2019-11-17T20:37:46Z")

</div>

dceejay,

Great work with my example data. I am much encouraged and spending this evening adding to it

---

<div class="post-metadata">

**Author:** ![aidan](https://avatars.discourse-cdn.com/v4/letter/a/c5a1d2/32.png) [@aidan](https://discourse.nodered.org/u/aidan)\
**Post date:** [6 December 2019 18:53 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/9 "2019-12-06T18:53:50Z")

</div>

I am after some help having become a bit stuck with my array, understanding how to define and then push data into it. - actually just looking at it again I'm doing daft things subtracting numbers from strings..

```auto
var i = 0;
var sieArr= 0
var cityArr= 0
//Read into two dimensional array:
// Tram id's 301-327 and 501-507
// [id,gpsdatastring,timestamp,newdataFlg]

if (sieArr === 0);{
   for (i = 1; i < 27; i++){
       sieArr [i] = [(i+300),"NoGPS","NoTime",false];
   }  
}

// IF var CityArr does not exist create array id 501-507
if (cityArr === 0);{
      for (i = 1; i < 8; i++){
       cityArr [i] = [(i+500),"NoGPS","NoTime",false];
   }  
}

//parse incoming string for ID:
//0310 53 23 2928 001 26 1244 220023 WNGN27S01003000000000003

let m = msg.payload

let ident = m.substr(1,4)
//source radio ident

let time = m.substr(22,6)
// HHmmss

//Push data into array
if (ident <400){
    sieArr [ident-300] =[ident,msg.payload,time,true]
}
else { 
    cityArr [ident-500] = [ident,msg.payload,time,true]
}
//readout data into tables
//var tableSie = {payload:{identname:name,lat:lat,lon:lon,speed:speed,bearing:bearing,time:time}};
return [sieArr,cityArr];

```

Flow below is my hack-space. If anyone would like to look at live data PM me for the URL.

[TramNode.txt](https://discourse.nodered.org/uploads/short-url/bNpzkgjvBgY4zKtFr9IlqmRKjPx.txt) (11.4 KB)

---

<div class="post-metadata">

**Author:** ![aidan](https://avatars.discourse-cdn.com/v4/letter/a/c5a1d2/32.png) [@aidan](https://discourse.nodered.org/u/aidan)\
**Post date:** [8 December 2019 17:52 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/10 "2019-12-08T17:52:22Z")

</div>

Thanks to dceejay for helping me with this off line. With guidance I am now using context and the array node is sort-of-working, but incoming data overwrites the array, also the array is being re-initialized every few seconds, have spend a few hours wondering why - anyone with ideas please?

Here is my function node:

```auto
var i;
var l;
var m;
var length;

// Load arrays from context or start with blank one.

siemArr = context.seimArr || [];
cityArr = context.cityArr || [];

//Read into two dimensional array:
// Tram id's 301-327 and 501-507
// [id,gpsdatastring,timestamp,newdataFlg]

// If sieArr is empty create array id 301-326
if (siemArr[1[0]] !== 301) {
    for (i = 1; i < 27; i++) {
        siemArr[i] = [(i+300),"NoGPS","NoTime",false];
    }  
}

// If var cityArr is empty create array id 501-507
if (cityArr[1[0]] !== 501) {
    for (i = 1; i < 8; i++) {
        cityArr[i] = [(i+500),"NoGPS","NoTime",false];
    }  
}

//parse incoming string for ID:
//M0310 53 23 2928 001 26 1244 220023 WNGN27S01003000000000003

m = msg.payload;
length = msg.payload.length // 52
prefix = m.substr(0,1) // M
good = m.substr(30,1) // G

//sanity checking for valid data 
if (length == 52 && prefix == "M" && good == "G"){
   //source radio ident
   let ident = Number(m.substr(2,3));
   let time = m.substr(22,6)
   // HHmmss

   //Push data into array
   if (ident >= 301 && ident <= 327 ){
       siemArr[ident-301] = [ident,msg.payload,time,true]
    }
   if (ident >= 501 && ident <= 507 ){
       cityArr[ident-501] = [ident,msg.payload,time,true]
    }
}
//readout data into tables
//var tableSie = {payload:{identname:name,lat:lat,lon:lon,speed:speed,bearing:bearing,time:time}};
//var tableSie = {payload:{identname:name,lat:lat,lon:lon,speed:speed,bearing:bearing,time:time}};

// Save the arrays back to context ready for next time
context.siemArr = siemArr;
context.cityArr = cityArr;
return [{payload:context.siemArr},{payload:context.cityArr}];

```

Output to table

```auto
<table id="table" border="1">
 <tr>
 <th>Ident</th> 
 <th>GPSdata</th>
 <th>Time</th>
  <th>New</th>
 </tr>
 <tbody>
 <tr ng-repeat="row in msg.payload">
 <td ng-repeat="item in row" >{{item}}</td>
 </tr>
 </tbody>
</table>

```

---

<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:** [8 December 2019 19:31 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/11 "2019-12-08T19:31:46Z")

</div>

> [@aidan](#):
>
> if (siemArr[1[0]] !== 301) {

Why not only initialise it if the length is 0 - `if (siemArr.length === 0)...` ?  
It should not re-initialise unless it is being reset somewhere.

Is the point of this to create a table for the ui ? I thought the rest of your flow that included that map already did that ?

Not sure what you mean by the data overwriting... I thought that was the point - so that each tram index was updated to the latest every time ?

---

<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:** [8 December 2019 20:12 UTC](https://discourse.nodered.org/t/splitting-text-string-into-array/18025/12 "2019-12-08T20:12:43Z")

</div>

there may have been a spelling mistake in my previous attempt... an seiArr vs sieArr 🙂  
I can feed it direct into a ui-table node no problem ...

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/2X/d/d76df43b416d74978ab2265178c0002e2d8d99f4.png)
