Enphase local API with firmware 7.x - my setup

Hi, this looks like a really elegant solution. I’ve created the proper secret and placed this in the configuration.yaml, and after a reload it shows as available for the Energy dashboard, however it’s unable to load any data, and gives me the statistics_not_found error someone else in this thread also mentioned:

When I go to https://envoy.local/ivp/meters/readings I see populated data fields, so it seems to be working:

[
    {
        "eid": xx,
        "timestamp": 1686945645,
        "actEnergyDlvd": 0.000,
        "actEnergyRcvd": 0.000,
        "apparentEnergy": 0.000,
        "reactEnergyLagg": 0.000,
        "reactEnergyLead": 0.000,
        "instantaneousDemand": -12.539,
        "activePower": -12.539,
        "apparentPower": 236.613,
        "reactivePower": 204.446,
        "pwrFactor": -0.048,
        "voltage": 664.372,
        "current": 1.067,
        "freq": 50.000,
        "channels": [
            {
                "eid": xx,
                "timestamp": 1686945645,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": -2.911,
                "activePower": -2.911,
                "apparentPower": 41.091,
                "reactivePower": 41.091,
                "pwrFactor": 0.000,
                "voltage": 218.207,
                "current": 0.188,
                "freq": 50.000
            },
            {
                "eid": xx,
                "timestamp": 1686945645,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": -4.864,
                "activePower": -4.864,
                "apparentPower": 121.188,
                "reactivePower": 89.021,
                "pwrFactor": -0.045,
                "voltage": 222.549,
                "current": 0.545,
                "freq": 50.000
            },
            {
                "eid": xx,
                "timestamp": 1686945645,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": -4.764,
                "activePower": -4.764,
                "apparentPower": 74.334,
                "reactivePower": 74.334,
                "pwrFactor": -0.077,
                "voltage": 223.616,
                "current": 0.333,
                "freq": 50.000
            }
        ]
    },
    {
        "eid": xx,
        "timestamp": 1686945645,
        "actEnergyDlvd": 0.000,
        "actEnergyRcvd": 0.000,
        "apparentEnergy": 0.000,
        "reactEnergyLagg": 0.000,
        "reactEnergyLead": 0.000,
        "instantaneousDemand": 666.108,
        "activePower": 666.108,
        "apparentPower": 986.725,
        "reactivePower": -491.181,
        "pwrFactor": 0.691,
        "voltage": 664.538,
        "current": 4.463,
        "freq": 50.000,
        "channels": [
            {
                "eid": xx,
                "timestamp": 1686945645,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 327.920,
                "activePower": 327.920,
                "apparentPower": 390.753,
                "reactivePower": -92.558,
                "pwrFactor": 0.847,
                "voltage": 218.198,
                "current": 1.795,
                "freq": 50.000
            },
            {
                "eid": xx,
                "timestamp": 1686945645,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 285.530,
                "activePower": 285.530,
                "apparentPower": 363.707,
                "reactivePower": -178.180,
                "pwrFactor": 0.803,
                "voltage": 222.537,
                "current": 1.630,
                "freq": 50.000
            },
            {
                "eid": xx,
                "timestamp": 1686945645,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 52.657,
                "activePower": 52.657,
                "apparentPower": 232.266,
                "reactivePower": -220.443,
                "pwrFactor": 0.238,
                "voltage": 223.802,
                "current": 1.038,
                "freq": 50.000
            }
        ]
    }
]

The Envoy is on firmware D7.0.88 (5580b1). Can you help me figure out what I’m missing?

If you open that entity does it show a value?

Also, can you post the block of yaml where you define the sensor?

How do you enter the token with a browswer? If I go to: https://envoy.local/ivp/meters/readings in Chrome, I just get 401 - not authorized

ha_steve; When I enter the URL; https://envoy.local/api/v1/production I get the unauthorized message, and after that I’m redirected to this login page;

Like I said in my previous post, I just paste my API key. And reopen the URL; https://envoy.local/api/v1/production e voila, I get the JSON as text in the browser;

As long as I have been working with REST API’s, this is a general trick to do troubleshooting.

