# View and process Pylontech battery data

**URL:** https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657
**Category:** General
**Created:** [1 April 2022 19:17 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657 "2022-04-01T19:17:19Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [1 April 2022 19:17 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/1 "2022-04-01T19:17:19Z")

</div>

I connected today my Pylontech batteries via its console port into my Raspberry via USB. This allows me to query them via the serial node.  
Here is what the command looks like in PWR terminal emulation under Linux:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/8/1843ee7a5c7a80d9ce45b61c861d214f55ed0c4b.jpeg)

From NR, I run this same command and I get the data back fine. Now, for me begins the most difficult part.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/6/a69b5b2d5eef0b2edffed86fb50fc31583e373e7.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/6/163e235e014e966c3acc6b6c61741e6b83086cf3.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/a/eaa48edecdf9576d6b9af2b0f5a1bea1ca59be68.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/6/a68c8d663ae6e89bc9177299f2b19c4e42dfcfda.png)

I want to be able to display these values in a table, but also to be able to process each value to make further decisions according to their values.  
Could you help me to

1. create a dashboard table that will be refreshed regularly with the command
2. store each values for later use, Obviously except when the lines are empty of data

Currently I have only one rack connected, if I connect another one, there will be values in the array No4 and following if more rack.

I personally am not very comfortable with handling bulk data. So I want to get started the right way.  
And I'm not a programmer.Please be lenient.

---

<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: [2 April 2022 07:56 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/2 "2022-04-02T07:56:23Z")

</div>

The terminal output looks like tab separated data. You could use the join node to produce a string, instead of an array and try to feed that into a csv node and set the mode to tab.

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [2 April 2022 10:20 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/3 "2022-04-02T10:20:35Z")

</div>

The idea is good, I had never used this CSV node.  
I removed the first 3 lines from the top.  
It looks promising.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/6/b6ef2bc02bc80a86d8542dced077681e3cc79171.png)  
next step soon. Time to eat 🍽

---

<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: [2 April 2022 11:14 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/4 "2022-04-02T11:14:28Z")

</div>

I think you can configure the csv node to use the first line as the column names, which in turn will use them as properties names for the values (ie, instead of `col1:x`, it will become `Power:x`} ) - in addition you can set the output to 'single array', which then can be mapped to a ui-table.

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [2 April 2022 12:03 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/5 "2022-04-02T12:03:16Z")

</div>

The result is not there yet, but we are getting closer.  
The fields are not yet in the right places  
Here is the CSV setting & debug informations

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/3/53b6693ad5770bc99d4ce1dbd2748e506442488e.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/1/e13e92cc06c59389ebee52e84a486cca151d9ef0.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/5/75425a0482ed5bc6bbb7b974c49942b66ce561ef.png)  
and the result on the screen  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/6/46fb559865e741d441430a5eddae886c017d4096.png)

Is there any way to delete the last 2 rows of the matrix?  
I think I need to do some formatting before the UI\_TABLE in a Function node? Or to define each column in the Table node?  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/3/a31249a10308240c64cc53d435cbd0e78e9bdf8c.png)

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

---

<div class="post-metadata">

### Author: ![eddee54455](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/eddee54455/32/43350_2.png) [@eddee54455](https://discourse.nodered.org/u/eddee54455)
#### Post date: [2 April 2022 12:39 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/6 "2022-04-02T12:39:32Z")

</div>

Hi JL...

This is how I am doing it.... (Yeh, I know my coding isnt the best, but it works for me...)

