Add support for Tesla Powerwall

Yup. For the past few days, I haven’t been able to get access to do this.

Error: Unexpected error for call_service at pos 1: 401 Client Error: Unauthorized for url: https://owner-api.teslamotors.com/api/1/products

Definitely hoping to get this working again. It was fabulous before.

The issue as I understand it is that Tesla changed the methods around authorization tokens. This integration is based on Teslapy which has since been upgraded and works.
Unfortunately this HA integration doesn’t appear to be maintained by anyone at the moment and unless someone takes it on and integrates the new version of Teslapy then sadly it’s finished.

Personally, I’ve installed the latest version of Teslapy on my Homeseer PC and using Craig’s code and method above I can set the reserve % to charge the Powerwall overnight. Homeseer is my preferred system anyway so I’ll stick with this.

This integration still works for me on latest version of HA. However I am using email address and the token as username and password.

I manually generate a token from teslafi each month.

Not ideal, but it works until anyone wishes to own this add on. It’s too complex for me, but it would be a shame not to have it working.

For me I just wish I now knew how to access a couple of other sensors on the local gateway, namely instant voltage.

mine stopped working too. I don’t think anyone is maintaining this anymore as I haven’t seen @estebanp around in some time. I just want my PW to go to 100 reserve before my car charges, then back to 25 when it is done so I don’t drain and add cycles to the PW unnecessarily.

Is there something else that will do this even outside of HA?

Mine and my father in-law’s setup have stopped working too. We were using the original setup and we were not using a Tesla API Token. I have tried to follow the instructions for to add the Tesla API token as explained by @craigrouse and when I get to the stage of running the tesla-auth.py I get an ‘OSError: Could not find a suitable TLS CA certificate bundle error.’ Any ideas?

I assume this still works as @Hodor has said their setup is still working, but has to refresh the token every month. It would be better if Tesla just added the function to fully charge the battery in the app.

TIA

Sorry I have been offline for some time.

I also got it offline and was able to workaround it. Seems TeslaPy was using a method to login that Tesla completely removed. Now it has to go through their web login (this is where all the other Tesla integrations were breaking).
To get it to work again:

  1. Update TeslaPy to 2.3.0: go to custom_components/tesla_gateway/manifest.json, look for the requirements line, it should look like:
"requirements": ["teslapy==2.3.0"],
  1. In custom_components/tesla_gateway/__init__.py, remove the password from being passed to the TeslaPy constructor, replace something that looks like
tesla = teslapy.Tesla(domain_config[CONF_USERNAME], domain_config[CONF_PASSWORD])

with

tesla = teslapy.Tesla(domain_config[CONF_USERNAME])

(Just remove the second parameter being passed)
3. In some machine (not necessary to do in the same as homeassistant), install teslapy and pywebview:

python3 -m pip install teslapy
python3 -m pip install pywebview 
  1. Create a py file (I named it tesla_login.py) with the following contents:
import webview
import teslapy

def custom_auth(url):
    result = ['']
    window = webview.create_window('Login', url)
    def on_loaded():
        result[0] = window.get_current_url()
        if 'void/callback' in result[0].split('?')[0]:
            window.destroy()
    window.loaded += on_loaded
    webview.start()
    return result[0]

