Node-red-contrib-watt2kwh

I've just published v0.1.0 of node-red-contrib-watt2kwh which is specifically written to convert power (watts) to energy (kWh).
It carries out the conversion by measuring the interval between consecutive inputs, and multiplying it by the power value - interval x power = energy.
The output is then scaled to deliver units of Joules, Watt hour, Kilowatt hour or Megawatt hour which is selectable in the node's configuration.

Hope it's of use!

4 Likes

I test it immediately for my photovoltaic production :stuck_out_tongue:

1 Like

Installed and worked. I use it for my PV production and house consumption.
The node replaced a rather cumbersome flow with global variables.
Thanks.

1 Like

Hi Paul...

Just a small coding trick to compact those big switch-statements.

formats = {"j":1e-3, "kj": 1, "wh": 3.6}
output = formats["jk"]

So.. instead of the switch statement, use this instead?

const formats = {"j":1e-3, "kj": 1, "wh": 3.6, "kwh": 3600, "mwh": (1e3*3600)};
this.output = formats[config.format] || 0;

It seems to work ok, is there a trade off?

There are many ways of doing things - no one is more correct than others.

The advantage with the associative array is that if you do lookups with many key-value pairs then your code will be much more compact this way.

I don't think there are any trade offs.

In that case I'll update the node shortly
Thanks @x375993 Alex.

Btw... you can also do it with your timeunits

const unitfact={"secs": 1, "mins": 60, "hours": 3600}
this.maximum *= unitfact[config.maximumunit]

1 Like

Yes, already updated it, thanks

1 Like

Hi. How can i use this in more than one flow? Og i use it in more than one i get the same values out of every watt2kwh node..

If you are feeding in the same data, I would expect every watt2kwh to produce the same output.
Can you post a flow to demonstrate the problem, using inject nodes & debug nodes, because I'm not really sure what you are describing.


These two flows. It has different input values. but still the watt2kwh gives the same output

Try adding a debug node to each of the watt2kwh outputs, and show a screenshot of your debug panel (like below)
If you add names to the debug nodes, we can see which watt2kwh produced it.

tork

Thanks Paul,
That's a simple great tool that I needed and is in good use now.

Thanks again
Rich

1 Like

Hello,
I have been testing the watt2kWh node, I cannot figure out the following :
I downloaded the flow advised by Paul-Reed and injected zero kW every second. The stored result is not zero...
Can you please have a look ?
Kind regards,
Walt

[
    {
        "id": "72985628cd69b236",
        "type": "function",
        "z": "4fe759c01b309d0a",
        "name": "Store kwh",
        "func": "var inputVal = msg.payload;\nif (inputVal == \"reset\"){\n flow.set(\"energyVal\",0); \n } else {\nvar savedVal = flow.get('energyVal')||0;\nsavedVal += inputVal;\nflow.set(\"energyVal\",savedVal);\nmsg.payload = savedVal;\nreturn msg;\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 620,
        "y": 2520,
        "wires": [
            [
                "2f7c403dc696f005"
            ]
        ]
    },
    {
        "id": "f0342efc1df3ec36",
        "type": "watt2kwh",
        "z": "4fe759c01b309d0a",
        "format": "kwh",
        "maximum": "60",
        "maximumunit": "mins",
        "name": "",
        "x": 380,
        "y": 2480,
        "wires": [
            [
                "72985628cd69b236"
            ]
        ]
    },
    {
        "id": "8a6d0f53c496353c",
        "type": "inject",
        "z": "4fe759c01b309d0a",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "000",
        "payloadType": "num",
        "x": 180,
        "y": 2540,
        "wires": [
            [
                "f0342efc1df3ec36"
            ]
        ]
    },
    {
        "id": "2f7c403dc696f005",
        "type": "debug",
        "z": "4fe759c01b309d0a",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 910,
        "y": 2520,
        "wires": []
    }
]

I further my point : 2 identical flows, one injecting 1 kW/s, the other 2 kW/s. they give the same energy stored. Please help !