```auto
    {
        "id": "14161f8f.5bb748",
        "type": "function",
        "z": "a8cb3b26.8b8608",
        "g": "35635e2d.56d582",
        "name": "Extract Pylon req Bat Query Data",
        "func": "if(msg.payload == \"clear\"){//clear and initialise\n context.set(\"arr\",undefined,\"file\") ;\n return null\n}\n\nvar rT = 17; // Table max #rows(1st is headings)\n cT = global.get('INVNoBattStrings','file')+1 ; // Table max #columns(was5)\n r = 0 ; // Row Counter\n c = 0 ; // Column Counter\n \nif(context.get(\"arr\",\"file\") != undefined){\n arr = context.get(\"arr\",\"file\")\n}\nelse{\n arr = [];//Doesn't exist, so create the base array\n} \n//Layout Blank Table\nfor(r = 0; r < rT; r++) { // for each of rows(1st is headings)\n if(arr [r] == undefined){//Create if it doesn't exist\n arr[r] = []\n } \n for(c = 0; c < cT; c++) { // create columns\n if(arr[r][c] == undefined){//Create if it doesn't exist\n arr[r][c] = null\n }\n } \n}\n\n//Put in Headings/Titles\narr[0][0] = \"Batt#\";//\"Power\";\narr[1][0] = \"Volt\";\narr[2][0] = \"Amps\";//\"Curr\";\narr[3][0] = \"ºC\"//\"Temp C\";//\"Tempr\";\narr[4][0] = \"SOC\";//\"Coulomb\"; \narr[5][0] = \"Tlow\";\narr[6][0] = \"Thigh\";\narr[7][0] = \"Vlow\";\narr[8][0] = \"Vhigh\";\narr[9][0] = \"Mos ºC\";//\"MosTempr\";\narr[10][0] = \"Base.St\";\narr[11][0] = \"Volt.St\";\narr[12][0] = \"Curr.St\"; \narr[13][0] = \"Temp.St\"; \narr[14][0] = \"B.V.St\";\narr[15][0] = \"B.T.St\";\narr[16][0] = \"M.T.St\";\n//arr[13][0] = \"Time\";\n\nData = msg.payload;\nBatt = \"\";\nBatt = msg.payload.substring(55,61);//Get Unique for this query\n\n//Look for trigger string\nif(Batt == \"Dischg\" || Batt == \"Charge\"||Batt == \"Idle \"){\n //Data Populate from msg.payload string\n Address = Number(msg.payload.substring(0,5));//Battery\n arr[0][Address]= Number(msg.payload.substring(0,5));//Battery\n arr[1][Address]= Number(msg.payload.substring(6,12))/1000;//Volt\n arr[2][Address]= Number(msg.payload.substring(13,19))/1000;//Curr\n arr[3][Address]= Number(msg.payload.substring(20,26))/1000;//Tempr\n arr[4][Address]= Number(msg.payload.substring(91,99).trim().replace('%', ''));//Coulomb\n arr[5][Address]= Number(msg.payload.substring(27,33))/1000;//Tlow\n arr[6][Address]= Number(msg.payload.substring(34,40))/1000;//Thigh\n arr[7][Address]= Number(msg.payload.substring(41,47))/1000;//Vlow\n arr[8][Address]= Number(msg.payload.substring(48,54))/1000;//Vhigh\n arr[9][Address]= Number(msg.payload.substring(138,146))/1000;//MosTempr\n arr[10][Address]= msg.payload.substring(55,63).trim();//Base.St\n arr[11][Address]= msg.payload.substring(64,72).trim();//Volt.St\n arr[12][Address]= msg.payload.substring(73,81).trim();//Curr.St\n arr[13][Address]= msg.payload.substring(82,90).trim();//Temp.St\n arr[14][Address]= msg.payload.substring(121,129).trim();//B.V.St\n arr[15][Address]= msg.payload.substring(130,137).trim();//B.T.St\n arr[16][Address]= msg.payload.substring(147,154).trim();//M.T.St\n //arr[][]= msg.payload.substring(100,120).trim();//Time\n context.set(\"arr\",arr,\"file\");\n for(r = 0; r < rT; r++) { // for each of rows(1st is headings)\n for(c = 0; c < cT; c++) { // for each of columns\n if(arr[r][c] == null){ // Check it's populated\n return; //Get out of here, table isnt full yet\n }\n } \n }\n //Table is populated fully - Serve it!\n msg.payload = arr;\n return msg;\n}\n\nreturn;//Not a trigger string, just leave!\n\n//Power Volt Curr Tempr Tlow Thigh Vlow Vhigh Base.St Volt.St Curr.St Temp.St Coulomb Time B.V.St B.T.St MosTempr M.T.St\n//2 49020 -4748 27500 23900 24000 3268 3268 Dischg Normal Normal Normal 36% 2021-05-20 22:32:13 Normal Normal 25600 Normal\n//1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 330,
        "y": 1020,
        "wires": [
            [
                "b9680781.24a37"
            ]
        ]
    },
    {
        "id": "b9680781.24a37",
        "type": "delay",
        "z": "a8cb3b26.8b8608",
        "g": "35635e2d.56d582",
        "name": "",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "2",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "outputs": 1,
        "x": 580,
        "y": 1020,
        "wires": [
            [
                "a1639b7e.8df1a8"
            ]
        ]
    },
    {
        "id": "a1639b7e.8df1a8",
        "type": "ui_table",
        "z": "a8cb3b26.8b8608",
        "g": "35635e2d.56d582",
        "group": "78ad4256.fda3d4",
        "name": "Batt Basic Info",
        "order": 2,
        "width": 7,
        "height": 10,
        "columns": [],
        "outputs": 0,
        "cts": false,
        "x": 770,
        "y": 1020,
        "wires": []
    },
    {
        "id": "2365c560.586fa2",
        "type": "link in",
        "z": "a8cb3b26.8b8608",
        "g": "35635e2d.56d582",
        "name": "",
        "links": [
            "a210e66a.672038",
            "166e9d46.bfd18b"
        ],
        "x": 155,
        "y": 1020,
        "wires": [
            [
                "14161f8f.5bb748"
            ]
        ]
    },
    {
        "id": "78ad4256.fda3d4",
        "type": "ui_group",
        "name": "Pylon Info",
        "tab": "ac8a95bb.741908",
        "order": 4,
        "disp": true,
        "width": "7",
        "collapse": true
    },
    {
        "id": "ac8a95bb.741908",
        "type": "ui_tab",
        "name": "Management & Diag",
        "icon": "dashboard",
        "order": 11,
        "disabled": false,
        "hidden": false
    }
]

```

