[New Binding] Enphase Envoy Solar System gateway

I don’t know if it is of relevance but I know there are some differences from the new V7 local API and cloud based access.

https://entrez.enphaseenergy.com/login doesn’t load as a website for me but Enphase Authentication | Login page does. I guess your code is building up the token page url using the info from the .things file and you are using the web url method for obtaining a token?

@raaahbin It seems it can’t login. The login reports incorrect username/password. Did you configured the username and password for the Enphase portal? Or is there maybe a space extra in the username/password?

@davebuk It seems the binding has some issues with detecting what version it should use. For some reason the discovery doesn’t get the version. Therefor the binding falls back to trying to determine the version by connecting to the Envoy. However that seems to go wrong. I want to make this a bit more robust instead of guessing what it can be. Therefor can you check the following for me: In a browser open the following page to your envoy device: http://<ip of envoy>/info.xml (Make sure you’re not logged in, for example open in private browsing). Does it exists? And if so, what status does it return (a 200 or something else) and if it returns data what does it show in the tag <software>....</software>?

**https**://<ip of envoy>/info.xml gives <software>D7.0.88</software>.

Yes - copied and pasted username and password directly from keychain, also manually used them to log into the Enphase portal. Plus I tried the version where you don’t configure the username and password and instead paste in the JWT, which gave the same error as davebuk was reporting, and also the version where I manually create a things file with the username and password in there for auto-JWT. I’ll do some more testing tomorrow - has the JAR been updated?

@raaahbin I believe the JAR on github is at V2 and is at the latest version for testing.

I’m very much appreciative of the efforts to get the binding updated but from a personal point of view, if the binding can still only update the values every 5 minutes, its not as much use to me as compared to what I have running using the http binding. I know it can be changed but will the binding allow a say 10 second update?

I have some rules setup to run some radiator heaters when power is exported to the grid and then switch those off when I’m importing. A 5 minute update is a bit too long a gap. I can refresh the data using the CURL commands every 10 seconds.

I’ll have a look at replicating your HTTP binding approach when I next have some time to try things out. In the long run, perhaps the enphase binding for most info, coupled with the HTTP binding just for the really short-term “live” data might work best. I’d prefer not to just repeatedly hit the gateway with full queries every 10 seconds when most of the data doesn’t change except on the 5 minute, but I can see the benefit in having some “instantaneous” values too.

Hi

Just to follow up, I added a thing using the webGUI rather than a file and had the same result as @raaahbin . The thing will get the software version but fails to become ‘online’. I have tried using a working token and also the JWT auto mode checking for the correct user/password.

@raaahbin and @davebuk I’ve updated the binding (date when showing binding in list binding in openHAB ui = 18-05-2023). I’ve improved detecting what version it should use and also found some other bugs related to configuration. I’ve tested login with my own login an I it goes past the login.

Regarding the readings of the ipv end points. On my system the meters are reporting as disabled. But I do get reading values, every time I call the readings endpoint. Although the value seems not to match the actual values. So it’s a bit weird. An option could be to add reading those values to the binding, but that requires some more thought to see how that would be best implemented.

Hi

Still can’t connect I’m afraid using .things file.

