Manipulating sensor output display to match unit of measurement

Hi team

I am reporting on power generation from my new solar panels by querying Zevercloud REST API. only problem is that up to 1KV, power is provided in watts and over 1KW, power is reported in kW. how can use the if statement in the sensor template to make the reading consistent, either in W or kW? - I hope this makes sense.

here is the current configuration (that I am looking to change):

  • platform: rest
    resource: https://www.zevercloud.com/api/v1/getPlantOverview?key=
    json_attributes:
    - Power
    name: zeversolar
    value_template: ‘OK’
    • platform: template
      sensors:
      power_value:
      value_template: ‘{{ states.sensor.zeversolar.attributes[“Power”][“value”] }}’
      unit_of_measurement: “w”

I looked at the documentation, and the more I read, the more confused I get, so I would really appreciate if someone points me to the right direction

(the returned JSON template also includes the unit for the reported power, either w or kW, if this helps

  • I assume it can be read using states.sensor.zeversolar.attributes[“Power”][“unit”]) …

Many thanks - Ran

  1. you have to format the code in your post.
  2. Can you show us the what the json object looks like when it’s in kw vs when it’s in w?

Sure Petro. yes, I need help with formatting the results to convert one or the other so that the sensor data is either always in W or in kW

the results currently are either 0-999 W or 1.1 to 5.9 kW

the return JSON output is:

{“sid”:89597,“ludt”:“2020-03-18 17:21:40”,“E-Today”:{“unit”:“kWh”,“value”:31.5},“E-Month”:{“unit”:“kWh”,“value”:33.57},“E-Total”:{“unit”:“kWh”,“value”:33.67},“TotalYield”:{“unit”:"$",“value”:23.57},“CO2Avoided”:{“unit”:“kg”,“value”:26.94},“Power”:{“unit”:“W”,“value”:467}}

I will have another look tomorrow morning to capture a kW output but I am sure the unit retruns kW and the value is in the format of X.X (1.1 to 5.9)

Many thanks - Ran

P L E A S E format your code like petro asked. If in doubt, read this How to help us help you - or How to ask a good question

Is this better?

  - platform: rest
    resource: https://www.zevercloud.com/api/v1/getPlantOverview?key=<mykey>
    json_attributes:
      - E-Today
      - E-Month
      - E-Total
      - TotalYield
      - CO2Avoided
      - Power
    name: zeversolar
    value_template: 'OK'
  - platform: template
    sensors:
      e_today_value:
        value_template: '{{ states.sensor.zeversolar.attributes["E-Today"]["value"] }}'
        unit_of_measurement: "kWh"
      e_month_value:
        value_template: '{{ states.sensor.zeversolar.attributes["E-Month"]["value"] }}'
        unit_of_measurement: "kWh"
      e_total_value:
        value_template: '{{ states.sensor.zeversolar.attributes["E-Total"]["value"] }}'
        unit_of_measurement: "MWh"
      totalyield_value:
        value_template: '{{ states.sensor.zeversolar.attributes["TotalYield"]["value"] }}'
        unit_of_measurement: "$"
      co2avoided_value:
        value_template: '{{ states.sensor.zeversolar.attributes["CO2Avoided"]["value"] }}'
        unit_of_measurement: "T"
      power_value:
        value_template: '{{ states.sensor.zeversolar.attributes["Power"]["value"] }}'
        unit_of_measurement:  '{{ states.sensor.zeversolar.attributes["Power"]["unit"] }}'

as I said, I am looking for guidance in converting the returned Power value to a consistent format, as it is in W when the value is between 0 and 999 and in kW when the value is between 1 and 5.9.

Many thanks for your help

Regards - Ran

Yes, way better thanks.

I think for a complete answer you will need to post this

But as a guess you’ll need to do an if/then based on the units offered up in the json response, and convert to the units you want. Is pseudo code (as I don’t know enough templating)

if (Powerunit = W then Power / 1000)
unit_of_measurement = kW

Thanks - Here is the JSON return code when the value is in Watts.

{“sid”:89597,“ludt”:“2020-03-18 17:21:40”,“E-Today”:{“unit”:“kWh”,“value”:31.5},“E-Month”:{“unit”:“kWh”,“value”:33.57},“E-Total”:{“unit”:“kWh”,“value”:33.67},“TotalYield”:{“unit”:"$",“value”:23.57},“CO2Avoided”:{“unit”:“kg”,“value”:26.94},“Power”:{“unit”:“W”,“value”:467}}

in kW, the return code would be

{“sid”:89597,“ludt”:“2020-03-18 09:21:40”,“E-Today”:{“unit”:“kWh”,“value”:31.5},“E-Month”:{“unit”:“kWh”,“value”:33.57},“E-Total”:{“unit”:“kWh”,“value”:33.67},“TotalYield”:{“unit”:"$",“value”:23.57},“CO2Avoided”:{“unit”:“kg”,“value”:26.94},“Power”:{“unit”:“kW”,“value”:3.45}}

I agree with you regarding the IF statement. I am hoping someone will be able to help with the IF statement formatting as well, as I couldn’t find any examples in the documentation that are close enough for me to make sense from.

Regards - Ran

I think you’ll need to get the power units into the attribute or state of a sensor - this will be a sensor that is simply an intermediate entity that you won’t need to ever display in the UI. Similarly with the power value. The rest manipulation and/or jinja templating is beyond me.

