@PeteF
I too am in the UK and āmanageā a system at my sonās place with 3 x PowerWallās. We do not use the Interfacer but a script instead:
# PURPOSE: To input key PowerWall data into emoncms
# HOW TO ...
# The script will create an INPUT node to receive the data
# Copy this script file to /home/pi and make it executable with: chmod +x /home/pi/JB.powerwall.py # using the correct script name
# Run the script with: /usr/bin/python3 /home/pi/JB.powerwall.py # using the correct script name
# Create FEEDS using Log to Feed and add UNITS (pencil drop-down) to each
# IMPORTANT NOTE ...
# Data from this script is input to emoncms via an http API.
# IMPORTANT NOTE ...
# Reserve a LAN IP address in the ROUTER to fix it for the WIRED connection to PowerWall
import sys, requests, json, time
from time import sleep
# Emoncms server configuration
emoncms_apikey = "18f63xxxxxxxxxxxxaabe048da" # For Node 15 - use appropriate key
emoncms_server = "http://127.0.0.1"
node = "Power_Wall" # Name of the node to be created to receive the INPUT data from PowerWall
gateway = "http://192.168.1.119" # IP address of the Tesla Gateway on local network - IMPORTANT: Reserve a LAN IP address in the ROUTER to fix it
node = node
# Give a name to each of the data inputs associated with the newly created node ...
di1 = "Charge_percent"
di2 = "Power_Now"
di3 = "Total_Export_Energy"
di4 = "Total_Import_Energy"
# Repetitive Looping starts here ...
starttime = time.time()
while True:
# First enquiry
reply = requests.get(gateway+"/api/system_status/soe", timeout=10, verify=False)
jsonstr = reply.text.rstrip()
data_p1 = json.loads(jsonstr)
# Second enquiry
reply = requests.get(gateway+"/api/meters/aggregates", timeout=10, verify=False)
jsonstr = reply.text.rstrip()
data_p2 = json.loads(jsonstr)
# Extract relevant data from the json's
data1 = data_p1['percentage']
data2 = data_p2['battery']['instant_power']
data3 = data_p2['battery']['energy_exported']
data4 = data_p2['battery']['energy_imported']
# Send data to emoncms
dev_data = {di1: data1, di2: data2, di3: data3, di4: data4}
# print (dev_data) # a progress marker - can be commented out
data = {
'node': node,
'data': json.dumps (dev_data),
'apikey': emoncms_apikey
}
response = requests.post(emoncms_server+"/input/post", data=data)
# End of Loop
time.sleep(10.0 - ((time.time() - starttime) % 10.0)) # Repeat every 10 secs
# FINALLY ONCE THE SCRIPT RUNS OK: Create the powerwall.service and enable it so the script runs on boot up as follows:
# Do: CTRL-C to stop the script then - Do: sudo nano /etc/systemd/system/powerwall.service and copy & paste in the following (using the correct script name) ...
"""
[Unit]
Description=PowerWall Status
After=network.target
After=mosquitto.service
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=pi
ExecStart=/usr/bin/python3 /home/pi/JB.powerwall.py
[Install]
WantedBy=multi-user.target
"""
# Then save & exit and to ensure the powerwall.service runs on boot up - Do ...
# sudo systemctl start powerwall.service and then sudo systemctl enable powerwall.service
# AS A VERY LAST CHECK - Do: sudo reboot then SSH in again and check the service is active with: systemctl status powerwall.service
# Finally close the SSH terminal. The script/service will continue to run surviving any future reboots
# Unkowns: what happens to the script/service when emoncms is updated as it will not be included in any Export ... so - caveat emptor
The script is still functioning. It makes two API calls:
/api/system_status/soe and /api/meters/aggregates
The firmware version is 20.40.3 so it looks like we will be similarly afflicted in the near future.
In addition I have two scripts to control PowerWall charging behaviour ā so that it charges at overnight cheap rates. Hereās one:
"""
PURPOSE ...
To set the PowerWall Reserve charge to 100 percent
"""
import requests, json
from requests.structures import CaseInsensitiveDict
# Enter energy_site identifier ...
en_site = "15xxxxxxxxxxxxx1858"
url = "https://owner-api.teslamotors.com/api/1/energy_sites/"+en_site+"/backup"
# Get latest Access Token from file
f = open("/home/pi/ev-charging-scripts/access_token.txt", "r")
acc_tok = f.read()
headers = CaseInsensitiveDict()
headers["Accept"] = "application/json"
headers["Authorization"] = "Bearer "+acc_tok
headers["Content-Type"] = "application/json"
data = {"backup_reserve_percent": 100}
resp = requests.post(url, headers=headers, data=json.dumps(data))
print(resp.status_code)
But these scripts stopped working a couple of days ago because my Authority Token script stopped running a couple of days ago returning 400. Clearly this is where the authorisation body is buried:
"""
PURPOSE ...
Get a new Access Token and save it to a file
Access Tokens expire after 45 days
So run this script monthly via crontab -e
Other scripts can read the current Access Token (acc_tok) from the file by including the following lines ...
f = open("/home/pi/ev-charging-scripts/access_token.txt", "r")
acc_tok = f.read()
"""
import requests, json, datetime
from requests.structures import CaseInsensitiveDict
url = "https://owner-api.teslamotors.com/oauth/token"
headers = CaseInsensitiveDict()
headers["Content-Type"] = "application/json"
data = '{"grant_type": "password", "client_id": "81527cff06843c8634fdc09e8ac0abefb46ac849f38fe1e431c2ef2106796384", "client_secret": "c7257eb71a564034f9419ee651c7d0e5f7aa6bfbd18bafb5c5c033b093bb2fa3", "email": "xxxxxxxxxxxxxxxxxx.com", "password": "xxxxxxxxxxxxx"}'
response = requests.post(url, headers=headers, data=data)
if response.status_code in [200]:
token_dict = json.loads(response.text)
for x, y in token_dict.items():
print(x, y)
else:
print(response.status_code)
x = token_dict["created_at"] + token_dict["expires_in"]
date = datetime.datetime.fromtimestamp(x)
print("Valid UNTIL: " + date.strftime('%Y-%m-%d %H:%M:%S'))
# Over-write the access token in a file (access_token.txt) in the SAME directory as this script
f = open("/home/pi/ev-charging-scripts/access_token.txt", "w")
f.write(token_dict["access_token"])
f.close()
Thx for the link. This also looks informative:
Clearly written by an expert for expert readers ā which I am not.
If you do come up with a fix (albeit temporary) then please share it.
Thx