# Extracting from a string that can change

**URL:** <https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863>\
**Category:** General\
**Created:** [8 December 2021 10:05 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863 "2021-12-08T10:05:12Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![dougle03](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dougle03/32/32979_2.png) [@dougle03](https://discourse.nodered.org/u/dougle03)\
**Post date:** [8 December 2021 10:05 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/1 "2021-12-08T10:05:13Z")

</div>

Morning all, got a little problem that's stumpted me.  
I get an SMS message from an RV HVAC system that bears several metrics in a single string. I've used a change node with regex strings to extract the variables, however they can change resulting in the regex grabbing shifted parts of the message.  
Any ideas on how to solve this?

This is what comes in: Note that OFF (3 characters) could be ON (2 characters) plus the values will be shorter when the temp goes below 10  
`Hello user, living area battery: 13.3V, 230V: ON, timer: OFF, indoor temp.: 21C, water temp.: 55C. Regards, your iNet Box`  
I have this in my change node:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/3/330d3b6dc85d4521a7dae09c16a61331e252d442.png)

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [8 December 2021 10:59 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/2 "2021-12-08T10:59:41Z")

</div>

Hi Dougle,

.. played around a bit with Javascript

```auto
[{"id":"28620f4a3b7eac27","type":"inject","z":"54efb553244c241f","name":"data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello user, living area battery: 13.3V, 230V: ON, timer: OFF, indoor temp.: 21C, water temp.: 55C. Regards, your iNet Box","payloadType":"str","x":280,"y":1000,"wires":[["e50f7462a65217b2","971950a0069ec9b0"]]},{"id":"e50f7462a65217b2","type":"function","z":"54efb553244c241f","name":"","func":"\nlet sms = msg.payload;\n\nsms = sms.slice(24)\nsms = sms.slice(0, -24)\nsms = sms.split(\", \")\n\n//node.warn(sms);\n\nlet obj = {}\n\nsms.forEach(el => {\n obj[el.split(\":\")[0]] = el.split(\":\")[1].trim()\n})\n\nmsg.payload = obj\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":1000,"wires":[["c029a22bbb8fcd96"]]},{"id":"c029a22bbb8fcd96","type":"debug","z":"54efb553244c241f","name":"2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":1000,"wires":[]},{"id":"971950a0069ec9b0","type":"debug","z":"54efb553244c241f","name":"1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":400,"y":900,"wires":[]}]

```

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/0/80ee6398d51782a8a1064a91d67cc876202b04ef.png)

---

<div class="post-metadata">