But once you have them as attributes/states the manipulations should be simple®.

No doubt @petro will reappear and answer in one simple post with an elegant answer.

Simply try the function node from this flow:

[
    {
        "id": "2e6a5c51.991544",
        "type": "inject",
        "z": "6b8efe0d.bc75e",
        "name": "",
        "topic": "",
        "payload": "{\"sid\":89597,\"ludt\":\"2020-03-18 09:21:40\",\"E-Today\":{\"unit\":\"kWh\",\"value\":31.5},\"E-Month\":{\"unit\":\"kWh\",\"value\":33.57},\"E-Total\":{\"unit\":\"kWh\",\"value\":33.67},\"TotalYield\":{\"unit\":\"$\",\"value\":23.57},\"CO2Avoided\":{\"unit\":\"kg\",\"value\":26.94},\"Power\":{\"unit\":\"kW\",\"value\":3.45}}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 150,
        "y": 1820,
        "wires": [
            [
                "8b49d860.fe48f8",
                "d572b70.44fc348"
            ]
        ]
    },
    {
        "id": "d572b70.44fc348",
        "type": "debug",
        "z": "6b8efe0d.bc75e",
        "name": "Snapcast",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 720,
        "y": 1820,
        "wires": []
    },
    {
        "id": "8b49d860.fe48f8",
        "type": "function",
        "z": "6b8efe0d.bc75e",
        "name": "kW or W",
        "func": "newmsg = {}\n\nif (msg.payload.Power.unit == \"kW\")\n{  \n  newmsg.payload = msg.payload.Power.value * 1000;\n}\nelse\n{\n    newmsg.payload = msg.payload.Power.value;\n}\n\n\n\nreturn newmsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 440,
        "y": 1820,
        "wires": [
            [
                "d572b70.44fc348"
            ]
        ]
    }
]

Or if you want to do it without a function node you can also easily do it with a switch and a calculator node:

[
    {
        "id": "2e6a5c51.991544",
        "type": "inject",
        "z": "6b8efe0d.bc75e",
        "name": "",
        "topic": "",
        "payload": "{\"sid\":89597,\"ludt\":\"2020-03-18 09:21:40\",\"E-Today\":{\"unit\":\"kWh\",\"value\":31.5},\"E-Month\":{\"unit\":\"kWh\",\"value\":33.57},\"E-Total\":{\"unit\":\"kWh\",\"value\":33.67},\"TotalYield\":{\"unit\":\"$\",\"value\":23.57},\"CO2Avoided\":{\"unit\":\"kg\",\"value\":26.94},\"Power\":{\"unit\":\"kW\",\"value\":3.45}}",
        "payloadType": "json",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 130,
        "y": 1740,
        "wires": [
            [
                "aca318a0.2d54a8"
            ]
        ]
    },
    {
        "id": "d572b70.44fc348",
        "type": "debug",
        "z": "6b8efe0d.bc75e",
        "name": "VALUE",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 600,
        "y": 1800,
        "wires": []
    },
    {
        "id": "226b12.573534ee",
        "type": "calculator",
        "z": "6b8efe0d.bc75e",
        "name": "",
        "inputMsgField": "payload.Power.value",
        "outputMsgField": "payload.Power.value",
        "operation": "mult",
        "constant": "1000",
        "x": 440,
        "y": 1740,
        "wires": [
            [
                "d572b70.44fc348"
            ]
        ]
    },
    {
        "id": "aca318a0.2d54a8",
        "type": "switch",
        "z": "6b8efe0d.bc75e",
        "name": "",
        "property": "payload.Power.unit",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "kW",
                "vt": "str"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 270,
        "y": 1740,
        "wires": [
            [
                "226b12.573534ee"
            ],
            [
                "d572b70.44fc348"
            ]
        ]
    }
]

So as @nickrout said, all you need to do is check the units and build an availability template to ensure you don’t get errors:

Watts as units…

      power_value:
        value_template: >
          {% set units = states('sensor.zeversolar', 'Power')['unit'] %}
          {% set value = states('sensor.zeversolar', 'Power')['value'] | int %}
          {{ value * 1000 if units == 'kW' else value }}
        availability_template: >
          {{ states.sensor.zeversolar.attributes.Power is defined }}
        unit_of_measurement: W

OR

kWatts as units

      power_value:
        value_template: >
          {% set units = states('sensor.zeversolar', 'Power')['unit'] %}
          {% set value = states('sensor.zeversolar', 'Power')['value'] | int %}
          {{ value if units == 'kW' else value / 1000 }}
        availability_template: >
          {{ states.sensor.zeversolar.attributes.Power is defined }}
        unit_of_measurement: kW

Thanks @petro, @nickrout and @AlmostSerious . - this is great.

much appreciated - Ran

got it working - thanks @petro for showing me the way. I only had to change states to state_attr to get the values, as well as changing the type to float (from int):

      power_value:
        value_template: >-
          {% set units = state_attr('sensor.zeversolar', 'Power')['unit'] %}
          {% set value = state_attr('sensor.zeversolar', 'Power')['value'] | float %}
          {{ value if units == "kW" else value / 1000 }}
        availability_template: >
          {{ states.sensor.zeversolar.attributes.Power is defined }}
        unit_of_measurement: "kW"

Thanks again - Ran

Ah yep, my bad. Glad you got it working though.