# Help with the Maths/Javascript on this one please

**URL:** <https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732>\
**Category:** Dashboard\
**Created:** [8 September 2021 01:18 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732 "2021-09-08T01:18:06Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [8 September 2021 01:18 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/1 "2021-09-08T01:18:06Z")

</div>

Guys,

I have my 3 inverters feeding me information - one part of which is state of charge (SOC) of the batteries that are attached to each unit.

These will slowly creep out of sync over time - i would like a way dynamically vary the SOC to try and balance them all up

So lets say

1. AvailableSolar = 3000w
2. Number of inverters online = 3
3. SOC1 = 30, SOC2 = 34, SOC3 = 38

At the moment i am taking the AvailableSolar and dividing it by the number of inverters online to give me a charging rate that is then converted to a percentage for each inverter - they are all given the same rate - so 1000w per inverter translates to 20%

What i would like to do is (as a first crude measurement)

Find the inverter with the highest SOC  
Find the inverter with the lowest SOC  
Take 20% of the charge away from the inverter with the highest SOC and give that to the lowest inverter

So my function at the moment spits out (every 10 seconds) a single number - lets call it 20 in this case - which is telling each inverter to charge at 20% rate

So i would like to take the Highest SOC inverter and take 4% to to take it to 16 and add that 4% to the lowest to take it to 24%

So my question is how do i with the 3 inverters identify which one has the highest and lowest SOC

I thought i could read the global variables into function variables such as below and then put them into an array -this is not working - but surely there must be a simpler way ?

let sbpleftsoc = global.get("Battery.SBP-Left-SOC");  
let sbpmiddlesoc = global.get("Battery.SBP-Middle-SOC");  
let sbprightsoc = global.get("Battery.SBP-Right-SOC");

let inverterssoc = [sbpleftsoc, sbpmiddlesoc, sbprightsoc]; // Get max value of an array in Javascript  
node.warn("inverterssoc = " + inverterssoc);  
msg.payload = Math.max.apply(null, inverterssoc);

Craig

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [8 September 2021 01:55 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/2 "2021-09-08T01:55:08Z")

</div>

Sorry a screenshot of the current Global variables as well

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

Craig

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [8 September 2021 02:52 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/3 "2021-09-08T02:52:03Z")

</div>

I have looked at the Sort node and can not see how that would work here - whilst still enabling me to identify which inverter is which

Craig

---

<div class="post-metadata">

**Author:** ![Buckskin](https://avatars.discourse-cdn.com/v4/letter/b/b9e5f3/32.png) [@Buckskin](https://discourse.nodered.org/u/Buckskin)\
**Post date:** [8 September 2021 13:34 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/5 "2021-09-08T13:34:17Z")

</div>

Craig

try

```auto
let sbpleftsoc = global.get("Battery.SBP-Left.SOC");

```

etc. Note dot rather than dash between Left and SOC

also

```auto
msg.payload = Math.max(...inverterssoc)

```

will also work

to find out WHICH inverter is max then use

```auto
maxInverter = inverterssoc.indexOf(msg.payload)

```

0 = left  
1 = middle  
2 = right

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [8 September 2021 15:49 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/6 "2021-09-08T15:49:59Z")

</div>

You can sort array to [0] would be lowest and [2] would be highest  
eg.

```auto
[{"id":"fb3c9a6d.75065","type":"inject","z":"b779de97.b1b46","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"SOC1\": 1, \"SOC2\": 1, \"SOC3\": 90}","payloadType":"json","x":270,"y":2040,"wires":[["b30e7aa1.428f38"]]},{"id":"b30e7aa1.428f38","type":"function","z":"b779de97.b1b46","name":"","func":"let socs = msg.payload; // for testing uncomment below for input from context\n/*let socs = {\"soc1\": global.get(\"Battery.SBP-Left.SOC\") || 0,\n \"soc2\": global.get(\"Battery.SBP-Middle.SOC\") || 0,\n \"soc3\": global.get(\"Battery.SBP-Right.SOC\") || 0};*/\nlet target = 20;\nlet change = 4;\nlet socs_sorted = Object.values(socs).sort((a,b) => a-b) // lowest [0] highest [2]\nfor(const key in socs){\n //node.warn(offset);\n if (socs[key] === socs_sorted[2]){\n socs[key] = target - change * socs_sorted.filter((e)=>socs_sorted[0]===e).length;\n }else if (socs[key] === socs_sorted[0]){\n socs[key] = target + change * socs_sorted.filter((e)=>socs_sorted[2]===e).length;\n }else{\n socs[key] = target;\n }\n}\nmsg.payload = socs;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":450,"y":2220,"wires":[["f44c4a9.93ec0b8"]]},{"id":"739bacd9.656854","type":"inject","z":"b779de97.b1b46","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"SOC1\": 3, \"SOC2\": 30, \"SOC3\": 88}","payloadType":"json","x":180,"y":2120,"wires":[["b30e7aa1.428f38"]]},{"id":"efecca6.bce9938","type":"inject","z":"b779de97.b1b46","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"SOC1\": 10, \"SOC2\": 20, \"SOC3\": 30}","payloadType":"json","x":270,"y":2200,"wires":[["b30e7aa1.428f38"]]},{"id":"f44c4a9.93ec0b8","type":"debug","z":"b779de97.b1b46","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":680,"y":2160,"wires":[]}]

```

```auto
let socs = msg.payload; // for testing uncomment below for input from context
/*let socs = {"soc1": global.get("Battery.SBP-Left.SOC") || 0,
            "soc2": global.get("Battery.SBP-Middle.SOC") || 0,
            "soc3": global.get("Battery.SBP-Right.SOC") || 0};*/
let target = 20;
let change = 4;
let socs_sorted = Object.values(socs).sort((a,b) => a-b) // lowest [0] highest [2]
for(const key in socs){
    //node.warn(offset);
    if (socs[key] === socs_sorted[2]){
        socs[key] = target - change * socs_sorted.filter((e)=>socs_sorted[0]===e).length;
    }else if (socs[key] === socs_sorted[0]){
        socs[key] = target + change * socs_sorted.filter((e)=>socs_sorted[2]===e).length;
    }else{
        socs[key] = target;
    }
}
msg.payload = socs;
return msg;

```

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [8 September 2021 15:53 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/7 "2021-09-08T15:53:54Z")

</div>

Thanks Buckskin - obviously too long looking at the keyboard today and not focusing properly.

Craig

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [8 September 2021 15:54 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/8 "2021-09-08T15:54:54Z")

</div>

OK let me play with this and try to understand what you are doing here !!

Thanks for taking so much time on this - will report back !

Craig

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [8 September 2021 16:13 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/9 "2021-09-08T16:13:59Z")

</div>

slight change to function. To account for rare situation that all 3 socs are the same value

```auto
let socs = msg.payload; // for testing uncomment below for input from context
/*let socs = {"soc1": global.get("Battery.SBP-Left.SOC") || 0,
            "soc2": global.get("Battery.SBP-Middle.SOC") || 0,
            "soc3": global.get("Battery.SBP-Right.SOC") || 0};*/
let target = 20;
let change = 4;
let socs_sorted = Object.values(socs).sort((a,b) => a-b) // lowest [0] highest [2]
let count0 = socs_sorted.filter((e)=>socs_sorted[0]===e).length;
let count2 = socs_sorted.filter((e)=>socs_sorted[2]===e).length;

for(const key in socs){
    if (count0 < 3 && socs[key] === socs_sorted[2]){
        socs[key] = target - change * count0;
    }else if (count2 < 3 && socs[key] === socs_sorted[0]){
        socs[key] = target + change * count2;
    }else{
        socs[key] = target;
    }
}
msg.payload = socs;
return msg;

```

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [8 September 2021 16:55 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/10 "2021-09-08T16:55:09Z")

</div>

Thanks so much for all the effort on this -i have to step through this and TRY to understand what it is doing.

Craig

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [8 September 2021 16:58 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/11 "2021-09-08T16:58:09Z")

</div>

After taking your hints for my stupidity and then your hint re Index of function i have gotten this far now

```auto
//output 1 = SBPLeft
//Output 2 = SBPMiddle
//Output 3 = SBPRight

let ProposedChargingLevel = msg.payload

//Read out Global Variables
let sbpleftsoc = global.get("Battery.SBP-Left.SOC");
let sbpmiddlesoc = global.get("Battery.SBP-Middle.SOC");
let sbprightsoc = global.get("Battery.SBP-Right.SOC");

//Set them up as an array
let InvertersSOC = [sbpleftsoc, sbpmiddlesoc, sbprightsoc]; // Get max value of an array in Javascript
node.warn("inverterssoc = " + InvertersSOC);

msg.MaxInverterSOC = Math.max(...InvertersSOC);
MaxInverter = InvertersSOC.indexOf(msg.MaxInverterSOC);
msg.MaxInverter = MaxInverter;

msg.MinInverterSOC = Math.min(...InvertersSOC);
MinInverter = InvertersSOC.indexOf(msg.MinInverterSOC);
msg.MinInverter = MinInverter;

if (msg.MaxInverterSOC - msg.MinInverterSOC > 1) {
    node.warn("Difference bigger than 1 in SOC");
    ProposedChargingLevelMinInverter = ProposedChargingLevel * 1.2;
    ProposedChargingLevelMaxInverter = ProposedChargingLevel * 0.8;
    
}

return msg;

```

I have setup the function node with 3 outputs so now just to work out how to push the correct values out of each port - 3AM time for bed and hit this tomorrow

Thanks for all your help and hints guys

Craig

---

<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:** [8 October 2021 16:58 UTC](https://discourse.nodered.org/t/help-with-the-maths-javascript-on-this-one-please/50732/12 "2021-10-08T16:58:38Z")

</div>

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