with teslapy.Tesla('<fill with the tesla's account email>', authenticator=custom_auth) as tesla:
    tesla.fetch_token()
  1. Replace <fill with the tesla's account email> with the email from your account
  2. execute the py script
python3 ./tesla_login.py
  1. When executing it, it will pop a tesla login page, login. That will generate a cache.json file.
  2. Copy the cache.json file to homeassistant’s conf root (there should be one there) (overwrite it)
  3. Restart HA

Moving forward, we need to integrate the login into HA’s config flow. This will allow this login process to happen within HA. The integration has a way to forward the url and do the login, and HA has a way to integrate such logins: Data Entry Flow | Home Assistant Developer Docs
After that, we could potentially use this same integration for all Tesla-related things (that will be quite some work), and forget about pasting tokens all over the place (tired of having 3 different integrations that constantly break and have to paste tokens in)

Hope that helps,
Esteban

2 Likes

Thanks, @estebanp ! Glad to see you’re back. I made the changes and am getting an error. I was getting this error prior to your changes, so not related to them, but thought that the error was due to them.

When I call the Tesla Gateway: set_operation service under development tools, I get this error:

service: tesla_gateway.set_operation
data:
real_mode: self_consumption
backup_reserve_percent: ‘100’

Failed to call service tesla_gateway.set_operation. Unknown error

Any hints on where I should begin looking?

I suggest enabling the logs and getting a callstack of the error.

Hmm, I haven’t ever seen this one before.

2022-01-17 12:15:40 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Unexpected error for call_service at pos 1: Could not find a suitable TLS CA certificate bundle, invalid path: nXz-Pdt-uxX-B7E
Traceback (most recent call last):
raise IOError("Could not find a suitable TLS CA certificate bundle, "
OSError: Could not find a suitable TLS CA certificate bundle, invalid path: nXz-Pdt-uxX-B7E
2022-01-17 12:15:40 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [2806694936] Error handling message: Unknown error

Ah, sorry about that. In the __init__.py file, remove the password from being passed to the TeslaPy constructor, it should look like:

tesla = teslapy.Tesla(conf_user)

Here’s my init..py. Remove this line? tesla = teslapy.Tesla(domain_config[CONF_USERNAME], domain_config[CONF_PASSWORD])

"""
Monitors and controls the Tesla gateway.
"""
import logging

import asyncio
import voluptuous as vol
import teslapy

from homeassistant.const import (
    CONF_USERNAME,
    CONF_PASSWORD
    )
import homeassistant.helpers.config_validation as cv

DOMAIN = 'tesla_gateway'

_LOGGER = logging.getLogger(__name__)

CONFIG_SCHEMA = vol.Schema({
    DOMAIN: vol.Schema({
        vol.Required(CONF_USERNAME): cv.string,
        vol.Required(CONF_PASSWORD): cv.string
    }),
}, extra=vol.ALLOW_EXTRA)

@asyncio.coroutine
def async_setup(hass, config):

    domain_config = config[DOMAIN]
    conf_user = domain_config[CONF_USERNAME]
    conf_password = domain_config[CONF_PASSWORD]
    
    tesla = teslapy.Tesla(domain_config[CONF_USERNAME], domain_config[CONF_PASSWORD])

    def get_battery():
        batteries = tesla.battery_list()
        if len(batteries) > 0:
            return batteries[0]
        else:
            return None

    @asyncio.coroutine
    async def set_operation(service):
        
        battery = await hass.async_add_executor_job(get_battery)
        if not battery:
            _LOGGER.warning('Battery object is None')
            return None

        await hass.async_add_executor_job(battery.set_operation, service.data['real_mode'])
        if 'backup_reserve_percent' in service.data:
            await hass.async_add_executor_job(battery.set_backup_reserve_percent, service.data['backup_reserve_percent'])

    hass.services.async_register(DOMAIN, 'set_operation', set_operation)

    @asyncio.coroutine
    async def set_reserve(service):
        
        battery = await hass.async_add_executor_job(get_battery)
        if not battery:
            _LOGGER.warning('Battery object is None')
            return None
            
        if 'backup_reserve_percent' in service.data:
            await hass.async_add_executor_job(battery.set_backup_reserve_percent, service.data['backup_reserve_percent'])

    hass.services.async_register(DOMAIN, 'set_reserve', set_reserve)

    return True

do not remove, replace:

tesla = teslapy.Tesla(domain_config[CONF_USERNAME], domain_config[CONF_PASSWORD])

with

tesla = teslapy.Tesla(domain_config[CONF_USERNAME])

it’s working now. you’re the best, Esteban!

1 Like

that’s all great, thanks !
I’d got most of the way there by trial and error, but hadn’t taken out the password bit of init.

Hello, I was originally getting the error ‘Failed to call service tesla_gateway.set_operation. Unknown error’ but changed my init.py to this

tesla = teslapy.Tesla(domain_config[CONF_USERNAME])

However when I fire this event

service: tesla_gateway.set_reserve
data_template:
backup_reserve_percent: 0

I now get this error

Unable to find service tesla_gateway.set_reserve

As always any thoughts would be appreciated.

Update
Have removed the various integrations, restarted, re-added the integrations and amended the 2 tesla_gateway files as above, again restarted, and all now looks good…if in doubt go back to the beginning, lol

I have modified init.py and manifest.json, generated the cache.json and copied it the the config directory, but I still get this during boot up:

2022-02-09 07:23:32 ERROR (MainThread) [homeassistant.setup] Error during setup of component tesla_gateway
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/setup.py", line 227, in _async_setup_component
result = await task
File "/usr/local/lib/python3.9/asyncio/coroutines.py", line 124, in coro
res = func(*args, **kw)
File "/config/custom_components/tesla_gateway/__init__.py", line 30, in async_setup
domain_config = config[DOMAIN]
KeyError: 'tesla_gateway'

Any suggestions?

I added this python script to my config directory and it runs fine:

import teslapy
with teslapy.Tesla('[email protected]') as tesla:
    if tesla.authorized:
        vehicles = tesla.vehicle_list()
        print(vehicles[0])

so I know the cache.json file is correct.

I’m relatively new to HA and very new to adding custom components. Is the config directory not the place the cache.json file is supposed to go? I could not find any directory called “conf”, so I assumed it was short hand for “config”.

I managed to get around the “async_setup_component” issue by using the init.py posted by
@craigrouse, renamed __init__.py and with all parameters but the email address removed in the teslapy.Tesla() calls, as described by @estebanp

I generated the cache.json file using the method from @estebanp, and placed it in the /config directory.

It now works perfectly. Thanks for all the info posted here.

Just got powerwalls and trying to control them so I can utilize super off peak rates. I am a bit lost in the thread there - could someone kindly educate me on what the current status is? I have the powerwall integration working but seems to be read only sensor data. Is it possible to set values currently? If so, what is the best way to do it? Anything available through HACS?

I used TeslaPy to generate a cache.json file using the SSO token refresh mechanism, and then followed these two posts to patch the addon.

Initially got a rate limit error, restarted HA 24h later, and it’s been working for 24h. I’m not using HA to control. I’m using teslapy scripts to set my battery reserve levels based on my time of use rates. Here’s what it looks like on my Linux server.

username@hostnamename:~$ git clone https://github.com/tdorssers/TeslaPy
Cloning into 'TeslaPy'...

username@hostnamename:~$ cd TeslaPy/

username@hostnamename:~/TeslaPy$ pip install -r requirements.txt
<lots of output>

username@hostnamename:~/TeslaPy$ vi tesla_auth.py
import teslapy
with teslapy.Tesla('[email protected]') as tesla:
    if not tesla.authorized:
        tesla.refresh_token(refresh_token=input('Enter SSO refresh token: '))
        vehicles = tesla.vehicle_list()
        print(vehicles[0])


username@hostnamename:~/TeslaPy$ python3 tesla_auth.py
/usr/lib/python3/dist-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (1.26.8) or chardet (3.0.4) doesn't match a supported version!
  warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "
Enter SSO refresh token: <input my token>

<output with my vehicle info>

Now you have a cache.json you can plug into the patched HA powerwall addon.


username@hostnamename:~/TeslaPy$ vi powerwall_set_battery_020percent.py
import teslapy
with teslapy.Tesla("[email protected]") as tesla:
        tesla.fetch_token()
        battery = tesla.battery_list()[0]
        battery.set_backup_reserve_percent(20)
        #print(battery) # should print battery status once successfully authenticated
        #print(battery.get_battery_data()['backup'])

username@hostnamename:~/TeslaPy$ vi powerwall_set_battery_100percent.py
import teslapy
with teslapy.Tesla("[email protected]") as tesla:
        tesla.fetch_token()
        battery = tesla.battery_list()[0]
        battery.set_backup_reserve_percent(100)
        #print(battery) # should print battery status once successfully authenticated
        #print(battery.get_battery_data()['backup'])

username@hostnamename:~/TeslaPy$ vi tesla_test.py
import teslapy
with teslapy.Tesla("[email protected]") as tesla:
        tesla.fetch_token()
        battery = tesla.battery_list()[0]
        print(battery.get_battery_data())
        vehicles = tesla.vehicle_list()
        print(vehicles[0])


username@hostnamename:~/TeslaPy$ crontab -e

#Mon-Fri at 9:01pm, set battery reserve to 100 percent
1 21 * * 1-5 cd /home/username/TeslaPy/ && /usr/bin/python3 powerwall_set_battery_100percent.py

#Mon-Fri at 6:59am, set battery reserve to 20 percent
59 6 * * 1-5 cd /home/username/TeslaPy/ && /usr/bin/python3 powerwall_set_battery_020percent.py

#Saturday at 9am, update, test, and refresh the integration
00 9 * * 6 cd /home/username/TeslaPy/ && git pull && /usr/bin/python3 tesla_test.py && /usr/bin/python3 powerwall_set_battery_100percent.py
1 Like