Introduction
In April 2022 I had a PV system installed, with a local Enphase Envoy as part of the configuration.
The Enphase Envoy acts as a management gateway for the Enphase system. Collecting, storing and forwarding data to Enphase for the consumer Enlighten datapool and application.
My installation consists of an IQ Combiner; but I believe these instructions are valid for any Envoy running software greater than version 7. At the time of writing my Envoy is running D7.0.85.
Some history
I was interested in the raw data coming from the PV system. During vendor selection I reviewed the access and APIs available; and Enphase seemed to have a good mix of capabilities.
At some point in late 2021/early 2022 access to a local Envoy gateway was changed to require a JWT access token. This caused many home automation and data logging integrations to break. The documentation from Enphase showed how to interactively get the token and login. I found no documentation on doing this automatically through code.
After much reading, reviewing multiple blogs and github repos, and trial and error – I have this now working.
Authentication flow
Firstly, there’s a lot of head scratching on this approach from Enphase. Yes – it protects access behind a token, but it’s all intended for interactive work. I can only surmise that the market for this is not the home integrator or API data scraper. I see Enphase pushing that persona towards the Enlighten API v4 – which has a different set of issues (which I’ll write about in the future).
So the flow:
- login, using Enphase username/password, to the Enphase Entrez token service
- get a JWT access token
- post this JWT to the local envoy
- get data
The third step of this, posting the JWT to /auth/check_jwt, does not seem to be documented anywhere.
Also, and most troubling, the JWT itself is returned as part of the body of a html page. Some regex is needed to extract the specific text string. This has risk in the event that the html document structure changes in the future.
I posted a sample PowerShell script here.
Using this approach, I now have data being pulled from the local IQ Combiner, parsed, posted to a NoSQL database, and then graphed.
Hello,
I’m interested in trying to connect to my Envoy too – Your solution looks very nice and i’d like to thank you for sharing your experience.
Unfortunately, i am stuck at step 2, i don’t know how to get my JWT token. I can connect and login to the Enphase website, but to get the token, i need to enter a system and a gateway, and i don’t know at all what to fill. I tried several names and serial number for the system, but the gateway dropdown menu stays with only “select gateway” choice, and the get Token button is always greyed. Can you help me with this step please?. Thanks very much!
I have written a Python client for the local API here : https://github.com/Matthew1471/Enphase-API there’s also some local API documentation https://github.com/Matthew1471/Enphase-API/blob/main/Documentation/IQ%20Gateway%20API/General/Production.adoc I will be adding some more documentation over the next few days.
Hello,
it’s very interesting !
I have a solution with ESP8266 to heat my electric boiler water with the sun.
More on https://github.com/gelit/EnphaseReadPowerLive
Local API Token expires in one year !
I am not Oauth guru, my question about Token renewal : I need to adapt your example with https get & post to send 4 parameters (email + password + system + serial_number) … and I will receive new Token ?
As noted by Gérald, the local API tokens expire after a year. This leaves me not feeling very confident as companies come and go. To give myself (and the community) as much time to come up with a workaround if something were to happen to Enphase, I have scripted the renewal of the token weekly and I update my systems (Telegraf which feeds an InfluxDB and Grafana other bash scripts for various purposes) to use the new token. Because I am an old Unix admin I wrote a Bash script to do this. Posting it here in case its of use to anyone. It does some fiddly bits like decoding the token and getting the issued and expiry dates and emailng them out as proof of success that you may not want so feel free to pull that out and modify as desired. No warranty blah, blah and I might not be back by here to see any comments or questions. Hope it helps someone.
#!/bin/bash
now=`date +%m-%d-%y-%H_%M_%S`
working_path=” #path where all the temp files are saved during execution
enphase_user=” #enphase website user name
enphase_password=’ ‘ #enphase website password
envoy_serial=” #serial number of your envoy
notification_email=” #email address to send success/failure notifications to
source_email=” #email address to send success/failure notifications from
header=$path/scripts/header.$now #temp file to hold the token for later use in a verification api call
#Log in and get session ID
session_id=$(curl -s -X POST https://enlighten.enphaseenergy.com/login/login.json? -F “user[email]=$enphase_user” -F “user[password]=$ephase_password” | jq -r “.session_id”)
#Generate Token using session ID and serial number
web_token=$(curl -s -X POST https://entrez.enphaseenergy.com/tokens -H “Content-Type: application/json” -d “{\”session_id\”: \”$session_id\”, \”serial_num\”: \”$envoy_serial\”, \”username\”: \”$enphase_user\”}”)
#Write new JWT to temp file
echo $web_token > $path/envoy_token.$now
#Decode JWT and output to temp file
echo $web_token | tr “.” “\n” |base64 -d 2> /dev/null | jq 2> /dev/null > decoded.$now
#Parse decoded JWT for times and fingerprint
generationTime=`cat decoded.$now | grep iat | cut -d: -f2 | sed ‘s/,//g’`
expirationTime=`cat decoded.$now | grep exp | cut -d: -f2 | sed ‘s/,//g’`
fingerprint=`cat decoded.$now | grep jti | cut -d: -f2 | sed ‘s/,//g’ | sed ‘s/\”//g’`
#Convert epoch dates to gregorian
generationTime=`date -d “@$generationTime” +”%m-%d-%Y %T %z”`
expirationTime=`date -d “@$expirationTime” +”%m-%d-%Y %T %z”`
#Get last 20 characters of new token for inclusion in email
token=`cat $path/envoy_token.$now`
token=`echo “${token: -20}”`
#Test new JWT
bearerToken=`cat $path/envoy_token.$now`
echo “Authorization: Bearer $bearerToken” > $header
verification=`curl -s -f -k -H ‘Accept: application/json’ -H @$header -X GET https://YOUR_ENVOY_IP/production.json`
#Verify token returns valid data
if test -z $verification; then
#Set up email to notify of falure
echo “To: $notification_email” > /tmp/token-email.$now
echo “From: $source_email” >> /tmp/token-email.$now
echo “Subject: Token Generation Failed!” >> /tmp/token-email.$now
echo “Token generation failed. Please log in and run the script manually after ensuring internet connectivity.” >> /tmp/token-
email.$now
#Send email
`ssmtp $notification_email /tmp/token-email.$now
echo “From: $source_email” >> /tmp/token-email.$now
echo “Subject: A New JWT Token for Envoy has been generated” >> /tmp/token-email.$now
echo “A new envoy token has been generated!” >> /tmp/token-email.$now
echo “Generation time: $generationTime” >> /tmp/token-email.$now
echo “Expiration Time: $expirationTime” >> /tmp/token-email.$now
echo “JWT Fingerprint: $fingerprint” >>/tmp/token-email.$now
echo “Last 20 Characters of Token: $token” >>/tmp/token-email.$now
echo “Verification output: ” >>/tmp/token-email.$now
echo $verification >>/tmp/token-email.$now
#Send email
`ssmtp $notification_email < /tmp/token-email.$now`
#clean up
rm /tmp/token-email.$now
rm $header
rm decoded.$now
rm $path/envoy_token.$now
exit 0
fi
Hello,
Please disregard the above as I hacked it to put in variables in place of my personal info and didn’t fully test it. I have cleaned the script up along with some additional ones (which are all tested and functional) and posted it them on github. https://github.com/csmcolo/Enphase-Envoy-JWT-Tools
I hope they are useful to someone.