So for those with a ‘Enphase Envoy-s Standard’, you can use this REST yaml;

rest:
  - headers:
      Authorization: !secret enphase_api_token
    verify_ssl: False
    scan_interval: 60
    resource: https://envoy.local/api/v1/production
    sensor:
      - name: "Zonne panelen huidige opbrengst"
        unique_id: zonne_panelen_opbrengst_nu"
        value_template: "{{ value_json.wattsNow | float }}"
        device_class: power
        state_class: measurement
        unit_of_measurement: W
      - name: "Zonne panelen opbrengst vandaag"
        unique_id: zonne_panelen_opbrengst_vandaag"
        value_template: "{{ value_json.wattHoursToday | float }}"
        device_class: energy
        state_class: measurement
        unit_of_measurement: Wh
      - name: "Zonne panelen totaal opbrengst"
        unique_id: zonne_panelen_opbrengst_totaal"
        value_template: "{{ value_json.wattHoursLifetime | float }}"
        device_class: energy
        state_class: measurement
        unit_of_measurement: Wh        
  - headers:
      Authorization: !secret enphase_api_token
    verify_ssl: False
    scan_interval: 60
    resource: https://envoy.local/api/v1/production/inverters
    sensor:
      - name: "Inverter 1 Power Output"
        unique_id: solar_power_inverter_1
        value_template: "{{ value_json[0].lastReportWatts | float }}"
        device_class: power
        state_class: measurement        
        unit_of_measurement: W
      - name: "Inverter 2 Power Output"
        unique_id: solar_power_inverter_2
        value_template: "{{ value_json[1].lastReportWatts | float }}"
        device_class: power
        state_class: measurement        
        unit_of_measurement: W
      - name: "Inverter 3 Power Output"
        unique_id: solar_power_inverter_3
        value_template: "{{ value_json[2].lastReportWatts | float }}"
        device_class: power
        state_class: measurement        
        unit_of_measurement: W
      - name: "Inverter 4 Power Output"
        unique_id: solar_power_inverter_4
        value_template: "{{ value_json[3].lastReportWatts | float }}"
        device_class: power
        state_class: measurement        

Ofcourse you also have to get your API code etc…

1 Like

This is why. For the IQ-series, you must send the Authorization header with the Bearer token. There is no way (without some extensions) to manually do this in a browser. This is all documented here: Enphase documentation

Hi ha_steve, when I open the status of the entities, both their statuses are unknown, unfortunately. The config I’ve used in the configuration.yaml is almost identical to the one you posted earlier:

rest:
  - headers:
      Authorization: !secret enphase_api
    verify_ssl: False
    scan_interval: 60
    resource: https://192.168.1.x/ivp/meters/readings    
    sensor:
      - name: "Solar Power Output"
        unique_id: solar_power_output_id
        value_template: "{{ value_json[0].activePower | float }}"
        device_class: power
        unit_of_measurement: W
        state_class: measurement
      - name: "Solar Array Production"
        unique_id: solar_array_production_id
        value_template: "{{ value_json[0].actEnergyDlvd | float / 1000 }}"
        state_class: total_increasing
        device_class: energy
        unit_of_measurement: "kWh"
        icon: mdi:solar-power

The token in the secret works when I use it in the browser. I use HA in a dockerized version on my Synology NAS. When I exec into the container, I can ping the ip address of my Envoy and connect on 80/443 aswell so it doesn’t seem to be a network problem.

You don’t literally have a .x in the IP address, correct? Sorry, had to ask.

Not a problem :slight_smile: but no, this is a valid octet in my network config. Still no matter what I do I get no statuses and the state problem I earlier mentioned. Other docs don’t provide a solution. Is the code I used the one you have it working with?

Your enphase_api in your secrets.yaml should be defines as:

enphase_api: Bearer eyJraWQiOiI.....

Just making sure you have the word ‘Bearer’ at the beginning. You can also check the logs to see what errors are being produced.

1 Like

I added the ‘Bearer’ text in front of the token in the secrets.yaml did the trick.Thanks for sticking with me on this one, much obliged!