[
    {
        "id": "72985628cd69b236",
        "type": "function",
        "z": "4fe759c01b309d0a",
        "name": "Store kwh",
        "func": "var inputVal = msg.payload;\nif (inputVal == \"reset\"){\n flow.set(\"energyVal\",0); \n } else {\nvar savedVal = flow.get('energyVal')||0;\nsavedVal += inputVal;\nflow.set(\"energyVal\",savedVal);\nmsg.payload = savedVal;\nreturn msg;\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 620,
        "y": 2520,
        "wires": [
            [
                "2f7c403dc696f005",
                "62fc58e95b92ba3f",
                "75c409b68ba81ef1"
            ]
        ]
    },
    {
        "id": "f0342efc1df3ec36",
        "type": "watt2kwh",
        "z": "4fe759c01b309d0a",
        "format": "kwh",
        "maximum": "60",
        "maximumunit": "mins",
        "name": "",
        "x": 380,
        "y": 2480,
        "wires": [
            [
                "72985628cd69b236"
            ]
        ]
    },
    {
        "id": "8a6d0f53c496353c",
        "type": "inject",
        "z": "4fe759c01b309d0a",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1000",
        "payloadType": "num",
        "x": 180,
        "y": 2540,
        "wires": [
            [
                "f0342efc1df3ec36"
            ]
        ]
    },
    {
        "id": "2f7c403dc696f005",
        "type": "debug",
        "z": "4fe759c01b309d0a",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 910,
        "y": 2480,
        "wires": []
    },
    {
        "id": "400ccdd38c87a58a",
        "type": "function",
        "z": "4fe759c01b309d0a",
        "name": "Store kwh",
        "func": "var inputVal = msg.payload;\nif (inputVal == \"reset\"){\n flow.set(\"energyVal\",0); \n } else {\nvar savedVal = flow.get('energyVal')||0;\nsavedVal += inputVal;\nflow.set(\"energyVal\",savedVal);\nmsg.payload = savedVal;\nreturn msg;\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 620,
        "y": 2640,
        "wires": [
            [
                "6c9caf2dc266bf9a",
                "844083559b2e28ed",
                "ac0beed0fc15f477"
            ]
        ]
    },
    {
        "id": "38d80f0408df092e",
        "type": "watt2kwh",
        "z": "4fe759c01b309d0a",
        "format": "kwh",
        "maximum": "60",
        "maximumunit": "mins",
        "name": "",
        "x": 380,
        "y": 2600,
        "wires": [
            [
                "400ccdd38c87a58a"
            ]
        ]
    },
    {
        "id": "3fd908d1c1f43cda",
        "type": "inject",
        "z": "4fe759c01b309d0a",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "1",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "2000",
        "payloadType": "num",
        "x": 180,
        "y": 2660,
        "wires": [
            [
                "38d80f0408df092e"
            ]
        ]
    },
    {
        "id": "6c9caf2dc266bf9a",
        "type": "debug",
        "z": "4fe759c01b309d0a",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 910,
        "y": 2600,
        "wires": []
    },
    {
        "id": "844083559b2e28ed",
        "type": "ui_chart",
        "z": "4fe759c01b309d0a",
        "name": "",
        "group": "54ec15a15f8c33b7",
        "order": 1,
        "width": 0,
        "height": 0,
        "label": "2 kW/s",
        "chartType": "line",
        "legend": "false",
        "xformat": "dd HH:mm",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "0",
        "ymax": "1",
        "removeOlder": 1,
        "removeOlderPoints": "100",
        "removeOlderUnit": "86400",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": true,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 1070,
        "y": 2640,
        "wires": [
            []
        ]
    },
    {
        "id": "62fc58e95b92ba3f",
        "type": "ui_chart",
        "z": "4fe759c01b309d0a",
        "name": "",
        "group": "54ec15a15f8c33b7",
        "order": 1,
        "width": 0,
        "height": 0,
        "label": "1 kW/s",
        "chartType": "line",
        "legend": "false",
        "xformat": "dd HH:mm",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "0",
        "ymax": "1",
        "removeOlder": 1,
        "removeOlderPoints": "100",
        "removeOlderUnit": "86400",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": true,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 1070,
        "y": 2520,
        "wires": [
            []
        ]
    },
    {
        "id": "ac0beed0fc15f477",
        "type": "ui_gauge",
        "z": "4fe759c01b309d0a",
        "name": "",
        "group": "54ec15a15f8c33b7",
        "order": 1,
        "width": 0,
        "height": 0,
        "gtype": "wave",
        "title": "2 kW/s",
        "label": "W",
        "format": "{{value}}",
        "min": 0,
        "max": "10000",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "className": "",
        "x": 1070,
        "y": 2700,
        "wires": []
    },
    {
        "id": "75c409b68ba81ef1",
        "type": "ui_gauge",
        "z": "4fe759c01b309d0a",
        "name": "",
        "group": "54ec15a15f8c33b7",
        "order": 1,
        "width": 0,
        "height": 0,
        "gtype": "wave",
        "title": "1 kw/s",
        "label": "W",
        "format": "{{value}}",
        "min": 0,
        "max": "10000",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "className": "",
        "x": 1095.6666259765625,
        "y": 2560.666748046875,
        "wires": []
    },
    {
        "id": "54ec15a15f8c33b7",
        "type": "ui_group",
        "name": "test",
        "tab": "9d3d0269bc96b7c1",
        "order": 3,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "9d3d0269bc96b7c1",
        "type": "ui_tab",
        "name": "Home",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

I'll take a look, and reply back later.

I think that the problem is that you have more than one flow accessing the same flow context described in your function nodes.
In the 3 flows that you have posted, all three use flow.set("energyVal",savedVal); so all three flows are being influenced by each other.
The flow context will work fine if you have just the one flow, but if you have more than one flow, you need to change the name of each flow context (energyVal, energyValSolar, energyValHome, etc) to stop them all overwriting each other.

Alternatively you could always use node context - context.set("energyVal",savedVal); instead.

Something like;

var inputVal = msg.payload;
if (inputVal == "reset"){
 context.set("energyVal",0); 
 } else {
var savedVal = context.get('energyVal')||0;
savedVal += inputVal;
context.set("energyVal",savedVal);
node.status(savedVal)
msg.payload = savedVal;
return msg;
}

See Writing Functions : Node-RED

Hi Paul,
Thank you for your answer !
I will test your solution, nevertheless, when the Zero injection flow is working alone, I get a non zero storing answer...
Regards,
W.

Envoyé: samedi 22 octobre 2022 à 10:29

Hi Paul,
Everything seems OK with the context solution.
I suggest you implement it definitively as it solves some structural deficiency without the user tinkering the code for each and every flow including the watt2kWh node.
Kind regards,
W.

Envoyé: samedi 22 octobre 2022 à 10:29