2023-05-19 07:48:33.055 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'enphase.things'
2023-05-19 07:48:33.169 [TRACE] [.internal.handler.EnvoyBridgeHandler] - Check connection
2023-05-19 07:48:33.170 [DEBUG] [hase.internal.handler.EnvoyConnector] - Check connection to '192.168.1.XXX/info.xml'
2023-05-19 07:48:33.568 [DEBUG] [hase.internal.handler.EnvoyConnector] - Checkconnection status from request is: 200
2023-05-19 07:48:33.570 [DEBUG] [hase.internal.handler.EnvoyConnector] - Check connection to '192.168.1.XXX/info.xml'
2023-05-19 07:48:34.440 [DEBUG] [hase.internal.handler.EnvoyConnector] - Checkconnection status from request is: 200
2023-05-19 07:48:34.440 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - EnphaseException in Enphase thing enphase:envoy:XXXXXX:
org.openhab.binding.enphase.internal.exception.EnphaseException: No connection could be made with the Envoy. Check your connection/hostname.
at org.openhab.binding.enphase.internal.handler.EnvoyConnectorWrapper.determineConnector(EnvoyConnectorWrapper.java:138) ~[?:?]
at org.openhab.binding.enphase.internal.handler.EnvoyConnectorWrapper.setConnector(EnvoyConnectorWrapper.java:67) ~[?:?]
at org.openhab.binding.enphase.internal.handler.EnvoyBridgeHandler.checkConnection(EnvoyBridgeHandler.java:301) ~[?:?]
at org.openhab.binding.enphase.internal.handler.EnvoyBridgeHandler.updateData(EnvoyBridgeHandler.java:263) ~[?:?]
at org.openhab.binding.enphase.internal.handler.EnvoyBridgeHandler.lambda$2(EnvoyBridgeHandler.java:161) ~[?:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
at java.lang.Thread.run(Thread.java:829) [?:?]

I had no luck with my existing .things file, but after disabling that and adding the config through the webGUI… it works! Good connection to the envoy, and it has 8 channels available - 4 production, 4 consumption (each is Today, 7 Days, Lifetime and Latest).

I also got the readout from the inverter in the debug log - pasted here, in case there’s a way to set up the binding to create channels for those too:

Envoy returned data for '/api/v1/production/inverters' with status 200: [
  {
    "serialNumber": "122303000535",
    "lastReportDate": 1684479944,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 223
  },
  {
    "serialNumber": "122303000557",
    "lastReportDate": 1684479905,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 137
  },
  {
    "serialNumber": "122303001062",
    "lastReportDate": 1684479946,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 194
  },
  {
    "serialNumber": "122303009183",
    "lastReportDate": 1684480168,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 205
  },
  {
    "serialNumber": "122303009530",
    "lastReportDate": 1684480169,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 206
  },
  {
    "serialNumber": "122303011051",
    "lastReportDate": 1684479915,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 94
  },
  {
    "serialNumber": "122303012229",
    "lastReportDate": 1684479915,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 88
  },
  {
    "serialNumber": "122303013590",
    "lastReportDate": 1684480138,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 205
  },
  {
    "serialNumber": "122303014065",
    "lastReportDate": 1684479921,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 215
  },
  {
    "serialNumber": "122303014400",
    "lastReportDate": 1684479922,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 186
  },
  {
    "serialNumber": "122303014774",
    "lastReportDate": 1684479925,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 125
  },
  {
    "serialNumber": "122303015006",
    "lastReportDate": 1684479928,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 229
  },
  {
    "serialNumber": "122303015073",
    "lastReportDate": 1684480147,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 209
  },
  {
    "serialNumber": "122303015112",
    "lastReportDate": 1684479930,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 113
  },
  {
    "serialNumber": "122303015529",
    "lastReportDate": 1684480151,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 205
  },
  {
    "serialNumber": "122303015543",
    "lastReportDate": 1684480152,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 208
  },
  {
    "serialNumber": "122303015557",
    "lastReportDate": 1684480156,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 205
  },
  {
    "serialNumber": "122303022334",
    "lastReportDate": 1684480115,
    "devType": 1,
    "lastReportWatts": 0,
    "maxReportWatts": 208
  }
]


Incidentally, this is using autoJWT. Since that’s my preferred config, I haven’t tried with a manually retrieved JWT.

Also I’m pretty sure those inverter values are correct - it’s currently late evening without enough light to get anything from the panels.

Further to the above, I was able to create things for the inverters in a .things file and get them connected, so it looks like I’ve now got all that info ready to come through as well. Looks like it’s fully functional, but I’ll certainly be doing further testing!

@davebuk I’ve updated the binding (19-05-2023). The binding seems to fall back to the info.xml. This failed due to difference in version coding between old and new systems. The binding uses MDNSDiscovery to get the ip address in case only the serial number if configured. For some reason this discovery is not always triggered. This means it won’t get the ip or version number and than it falls back to the info.xml variant. I’ve updated the binding that it should now correctly identify the version number of newer systems.

@raaahbin Great you get it working. Let me know if you find anything.

If all seem stable I might put on a kar version of the binding. Because for merging the binding with the openHAB repo the dependencies need to be a bit different. But a kar version only works on a specific version of openHAB, therefor I’ve not posted a kar file for now to let it work on different versions.

Hi

I just saw the update and tried again. Its working using the webGUI but not as a .thing file

2023-05-19 17:17:53.592 [TRACE] [.internal.handler.EnvoyBridgeHandler] - Check connection
2023-05-19 17:17:53.912 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.
2023-05-19 17:18:03.915 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.
2023-05-19 17:18:13.918 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.
2023-05-19 17:18:23.927 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.
2023-05-19 17:18:33.943 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.
2023-05-19 17:18:43.957 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.
2023-05-19 17:18:53.968 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.
2023-05-19 17:19:03.985 [DEBUG] [.internal.handler.EnvoyBridgeHandler] - Schedule hostname/ip address update for thing enphase:envoy:122243083593 in 10 seconds.

It can’t seem to get an IP address. Even if I set hostname="192.168.1.XXX" in the .things file it still shows the same error.
@raaahbin what operating system are you running openHAB on?

@hilbrand

Its working :slight_smile:

I restarted the openHAB service and it’s picked up the configuration from the .things file and is connected.

Do you have time to look to adding other url end points and a quicker, customisable refresh option?

Thanks again.

My openHAB is running on MacOS 10.15.7 on an old Mac Mini.

@hilbrand

Out of curiosity, how often does the binding update the token? I believe they last for 12 months.

Can the binding extract the expiry time stamp and output it as a channel/thing?

I don’t know it gets the expiration time from the api and uses that to set monitor if it is outdated. It’s likely possible to add a channel to show the timestamp.

Thank you Hilbrand for the updated Enphase binding! I have installed your latest version from GitHub and it is working very well so far. Gateway with firmware version 7.6.172 here.

Will your update be part of the upcoming OH 4 release?

Thanks,
Matt

Hi all,

My envoy got updated to D7.6.175, and sadly the new binding code (org.openhab.binding.enphase-4.0.0-SNAPSHOT.jar) can not log into my envoy. I tried the static JWT and auto-JWT. When using static JWT, the error message in openhab is: "CONFIGURATION_ERROR Could not login to Envoy with the access token. Envoy returned status:200 ".

Any suggestions how to debug / fix this?

Thanks in advance!

@mstehle I have a PR to include it in openHAB 4, but I dont know if this will make it in the 4 release. If not I think about creating a markplace topic here for the binding.

@Karel it looks like the binding couldn’t find the sessionid. I don’t know if they changed something or something else is wrong. If you enable log level debug on the enpase binding org.openhab.binding.enphase you might see if it gives you some more detailed information regarding this issue.

2 Likes