2 Likes

Hmm apparently I was a bit early cheering, because the actEnergyDlvd value seems to be empty when I query the Envoy. I did however find another way of displaying the statistics via https://envoy.local/production.json?details=1. It also seems that you can poll this URL like every 500ms so you can get near-realtime statistics. But also in this json view I see that my ‘whToday’ value is empty, so there seems to be something strange going on with my Envoy. Will inspect and keep you posted.

I’m seeing the same behavior both with this new URL and my whToday value is 0 as well as /ivp/meters/readings URL and my actEnergyDlvd value is 0, my ActivePower value is correct however.

This is what I see when I query my device.

{
        "eid": 704643328,
        "timestamp": 1687269641,
        "actEnergyDlvd": 0.000,
        "actEnergyRcvd": 0.000,
        "apparentEnergy": 0.000,
        "reactEnergyLagg": 0.000,
        "reactEnergyLead": 0.000,
        "instantaneousDemand": 3829.339,
        "activePower": 3829.339,
        "apparentPower": 4040.183,
        "reactivePower": 1107.200,
        "pwrFactor": 0.948,
        "voltage": 244.966,
        "current": 32.503,
        "freq": 60.000,
        "channels": [
            {
                "eid": 1778385169,
                "timestamp": 1687269641,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 1916.977,
                "activePower": 1916.977,
                "apparentPower": 2023.881,
                "reactivePower": 558.906,
                "pwrFactor": 0.947,
                "voltage": 122.741,
                "current": 16.247,
                "freq": 60.000
            },
            {
                "eid": 1778385170,
                "timestamp": 1687269641,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 1912.362,
                "activePower": 1912.362,
                "apparentPower": 2016.302,
                "reactivePower": 548.293,
                "pwrFactor": 0.950,
                "voltage": 122.225,
                "current": 16.256,
                "freq": 60.000
            },
            {
                "eid": 1778385171,
                "timestamp": 1687269641,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 0.000,
                "activePower": 0.000,
                "apparentPower": 0.000,
                "reactivePower": 0.000,
                "pwrFactor": 0.000,
                "voltage": 0.000,
                "current": 0.000,
                "freq": 60.000
            }
        ]
    },
    {
        "eid": 704643584,
        "timestamp": 1687269641,
        "actEnergyDlvd": 0.000,
        "actEnergyRcvd": 0.000,
        "apparentEnergy": 0.000,
        "reactEnergyLagg": 0.000,
        "reactEnergyLead": 0.000,
        "instantaneousDemand": 639.052,
        "activePower": 639.052,
        "apparentPower": 1217.303,
        "reactivePower": 836.618,
        "pwrFactor": 0.494,
        "voltage": 244.882,
        "current": 9.772,
        "freq": 60.000,
        "channels": [
            {
                "eid": 1778385425,
                "timestamp": 1687269641,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": -50.215,
                "activePower": -50.215,
                "apparentPower": 66.753,
                "reactivePower": 19.450,
                "pwrFactor": -0.778,
                "voltage": 122.729,
                "current": 0.544,
                "freq": 60.000
            },
            {
                "eid": 1778385426,
                "timestamp": 1687269641,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 689.267,
                "activePower": 689.267,
                "apparentPower": 1150.550,
                "reactivePower": 817.168,
                "pwrFactor": 0.570,
                "voltage": 122.154,
                "current": 9.228,
                "freq": 60.000
            },
            {
                "eid": 1778385427,
                "timestamp": 1687269641,
                "actEnergyDlvd": 0.000,
                "actEnergyRcvd": 0.000,
                "apparentEnergy": 0.000,
                "reactEnergyLagg": 0.000,
                "reactEnergyLead": 0.000,
                "instantaneousDemand": 0.000,
                "activePower": 0.000,
                "apparentPower": 0.000,
                "reactivePower": 0.000,
                "pwrFactor": 0.000,
                "voltage": 0.000,
                "current": 0.000,
                "freq": 60.000
            }
        ]
    }
]