**Author:** ![dougle03](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dougle03/32/32979_2.png) [@dougle03](https://discourse.nodered.org/u/dougle03)\
**Post date:** [8 December 2021 11:03 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/3 "2021-12-08T11:03:15Z")

</div>

Hi,  
That is impressive, I wish I knew how it works. It does by the way. I changed ON/OFF and reduced value to change the chr count.. Still works. Amazing. Thanks very much. Now I need to try and understand the code a little.. 😄

EDIT: Looks like you went of the commas perhaps?

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [8 December 2021 11:07 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/4 "2021-12-08T11:07:07Z")

</div>

> [@dougle03](#):
>
> Looks like you went of the commas perhaps

yes exactly ... once i sliced off the text at the beginning and the end i saw the pattern of commas , and then another split based on colons `:` to construct the object

---

<div class="post-metadata">

**Author:** ![dougle03](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dougle03/32/32979_2.png) [@dougle03](https://discourse.nodered.org/u/dougle03)\
**Post date:** [8 December 2021 11:10 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/5 "2021-12-08T11:10:33Z")

</div>

Very clever; now, If I can just turn the numbers in to int's rather than strings I'll be home free.. lol

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [8 December 2021 11:16 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/6 "2021-12-08T11:16:32Z")

</div>

> [@dougle03](#):
>
> turn the numbers in to int's rather than strings

hmm .. thats going to be a challenge because its not as simple as slicing off one character from the end of, lets say 13.3V to remove the V because doing that programmatically would also remove a character from ON and OFF.

so maybe we have to check what's the last character and if its a V or a C then slice it

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [8 December 2021 11:27 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/7 "2021-12-08T11:27:49Z")

</div>

Catch 😉

needs some testing ...

```auto
[{"id":"28620f4a3b7eac27","type":"inject","z":"54efb553244c241f","name":"data","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello user, living area battery: 13.3V, 230V: ON, timer: OFF, indoor temp.: 21C, water temp.: 55C. Regards, your iNet Box","payloadType":"str","x":280,"y":1000,"wires":[["e50f7462a65217b2","971950a0069ec9b0"]]},{"id":"e50f7462a65217b2","type":"function","z":"54efb553244c241f","name":"","func":"\nlet sms = msg.payload;\n\nsms = sms.slice(24)\nsms = sms.slice(0, -24)\nsms = sms.split(\", \")\n\n//node.warn(sms);\n\nlet obj = {}\n\nsms.forEach(el => {\n\n let key = el.split(\":\")[0]\n let value = el.split(\":\")[1].trim().replace(\"V\", \"\").replace(\"C\", \"\")\n\n obj[key] = !isNaN(value) ? Number(value) : value\n})\n\nmsg.payload = obj\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":1000,"wires":[["c029a22bbb8fcd96"]]},{"id":"c029a22bbb8fcd96","type":"debug","z":"54efb553244c241f","name":"2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":1000,"wires":[]},{"id":"971950a0069ec9b0","type":"debug","z":"54efb553244c241f","name":"1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":400,"y":900,"wires":[]}]

```

---

<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 2021 11:28 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/8 "2021-12-08T11:28:10Z")

</div>

a parseInt inside a try catch should handle it (or parseFloat) - as they tend to work with strings starting with numbers.

---

<div class="post-metadata">

**Author:** ![dougle03](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dougle03/32/32979_2.png) [@dougle03](https://discourse.nodered.org/u/dougle03)\
**Post date:** [8 December 2021 12:32 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/9 "2021-12-08T12:32:50Z")

</div>

Thanks, however Andy's code that works really well is beyond my level of competence and thus playing with it is a bit beyond me. Perhaps I can pull the values out into change nodes to convert them?

---

<div class="post-metadata">

**Author:** ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)\
**Post date:** [8 December 2021 13:33 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/10 "2021-12-08T13:33:57Z")

</div>

Whenever the data is in a semi-structured string, like yours is, I reach for a regex to pull out only the data I need, and leave the rest behind:

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

I know regexes are not for everyone, but for your data, this expression:

```
/(\w[\w .]+): ([\d.]+)?(\w+)/

```

seems to capture the right bits (_edit: added a '.' to the metric capture group_):

```auto
[
    [
        "living area battery",
        "13.3",
        "V"
    ],
    [
        "230V",
        null,
        "ON"
    ],
    [
        "timer",
        null,
        "OFF"
    ],
    [
        "indoor temp.",
        "21",
        "C"
    [,
    [
        "water temp.",
        "55",
        "C"
    ]
]

```

I used this JSONata expression in a `change` node to rearrange the matched groups into an object with named metric fields:

```auto
payload.$match(/(\w[\w .]+): ([\d.]+)?(\w+)/).[groups] {
    $[0]: {
        "value": $count($) = 3 ? $number($[1]) : $[1],
        "units": $count($) = 3 ? $[2]
    }
}

```

Here is the json for the `change` node that I used, in case you want to try it out.

> **change.json**
>
> ```auto
> [
> {
> "id": "944ceeae5a30108f",
> "type": "change",
> "z": "41b4ec2d69b148dd",
> "name": "HVAC parsing",
> "rules": [
> {
> "t": "set",
> "p": "payload",
> "pt": "msg",
> "to": "payload.$match(/(\\w[\\w .]+): ([\\d.]+)?(\\w+)/).[groups] {\t $[0]: {\t \"value\": $count($) = 3 ? $number($[1]) : $[1],\t \"units\": $count($) = 3 ? $[2]\t }\t}",
> "tot": "jsonata"
> }
> ],
> "action": "",
> "property": "",
> "from": "",
> "to": "",
> "reg": false,
> "x": 350,
> "y": 660,
> "wires": [
> []
> ]
> }
> ]
> 
> ```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [22 December 2021 13:34 UTC](https://discourse.nodered.org/t/extracting-from-a-string-that-can-change/54863/11 "2021-12-22T13:34:44Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