Regds  
Ed

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [2 April 2022 13:31 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/7 "2022-04-02T13:31:39Z")

</div>

it's cool. Is it for the " **bat**" command? I think so. it is written, I had not seen, it was too big 👀  
I have a mini bug on the function node. Can you just guide me?  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/9/19b6aabfd4eb1dffd5ca79865af5bbb340482b6f.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/c/5c76ee131a15101ffd2f6a8f96502faac9d96b9f.png)

on the other hand nothing comes out of the function extract node, I have the "bat" data in input and on the "out" debug node but nothing into "extract" debug node

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/1/414771d7f0f1672e1cfc6f44f5158500605a9be1.png)

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [2 April 2022 13:33 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/8 "2022-04-02T13:33:59Z")

</div>

I saw in the meantime that another person proposed a flow with MQTT. To test ....  
The link here [Github](https://github.com/juanhaywood/nodered-pylontech-console-reader)

---

<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: [2 April 2022 13:48 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/9 "2022-04-02T13:48:37Z")

</div>

What if you skip the first 2 lines ?

---

<div class="post-metadata">

### Author: ![eddee54455](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/eddee54455/32/43350_2.png) [@eddee54455](https://discourse.nodered.org/u/eddee54455)
#### Post date: [2 April 2022 13:52 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/10 "2022-04-02T13:52:16Z")

</div>

Hi JL,

I inject a java string every 10sec - "pwr\r" - using an inject node,,,

on line7 - cT = global.get('INVNoBattStrings','file')+1 ; // Table max #columns(was5)  
change it to: cT = 2  
This is how many batteries you have linked together... I store it as a global parameter that is written to disk... (hence the \<,'file' \> bit of the command)

for testing and playing, you should just be able to modify the function node as follows:  
search for all lines that contain the \<,'file'\> and delete the ,'file' bit of it...

ie: change arr = context.get("arr","file")  
to arr = context.get("arr")

I will be online for a bit still... Just shout!!

Regds  
Ed

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [2 April 2022 20:14 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/11 "2022-04-02T20:14:26Z")

</div>

> [@eddee54455](#):
>
> cT = 2

Sorry, I could not resume until now.  
Ed, it works, I have a beautiful table with the values inside 😀  
Thank you for sharing your flow with me.

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

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [2 April 2022 20:17 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/12 "2022-04-02T20:17:00Z")

</div>

> [@bakman2](#):
>
> What if you skip the first 2 lines ?

The first lines don't have any useful information, so I configured the CSV node to skip them.  
That was the question ? As I use a translator, I'm not sure I understood the remark

---

<div class="post-metadata">

### Author: ![eddee54455](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/eddee54455/32/43350_2.png) [@eddee54455](https://discourse.nodered.org/u/eddee54455)
#### Post date: [3 April 2022 15:39 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/13 "2022-04-03T15:39:32Z")

</div>

Hi JL,

> [@eddee54455](#):
>
> on line7 - cT = global.get('INVNoBattStrings','file')+1 ; // Table max #columns(was5)  
> change it to: cT = 2

Remember that you can change the number of Pylons you have by changing the value of the cT variable....

The table should automatically resize and add extra columns for your additional batteries when you do....

Glad it's working for you!!

Regds  
Ed

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [3 April 2022 16:36 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/14 "2022-04-03T16:36:32Z")

</div>

Salut Ed  
I have quite a few things working, I still have the empty columns displayed when I don't want them.  
But it's slowly taking shape

![Test-Dashboard-Pylontech](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/5/f56b03cd35798d147d5735a55fb9080bf492ff92.gif)

---

<div class="post-metadata">

### Author: ![Jean-Luc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jean-luc/32/89996_2.png) [@Jean-Luc](https://discourse.nodered.org/u/Jean-Luc)
#### Post date: [4 April 2022 17:52 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/15 "2022-04-04T17:52:43Z")

</div>

Ed, do you have any idea why the columns stay at 8 on the dashboard?  
I do store the value 2 in a global variable, but no matter what value I put, it stays at 8 columns. I'm confused. It must be in front of me but I don't see 😳

Value of the number of columns:

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

The function code:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/1/71cc1a40944f5a372a38391ae4a063c92be7da16.png)

The result:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/c/7cba7cf2fb1c7f37df1abff1416b3abc4ae4f12b.png)

The global value stored:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/2/a255f851e1123d32071d1d9ddc3bf15fdcb484ed.png)

The Ui\_Table setting:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/9/593d6b75f88e4f9c7611f40ca4f3e151b96c2b48.png)

Under linux, on the global context:  
_~/global-variables/context/global $ cat global.json, the variable is also OK_  
_"Nbre\_bat\_Pylontech": 2,_

---

<div class="post-metadata">

### Author: ![eddee54455](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/eddee54455/32/43350_2.png) [@eddee54455](https://discourse.nodered.org/u/eddee54455)
#### Post date: [5 April 2022 19:10 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/16 "2022-04-05T19:10:25Z")

</div>

Hi JL,

I wrote a clear command into the function, possibly the array/table isn't clearing fully... inject a payload "clear" into the function, see if that helps...

Regds  
Ed

PS... Very nice indeed!! I like the way u are doing it!!

---

<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: [4 June 2022 19:10 UTC](https://discourse.nodered.org/t/view-and-process-pylontech-battery-data/60657/17 "2022-06-04T19:10:36Z")

</div>

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