Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple local Tesla Energy Gateways (Powerwall/Inverters) using the server for local or cloud access #119

Open
Nexarian opened this issue Dec 6, 2024 · 9 comments

Comments

@Nexarian
Copy link
Contributor

Nexarian commented Dec 6, 2024

I'm referencing this line: TODO: Add support for multiple Powerwalls

As I have two side-by-side (SxS) Tesla 7.6 kw inverters, this feature is a must for me if I'm going to monitor my system using Powerwall dashboard, especially important is TEDAPI mode and a facility to alternate network routes to interleave data from the two.

This issue is to track development. I intend to tackle this myself.

@Nexarian
Copy link
Contributor Author

The first step was to solve the ability to query two Tesla Energy Gateways on a LAN by using variations in NAT: #128 (comment)

The second is to get the pypowerwall proxy server to be able to handle multiple gateways. I am working on this, but it's not done yet: Draft PR

Essentially the proxy server needs to compartmentalize each inverter into its own separate proxy server and then route each request from the virtual IPs configured in the scripts above. That simply requires a ton of refactoring and modularization.

@jasonacox
Copy link
Owner

@Nexarian 🙇 The draft looks good! Thanks for kicking that off and for the much needed refactoring. I'll put my additional comments in the PR.

@Nexarian
Copy link
Contributor Author

Nexarian commented Jan 11, 2025

@jasonacox Still not quite finished! I've been going through it line-by-line, doing my best to preserve functionality while increasing modularity and maintainability. I also haven't actually tested this yet, because this refactor is so invasive I can't really do that until I'm finished.

The main points in the PR are:

  • Remove all important state from global variables. Instead, things like config, pypowerwall, and the like will be accessed as class members of the Handler (or perhaps another class after an additional refactor) and/or function arguments.
  • Because things are now compartmentalized/modularized, accessing more than one TEG is a matter of setting up a loop.

A few things things I'm still not sure yet is how to handle:

  • proxystats. They seem to be a bit ad-hoc as to when they are manipulated and when they're not.
  • How to actually read configuration for each TEG/Pypowerwall object. What I'm moving towards is an "INI"-like file format, that lists each:
[Powerwall 1]
var=value
...
[Powerwall 2]
var=value
...

However, we could conceivably move this to JSON or YAML as well, but that's likely to break many things.

Thanks for your support on this, it's taking me forever to get this honed in! Several late nights of coding so far!

Also: I understand that a massive refactor like this is a big pill to swallow. I'm happy to "part out" the finished version into more digestible chunks so we migrate the server to the final result slowly, while I continue to test the full version on my own systems.

@jasonacox
Copy link
Owner

jasonacox commented Jan 11, 2025

Thanks @Nexarian - I haven't seen anything otherwise, but please keep these project design principles in mind:

  • Simplicity over Cleverness - As a open source repo, our bias should be easy to read and maintain, simple as possible, not clever structures or approaches that may be more efficient or concise but difficult to read. We have a lot of first time contributors who are just learning python. I think that indicates we have done a good job at keeping it simple enough to understand for those learning to code.
  • Maintain API - Changes should not require existing installations to change their approach or use of the tool/library. When API changes are needed, they should be justified, documented and as much as possible, avoided or mitigated for easier adoption.

Note on your suggested refactoring - for the most part I think these make it more readable, just to be clear.

A few things things I'm still not sure yet is how to handle:

  • Proxystats - this is a troubleshooting tool and intent is to represent config, calls and errors (operational metrics) - open to new ways to capture and serve, but this is an expected feature we would want to maintain.
  • Config settings - we should maintain the environmental variables as a way to pass the config settings into the container. That doesn't mean we can't include a new variable that has a JSON payload. If that variable is not null, it can be set to override the singleton approach from the existing env vars.

I'm happy to "part out" the finished version into more digestible chunks

We should target MVP so that each incremental is still a working proxy, backward compatible, but could slowly walk toward the final outcome. What is in scope for MVP? I'm having some difficulty thinking what would be broken out unless you are thinking about deeper refactoring.

@Nexarian
Copy link
Contributor Author

For me, at least, the MVP is the proxy can handle two simultaneous calls (using the virtual IPs above) to retrieve internal TEG/string data in such a way that two sets of string data/internal TEG data can show up on the Powerwall dashboard. Each inverter has its own TEG rather than a standalone Gateway like most Powerwall setups have. Why Tesla chose that route, I'm not sure, but it's what makes my situation harder.

As you mentioned the other way to do this might be to simply have two containers that report into InfluxDB, or to multiplex them with my earlier solution that alternates static routes. My solution is certainly "fancier" and thus may violate simplicity over cleverness. Still, I don't think it unreasonable to say the system should support querying multiple TEGs simultaneously without fancy Docker manipulation (which might ALSO be a violation of that principle).

MVP is two because I have two, but really the longer-term goal should be N (multiple).

As to the config, I will write it such a way that a simple "one TEG" setup will work, but it will also read multiple as well. Similar to how a black & white TV can read a color signal :)

I am actually not planning on changing the API other than supporting multiple TEGs.

@Nexarian
Copy link
Contributor Author

As to how to part it out, I think there are multiple phases:

  1. Move global variables into a more structured format (Mainly config and proxy stats)
  2. Change the post and get handlers to use functions with a dictionary selector rather than a gigantic if block.
  3. Use this modularization to support multiple TEGs.

In no step would the API or functionality change, except for the expansion in the last one.

@jasonacox
Copy link
Owner

Yes, I agree with you. There are several in the community that have multiple gateways (very larger systems) so this enhancement would work for them as well.

The complexity concern is more related to the code readability than the functions. I think your proposal is very reasonable.

@Nexarian
Copy link
Contributor Author

The server.py refactor now works on my Raspberry PI; at least, it does for local access. I decided against using a config file given the way that environmental variables are used. You can simply do this:

PW_DEBUG=no
TZ=America/New_York

# Inverter 1
export PW_EMAIL_1=email@email.com
export PW_PASSWORD_1=
export PW_GW_PWD_1=GATEWAY_PASSWORD
export PW_HOST_1=VIRTUAL_IP
export PW_PORT_1=8675
export PW_TIMEZONE_1=America/New_York
export PW_STYLE_1=solar

# Inverter 2
export PW_EMAIL_2=email@email.com
export PW_PASSWORD_2=
export PW_GW_PWD_2=GATEWAY_PASSWORD
export PW_HOST_2=VIRTUAL_IP
export PW_PORT_2=8676
export PW_TIMEZONE_2=America/New_York
export PW_STYLE_2=solar

I will continue testing. Feel free to check it out now!

@jasonacox
Copy link
Owner

I love that approach @Nexarian - I was worried about the config file as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants