Add support for Tesla Powerwall

yes, TeslaPy has operation mode and reserve setting.

1 Like

That is indeed excellent news. Thanks for your hard work. Looking to giving it a try.

you are the best, Esteban!

Here is a beta version that works for me.

For those that have it failing, give it a try and report back.
You need to update two files:

  1. in manifest.json:
{
  "domain": "tesla_gateway",
  "name": "Tesla Gateway",
  "documentation": "",
  "dependencies": [],
  "codeowners": [],
  "requirements": ["teslapy==1.1.0"],
  "version": "0.1.0"
}

The ā€œrequirementsā€ there is very important.

  1. in __init__.py:
"""
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

Once we validate that this works by a couple of people over a couple of days I will upload it to GitHub - carboncoop/tesla-gateway-ha-component: A Home Assistant component to control Tesla Powerwall.

1 Like

Well done! I can confirm its working on my setup! Backed up and replaced the files with the configuration above and its working again. I have tested going from self powered mode 10% reserve to backup 100% reserve and back again. I have also tested going from self powered mode 10% reserve to 25% reserve, then 50% reserve, then back to 10% reserve. Thanks for getting this working!

It is working for me as well :wink:
Very many thanks for your work.

Added TeslaPy and updated as above.

Can confirm all working as expected now.

Great work, many thanks, appreciated.

Yep working for me as well! Top work man

Sorry to be asking a basic question but Iā€™m very new to HA and although I had this integration working perfectly Iā€™m not clear on how to update init.py (I presume I simply replace the text in manifest.json)

Iā€™ve tried to replace init.py with the next text but the integration wonā€™t start so I presume this is incorrect.

Please can anyone advise this newbie as I really want to get this working again. Thanks

yes, replacing the code in __init__.py with the one above + the manifest.json is all you have to do.
What error do you get?

I restarted HA and in the notifications I get:

Invalid config
The following integrations and platforms could not be set up:

  • tesla_gateway
    Please check your config and [logs]ā€¦

And when I view the integrations, the Tesla Gateway integration has a red border with the message:

Not loaded, check the logs.

The log says:
2021-04-28 15:20:56 WARNING (MainThread) [homeassistant.loader] You are using a custom integration tesla_gateway which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant

Does this latest teslapy version work with MFA / 2FA ?
Or do I still need to do a fudge of getting the token in manually ?

It looks like the teslapy code does support MFA, is there any way of passing the MFA token into this tesla-gateway code ?

For now, Iā€™ve done another fudge.
Removed MFA from my account.
Got the latest tesla_gateway code running.

Switched MFA back on.
Manually generated a key and refresh key.
Manually put these into the cache.json file.

It seems to work, so itā€™ll do for now.
Will be interesting to see if it refreshes the token successfully when it expires ?
I suspect it wonā€™t.

Is it achievable to get MFA implemented in this tesla_gateway script, the codes seems to exist in teslapy but itā€™s way beyond my abilities.

this works for me!

thats weird, it should not show in the integrations page since it doesnt have a pageflow. The setup of it has to be done through yaml configs (configuration.yaml).
Can you turn on the log for that integration and find what other messages are in the log? The one you sent is benign, is basically stating that is a custom integration.
To enable the log, add this to your configuration.yaml

logger:
  logs:
    custom_components.tesla_gateway: debug

Yes, its possible, TeslaPy supports itā€¦ however, I dunno how that will work in HA and long term. In theory, if the token is kept and renewed, you shouldnt need to re-authenticate with the MFA.
However, if the token expires, you would have to re-authenticateā€¦

Usually APIs provide ā€œapi passwordsā€ to bypass MFA, but I dont see Tesla providing that. It will also may not give you enough time to put itā€¦ if you put the MFA code in your configuration.yaml and reboot, it may be expired by the time is used (those things expire pretty quickly). We would have to add a configflow (those ā€œcardsā€ in the integrations page) so it is loaded dynamically without rebooting.

With configflow, the integration would just need to pass the passcode on the 3rd parameter of:

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

You can test it by adding a MFA token there, you will have to add some more code, search for CONF_PASSWORD and replicate for your config entry. Likely, the MFA token will be expired by the time is used, so you may need to add all the configflow thing.

I did try putting the OTP in that line and updating the file while HA booted.
I wasnā€™t sure if I needed to add it as lambda: ā€˜123456ā€™ or just as ā€˜123456ā€™
I couldnā€™t get it to work which is why I resorted to manually changing the cache.json file.

In the long term if this code could move to a config flow, that would be fab, but itā€™s currently beyond me.
Maybe this is my time to learn this stuff and have a go !

give it a go!, I will try to add it whenever I have some more timeā€¦

I am trying to fix other stuff in my HA: the Tesla integration and now fighting with a rainforest energy metering device that hangs every other day.
Since this is now working for me, it went down in the priority list :sweat_smile:

This code works for me.
(with MFA off).

The set_reserve service doesnā€™t seem to work.
But you can set the reserve with the set_operation service.

Is this intentional that set_reserve doesnā€™t work any more ?

Not intentional, if look at to the code is actually calling the same code from teslapy, maybe there is something weird under the hood there when just that API is calledā€¦

Do you get any error there in the log? did you double check to be calling it with the right backup_reserve_percent parameter?
I will check it whenever I have some time