The metering was disabled by the company that installed the system. They remotely enabled it and it gives me data now. Perhaps you can ask them?

1 Like

Hi @ha_steve

Firstly, great solution and write up.

I’ve been monitoring the home assistant and enphase forums, and it would seem a lot of people got their firmware automatically upgraded recently, myself included.

I looked at the code on a few integrations and noticed they all pulled data from https://envoy.local/production.json

From my testing of this URL, it can take anywhere from 400ms to 2000ms for the envoy to generate this json file. I suspect this may be due to the envoy having to perform some calculations every time this url is requested.

This caused me to look for alternatives which led me to https://envoy.local/ivp/meters/readings which from my testing takes on average 50ms to 70ms to respond and offers roughly similar data.

This is where I noticed your thread and decided to do some of my own tweaks.

Here is what I did to get my power sensors back on track.

I removed any existing enphase related integrations (native and/or HACS)

Added my 12 month token to /config/secrets.yaml

enphase_api: "Bearer HIDDENFORPRIVACY"

Then, back in /config/configuration.yaml

rest:
  - headers:
      Authorization: !secret enphase_api
    verify_ssl: False
    scan_interval: 15
    resource: https://envoy.local/ivp/meters/readings    
    sensor:
      - name: "Power Production"
        value_template: >
            {% set value = value_json[0].activePower | int(0) %}
            {% if value  <= 5 -%}
                0
            {% elif is_state('sun.sun','below_horizon') %}
                0
            {%- else -%}
                {{ value }}
            {%- endif %}
        device_class: power
        unit_of_measurement: W
        state_class: measurement
        icon: mdi:solar-panel
      - name: "Power Net"
        value_template: "{{ value_json[1].activePower | int(0) }}"
        state_class: measurement
        device_class: power
        unit_of_measurement: W
        icon: mdi:transmission-tower

Then once I was happy with those sensors updating every 15 seconds, I was able to use template sensors to do some calculations with them to get the other sensors I needed.

template:
  - sensor:
        name: Power Consumption
        state_class: measurement
        icon: mdi:home-lightning-bolt
        unit_of_measurement: W
        device_class: power
        state : >
          {{ states('sensor.power_production') | int(0) + states('sensor.power_net') | int(0) }}
          
  - sensor:
        name: Power Export
        state_class: measurement
        icon: mdi:transmission-tower
        unit_of_measurement: W
        device_class: power
        state : >
          {{ [0, states('sensor.power_production') | int(0) - states('sensor.power_consumption') | int(0) ] | max }}
          
  - sensor:
        name: Power Import
        state_class: measurement
        icon: mdi:transmission-tower
        unit_of_measurement: W
        device_class: power
        state : >
          {{ [0, states('sensor.power_consumption') | int(0) - states('sensor.power_production') | int(0) ] | max }}

Now I am able to have a dashboard like this that updates every 15 seconds.
Feel free to try a smaller number of seconds for yourself.

image

Or graphs like this

Thanks a lot!

3 Likes

Hi Ha_Steve, bit by bit I get my system running. How do I execute the first part, the python script. How do I integrated this in HA. You see I’am not a pro.

Thanx Gert Gti-Pro

As it is a 12 month token, I have not figured out how to automate this yet.

In the meantime, if you have python installed, you can use the script on the system that has python installed.
If python is not installed, you can alternatively use 2 curl commands instead.

First curl command logs into enphase with your username and password to get a 32 character session id.

Second curl command uses that 32 character session id that was just created and your envoy serial number to generate the 408 character JWT token.

Please see this post

Have you tried using the link below? If it works, it will save you going through the above python route.

  1. Log into https://enlighten.enphaseenergy.com/
  2. Get your serial number by going to Settings > System > Devices
  3. Go to this URL and you should see the token in the output: https://enlighten.enphaseenergy.com/entrez-auth-token?serial_num=XXXXXXXXXXXX
  4. Then follow del13r’s post
1 Like

@del13r Now that you have the data coming in from Enphase system, have you got sensors for the inbuilt HA energy dashboard rather than standalone cards? I assume it needs to be turned into a sensor that keeps track over time.