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

V4.4.0 - Vitals and FleetAPI #479

Merged
merged 5 commits into from
Jun 8, 2024
Merged

V4.4.0 - Vitals and FleetAPI #479

merged 5 commits into from
Jun 8, 2024

Conversation

jasonacox
Copy link
Owner

Updates

TEDAPI Support for Device Vitals

  • Add TEDAPI Support for Extended Device Metrics (the return of most of /vitals) - This requires connecting to Powerwall WiFi directly or setting up a network route on the Dashboard host to allow it to reach the GW address (192.168.91.1). See discussion (more helps soon).
  • Run upgrade.sh and then run setup.sh to choose these new options.

FleetAPI Support

  • Add support for Tesla's official API, FleetAPI. This requires additional registration and configuration. Instructions are part of setup process or on the project page.
  • Run upgrade.sh and then run setup.sh to choose these new options.

Other Updates

The Return of Vitals

image

image

@jgleigh
Copy link

jgleigh commented Jun 3, 2024

@jasonacox Are the alerts supposed to look like they're active from now until infinity or is that just a consequence of adding them back in.

Seven strings again! Finally!!!

@jgleigh
Copy link

jgleigh commented Jun 3, 2024

jasonacox/pypowerwall:0.10.0t58-beta9

Any way to provide some better error reporting so we can figure out what is causing these issues, even though they're intermittent? i.e., is the packet malformed or something else getting corrupted?

2024-06-03 06:31:47 ----------------------------------------
2024-06-03 06:31:47 Exception occurred during processing of request from ('172.18.0.5', 41194)
2024-06-03 06:31:47 Traceback (most recent call last):
2024-06-03 06:31:47   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 06:31:47     self.finish_request(request, client_address)
2024-06-03 06:31:47   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 06:31:47     self.RequestHandlerClass(request, client_address, self)
2024-06-03 06:31:47   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 06:31:47     self.handle()
2024-06-03 06:31:47   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 06:31:47     self.handle_one_request()
2024-06-03 06:31:47   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 06:31:47     method()
2024-06-03 06:31:47   File "/app/server.py", line 387, in do_GET
2024-06-03 06:31:47     alerts = pw.alerts()
2024-06-03 06:31:47   File "/app/pypowerwall/__init__.py", line 561, in alerts
2024-06-03 06:31:47     devices: dict = self.vitals() or {}
2024-06-03 06:31:47   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 06:31:47     output = self.client.vitals()
2024-06-03 06:31:47   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 06:31:47     return self.tedapi.vitals()
2024-06-03 06:31:47   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 06:31:47     num = len(lookup(status, ['esCan', 'bus', 'PVAC']))
2024-06-03 06:31:47   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 06:31:47     if key in data:
2024-06-03 06:31:47 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 06:31:47 ----------------------------------------

@jasonacox
Copy link
Owner Author

jasonacox commented Jun 4, 2024

@jasonacox Are the alerts supposed to look like they're active from now until infinity or is that just a consequence of adding them back in.

These are active alerts from the Powerwall. They stay active until the Powerwall clears them. This is what we had before (with vitals). Below is a glimpse of my system for past 24 hours. The ones that are solid all the time make sense (e.g.connect to grid) while others are intimement (e.g. solar RGM comms issues) which could indicate a problem. The RGM comms is something that caused me troubles in the past and I lost the view when vitals went away.

The alert time series graph is different from others. A good way to think about it is that you have a dashboard with a bunch of indicator lights that can flicker on and off. You may miss them change state. But when it is stretched over a time graph, you can see when those blips happen.

image

any way to provide some better error reporting

Actually, what you provided is perfect. I know what happened (line 400 of the tedapi library) where one of the JSON walks ('esCan', 'bus', 'PVAC') has a step that is None. I can fix that. Thanks for sending that! Let me know if you see others. 🙏

@jgleigh
Copy link

jgleigh commented Jun 4, 2024

Here's some more that looks slightly different in case that's helpful:

2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05 Exception occurred during processing of request from ('172.18.0.5', 40508)
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05 Exception occurred during processing of request from ('172.18.0.5', 40526)
2024-06-03 19:17:05 Traceback (most recent call last):
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05 Traceback (most recent call last):
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 19:17:05     self.finish_request(request, client_address)
2024-06-03 19:17:05 Exception occurred during processing of request from ('172.18.0.5', 40538)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 19:17:05     self.RequestHandlerClass(request, client_address, self)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 19:17:05     self.handle()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 19:17:05     self.finish_request(request, client_address)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 19:17:05     self.RequestHandlerClass(request, client_address, self)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 19:17:05     self.handle()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 19:17:05     self.handle_one_request()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 19:17:05     method()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 19:17:05     self.handle_one_request()
2024-06-03 19:17:05 Exception occurred during processing of request from ('172.18.0.5', 40548)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 19:17:05     method()
2024-06-03 19:17:05   File "/app/server.py", line 478, in do_GET
2024-06-03 19:17:05     vitals = pw.vitals() or {}
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 19:17:05     output = self.client.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 19:17:05     return self.tedapi.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 19:17:05     num = len(lookup(status, ['esCan', 'bus', 'PVAC']))
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 19:17:05     if key in data:
2024-06-03 19:17:05 Traceback (most recent call last):
2024-06-03 19:17:05   File "/app/server.py", line 387, in do_GET
2024-06-03 19:17:05     alerts = pw.alerts()
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 561, in alerts
2024-06-03 19:17:05     devices: dict = self.vitals() or {}
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 19:17:05     self.finish_request(request, client_address)
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 19:17:05     output = self.client.vitals()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 19:17:05     self.RequestHandlerClass(request, client_address, self)
2024-06-03 19:17:05 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 19:17:05 Traceback (most recent call last):
2024-06-03 19:17:05   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 19:17:05     return self.tedapi.vitals()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 19:17:05     self.handle()
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 19:17:05     num = len(lookup(status, ['esCan', 'bus', 'PVAC']))
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 19:17:05     self.finish_request(request, client_address)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 19:17:05     self.handle_one_request()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 19:17:05     method()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 19:17:05     self.RequestHandlerClass(request, client_address, self)
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 19:17:05     if key in data:
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 19:17:05     self.handle()
2024-06-03 19:17:05   File "/app/server.py", line 345, in do_GET
2024-06-03 19:17:05     message: str = pw.strings(jsonformat=True) or json.dumps({})
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 375, in strings
2024-06-03 19:17:05     v: dict = self.vitals() or {}
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 19:17:05     output = self.client.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 19:17:05     return self.tedapi.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 19:17:05     num = len(lookup(status, ['esCan', 'bus', 'PVAC']))
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 19:17:05     if key in data:
2024-06-03 19:17:05 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 19:17:05 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 19:17:05     self.handle_one_request()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 19:17:05     method()
2024-06-03 19:17:05   File "/app/server.py", line 415, in do_GET
2024-06-03 19:17:05     vitals = pw.vitals() or {}
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 19:17:05     output = self.client.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 19:17:05     return self.tedapi.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 19:17:05     num = len(lookup(status, ['esCan', 'bus', 'PVAC']))
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 19:17:05     if key in data:
2024-06-03 19:17:05 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05 ----------------------------------------
2024-06-03 19:17:05 Exception occurred during processing of request from ('172.18.0.5', 40554)
2024-06-03 19:17:05 Traceback (most recent call last):
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 19:17:05     self.finish_request(request, client_address)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 19:17:05     self.RequestHandlerClass(request, client_address, self)
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 19:17:05     self.handle()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 19:17:05     self.handle_one_request()
2024-06-03 19:17:05   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 19:17:05     method()
2024-06-03 19:17:05   File "/app/server.py", line 375, in do_GET
2024-06-03 19:17:05     temps = pw.temps()
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 543, in temps
2024-06-03 19:17:05     devices: dict = self.vitals() or {}
2024-06-03 19:17:05   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 19:17:05     output = self.client.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 19:17:05     return self.tedapi.vitals()
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 19:17:05     num = len(lookup(status, ['esCan', 'bus', 'PVAC']))
2024-06-03 19:17:05   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 19:17:05     if key in data:
2024-06-03 19:17:05 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 19:17:05 ----------------------------------------

@jasonacox
Copy link
Owner Author

Thanks @jgleigh - those are caused by the same error, unfortunately. It's really blowing up big when it goes.

I pushed a patch and now a new version if you want to try it:

jasonacox/pypowerwall:0.10.1t58-beta

@jasonacox
Copy link
Owner Author

jasonacox commented Jun 4, 2024

For any who want to help beta test before 4.4.0 is released:

Testing - Using pyPowerwall with Vitals

Add Network Route

First, you need to set up the host that will run your Dashboard to have a route to your Powerwall Gateway. This will vary based on your network and OS. If your host is able to ping your Powerwall on your LAN (e.g. 10.x.x.x) you can do something like this:

# Linux & RPi
sudo ip route add 192.168.91.1 via <Powerwall_IP>

# MacOS
sudo route add -host 192.168.91.1 <Powerwall_IP>

# Windows
route add 192.168.91.1 mask 255.255.255.255 <Powerwall_IP>

# Test
ping -c 1 192.168.91.1 

# Note: This is a temporary route. To make it survive a reboot, you need to set it in the system
# or add it to something like /etc/rc.local 

Update Dashboard Install

Edit the powerwall.yml file and replace the image name for pypowerwall to jasonacox/pypowerwall:0.10.1t58-beta2
like this:

...
    pypowerwall:
        image: jasonacox/pypowerwall:0.10.1t58-beta2
        container_name: pypowerwall
        hostname: pypowerwall
        restart: unless-stopped
...

Edit pypowerwall.env and change the IP address to 192.168.91.1 and add the PW_GW_PWD setting. The PW_GW_PWD password is the Gateway WiFi password usually located by the QR code on the Powerwall Gateway itself.

PW_HOST=192.168.91.1
PW_GW_PWD="GW_PASSWORD"

Apply the changes using:

./compose-dash.sh up -d

# and to tail the logs... ^C to quit
docker logs pypowerwall -f

Welcome Back Vitals

Enjoy getting extended vitals metrics back: Strings, Powerwall Capacity, Alerts

image

@jgleigh
Copy link

jgleigh commented Jun 4, 2024

@jasonacox Still getting errors:

Also noticed all the meters are reporting as solarRGM and null firmware, which isn't correct. Not sure if this is a parsing issue or something else.

    "NEURIO--VAH4644AB6358": {
        "NEURIO_CT0_InstRealPower": -8.029999732971191,
        "NEURIO_CT0_Location": "solarRGM",
        "NEURIO_CT1_InstRealPower": -0.05000000074505806,
        "NEURIO_CT1_Location": "solarRGM",
        "NEURIO_CT2_InstRealPower": -0.05999999865889549,
        "NEURIO_CT2_Location": "solarRGM",
        "NEURIO_CT3_InstRealPower": -0.05000000074505806,
        "NEURIO_CT3_Location": "solarRGM",
        "componentParentDin": "1232100-00-E--TG121188000GLX",
        "firmwareVersion": null,
        "lastCommunicationTime": "2024-06-04T04:51:02-07:00",
        "manufacturer": "NEURIO",
        "meterAttributes": {
            "meterLocation": []
        },
        "serialNumber": "VAH4644AB6358"
    },
    "NEURIO--VAH4600AB1821": {
        "NEURIO_CT0_InstRealPower": 334.5799865722656,
        "NEURIO_CT0_Location": "solarRGM",
        "NEURIO_CT1_InstRealPower": 265.9100036621094,
        "NEURIO_CT1_Location": "solarRGM",
        "NEURIO_CT2_InstRealPower": -0.029999999329447746,
        "NEURIO_CT2_Location": "solarRGM",
        "NEURIO_CT3_InstRealPower": -0.10000000149011612,
        "NEURIO_CT3_Location": "solarRGM",
        "componentParentDin": "1232100-00-E--TG121188000GLX",
        "firmwareVersion": null,
        "lastCommunicationTime": "2024-06-04T04:51:02-07:00",
        "manufacturer": "NEURIO",
        "meterAttributes": {
            "meterLocation": []
        },
        "serialNumber": "VAH4600AB1821"
    },
    "NEURIO--VAH4602AB1827": {
        "NEURIO_CT0_InstRealPower": -11.140000343322754,
        "NEURIO_CT0_Location": "solarRGM",
        "NEURIO_CT1_InstRealPower": 0.07999999821186066,
        "NEURIO_CT1_Location": "solarRGM",
        "NEURIO_CT2_InstRealPower": -0.05999999865889549,
        "NEURIO_CT2_Location": "solarRGM",
        "NEURIO_CT3_InstRealPower": -0.029999999329447746,
        "NEURIO_CT3_Location": "solarRGM",
        "componentParentDin": "1232100-00-E--TG121188000GLX",
        "firmwareVersion": null,
        "lastCommunicationTime": "2024-06-04T04:51:02-07:00",
        "manufacturer": "NEURIO",
        "meterAttributes": {
            "meterLocation": []
        },
        "serialNumber": "VAH4602AB1827"
    },
2024-06-03 21:01:03 ----------------------------------------
2024-06-03 21:01:03 Exception occurred during processing of request from ('172.18.0.5', 59974)
2024-06-03 21:01:03 Traceback (most recent call last):
2024-06-03 21:01:03   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 21:01:03     self.finish_request(request, client_address)
2024-06-03 21:01:03   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 21:01:03     self.RequestHandlerClass(request, client_address, self)
2024-06-03 21:01:03   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 21:01:03     self.handle()
2024-06-03 21:01:03   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 21:01:03     self.handle_one_request()
2024-06-03 21:01:03   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 21:01:03     method()
2024-06-03 21:01:03   File "/app/server.py", line 345, in do_GET
2024-06-03 21:01:03     message: str = pw.strings(jsonformat=True) or json.dumps({})
2024-06-03 21:01:03   File "/app/pypowerwall/__init__.py", line 375, in strings
2024-06-03 21:01:03     v: dict = self.vitals() or {}
2024-06-03 21:01:03   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 21:01:03     output = self.client.vitals()
2024-06-03 21:01:03   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 21:01:03     return self.tedapi.vitals()
2024-06-03 21:01:03   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 21:01:03     num = len(lookup(status, ['esCan', 'bus', 'PVAC']) or {})
2024-06-03 21:01:03   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 21:01:03     if key in data:
2024-06-03 21:01:03 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 21:01:03 ----------------------------------------
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15 Exception occurred during processing of request from ('172.18.0.5', 34686)
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15 Exception occurred during processing of request from ('172.18.0.5', 34690)
2024-06-03 21:12:15 Traceback (most recent call last):
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 21:12:15     self.finish_request(request, client_address)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 21:12:15     self.RequestHandlerClass(request, client_address, self)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 21:12:15     self.handle()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 21:12:15     self.handle_one_request()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 21:12:15     method()
2024-06-03 21:12:15   File "/app/server.py", line 345, in do_GET
2024-06-03 21:12:15     message: str = pw.strings(jsonformat=True) or json.dumps({})
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 375, in strings
2024-06-03 21:12:15     v: dict = self.vitals() or {}
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15 Exception occurred during processing of request from ('172.18.0.5', 34708)
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 21:12:15     output = self.client.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 21:12:15     return self.tedapi.vitals()
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15 Traceback (most recent call last):
2024-06-03 21:12:15 Traceback (most recent call last):
2024-06-03 21:12:15 Exception occurred during processing of request from ('172.18.0.5', 34706)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 21:12:15     self.finish_request(request, client_address)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 21:12:15     self.finish_request(request, client_address)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 21:12:15     self.RequestHandlerClass(request, client_address, self)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 21:12:15     self.handle()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 21:12:15     self.handle_one_request()
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15 Exception occurred during processing of request from ('172.18.0.5', 34720)
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 21:12:15     num = len(lookup(status, ['esCan', 'bus', 'PVAC']) or {})
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 21:12:15     if key in data:
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 21:12:15     method()
2024-06-03 21:12:15 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 21:12:15 Traceback (most recent call last):
2024-06-03 21:12:15   File "/app/server.py", line 415, in do_GET
2024-06-03 21:12:15     vitals = pw.vitals() or {}
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 21:12:15     self.RequestHandlerClass(request, client_address, self)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 21:12:15     self.handle()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 21:12:15     self.handle_one_request()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 21:12:15     method()
2024-06-03 21:12:15   File "/app/server.py", line 387, in do_GET
2024-06-03 21:12:15     alerts = pw.alerts()
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 561, in alerts
2024-06-03 21:12:15     devices: dict = self.vitals() or {}
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 21:12:15     output = self.client.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 21:12:15     return self.tedapi.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 21:12:15     num = len(lookup(status, ['esCan', 'bus', 'PVAC']) or {})
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 21:12:15     if key in data:
2024-06-03 21:12:15 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15 Traceback (most recent call last):
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 21:12:15     self.finish_request(request, client_address)
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 21:12:15     output = self.client.vitals()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-03 21:12:15     self.finish_request(request, client_address)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 21:12:15     self.RequestHandlerClass(request, client_address, self)
2024-06-03 21:12:15   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 21:12:15     return self.tedapi.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 21:12:15     num = len(lookup(status, ['esCan', 'bus', 'PVAC']) or {})
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 21:12:15     if key in data:
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-03 21:12:15     self.RequestHandlerClass(request, client_address, self)
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 21:12:15     self.handle()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-03 21:12:15     self.handle()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 21:12:15     self.handle_one_request()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 21:12:15     method()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-03 21:12:15     self.handle_one_request()
2024-06-03 21:12:15   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-03 21:12:15     method()
2024-06-03 21:12:15   File "/app/server.py", line 478, in do_GET
2024-06-03 21:12:15     vitals = pw.vitals() or {}
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 21:12:15     output = self.client.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 21:12:15     return self.tedapi.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 21:12:15     num = len(lookup(status, ['esCan', 'bus', 'PVAC']) or {})
2024-06-03 21:12:15 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 21:12:15     if key in data:
2024-06-03 21:12:15 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 21:12:15   File "/app/server.py", line 375, in do_GET
2024-06-03 21:12:15     temps = pw.temps()
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 543, in temps
2024-06-03 21:12:15     devices: dict = self.vitals() or {}
2024-06-03 21:12:15   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-03 21:12:15     output = self.client.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-03 21:12:15     return self.tedapi.vitals()
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
2024-06-03 21:12:15     num = len(lookup(status, ['esCan', 'bus', 'PVAC']) or {})
2024-06-03 21:12:15   File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
2024-06-03 21:12:15     if key in data:
2024-06-03 21:12:15 ----------------------------------------
2024-06-03 21:12:15 TypeError: argument of type 'NoneType' is not iterable
2024-06-03 21:12:15 ----------------------------------------

@richbaron
Copy link

richbaron commented Jun 4, 2024

Just followed the beta test instructions on my side - the data is back!

  • Vitals have returned on the /vitals endpoint and are displaying in the dashboard as expected.
  • I was able to add the static route on my firewall so any device on the LAN can route to 192.168.91.0/24 via the IP of the Tesla gateway, worked perfect. Happy to help with any instructions relevant to my router/firewall (UniFi)

image

This error seems to occur in the logs every few minutes:


----------------------------------------
Exception occurred during processing of request from ('172.18.0.3', 49302)
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request                                                                                                                             _thread
    self.finish_request(request, client_address)
  File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
    self.handle()
  File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
    self.handle_one_request()
  File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_reque                                                                                                                             st
    method()
  File "/app/server.py", line 478, in do_GET
    vitals = pw.vitals() or {}
  File "/app/pypowerwall/__init__.py", line 355, in vitals
    output = self.client.vitals()
  File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
    return self.tedapi.vitals()
  File "/app/pypowerwall/tedapi/__init__.py", line 400, in vitals
    num = len(lookup(status, ['esCan', 'bus', 'PVAC']) or {})
  File "/app/pypowerwall/tedapi/__init__.py", line 62, in lookup
    if key in data:
TypeError: argument of type 'NoneType' is not iterable
----------------------------------------

@jasonacox
Copy link
Owner Author

@jgleigh - The problem is that we actually are not getting Neurio firmware or location (e.g. SolarRGM) data. The SolarRGM was my bad as I just copied in my old vitals JSON structure and forgot to remove the placeholder. Having said that, can you pull the raw TEDAPI data for me for your Neurios? I added this API to the proxy which will show you the raw data:

Both have Neurio data but not exactly what we had before. I only have 1 so it is a bad sample size.

@richbaron - Thanks for testing! I will take you up on your offer for instructions! Feel free to post here and I'll include in a helps doc or Discussion area for reference.

This error seems to occur in the logs every few minutes:

Yes, for you and @jgleigh - I'm an idiot! 🤦 I changed the logic to handle missing keys in the TEDAPI response but not if the response was Null. I addressed the core lookup() function. Here is the latest patch:

jasonacox/pypowerwall:0.10.1t58-beta3

@jgleigh
Copy link

jgleigh commented Jun 5, 2024

Here you go.
config.json
status.json

@jasonacox
Copy link
Owner Author

jasonacox commented Jun 5, 2024

Thanks @jgleigh ! I got them but removed the links for privacy. Important parts:

status.json

"neurio": {
    "isDetectingWiredMeters": false,
    "pairings": [],
    "readings": [
      {
        "dataRead": [
          {
            "currentA": 3.54999995231628,
            "reactivePowerVAR": -248.949996948242,
            "realPowerW": 316.829986572266,
            "voltageV": 123.269996643066
          },
          {
            "currentA": 3.79999995231628,
            "reactivePowerVAR": -289.380004882813,
            "realPowerW": 347.850006103516,
            "voltageV": 123.660003662109
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": -0.129999995231628,
            "realPowerW": -0.100000001490116,
            "voltageV": 123.669998168945
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": 0.0299999993294477,
            "realPowerW": -0.0599999986588955,
            "voltageV": 123.269996643066
          }
        ],
        "serial": "xxxxxx",
        "timestamp": "2024-06-04T22:06:50-07:00"
      },
      {
        "dataRead": [
          {
            "currentA": 0.150000005960464,
            "reactivePowerVAR": 18.3500003814697,
            "realPowerW": 0.980000019073486,
            "voltageV": 124.620002746582
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": 0.0299999993294477,
            "realPowerW": 0.0500000007450581,
            "voltageV": 124.279998779297
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": -0.0599999986588955,
            "realPowerW": 0.0199999995529652,
            "voltageV": 124.290000915527
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": -0.129999995231628,
            "realPowerW": -0.0199999995529652,
            "voltageV": 124.610000610352
          }
        ],
        "serial": "xxxxx",
        "timestamp": "2024-06-04T22:06:50-07:00"
      },
      {
        "dataRead": [
          {
            "currentA": 0.170000001788139,
            "reactivePowerVAR": 20.2199993133545,
            "realPowerW": 1.35000002384186,
            "voltageV": 123.849998474121
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": -0.0599999986588955,
            "realPowerW": 0.0500000007450581,
            "voltageV": 123.5
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": -0.0599999986588955,
            "realPowerW": 0,
            "voltageV": 123.580001831055
          },
          {
            "currentA": 0.00999999977648258,
            "reactivePowerVAR": 0,
            "realPowerW": -0.0500000007450581,
            "voltageV": 123.819999694824
          }
        ],
        "serial": "xxxx",
        "timestamp": "2024-06-04T22:06:50-07:00"
      }
    ]
  },

config.json

  "meters": [
    {
      "location": "solarRGM",
      "type": "neurio_w2_tcp",
      "cts": [true, false, false, false],
      "inverted": [false, false, false, false],
      "connection": {
        "ip_address": "PWRview-43107",
        "port": 443,
        "short_id": "43107",
        "device_serial": "xxxxx",
        "neurio_connected": true,
        "https_conf": {
          "client_cert": "/var/lib/neurio/neurio.crt",
          "client_key": "/var/lib/neurio/neurio.key",
          "server_ca_cert": "/etc/neurio-ca.crt",
          "server_name": "04-71-4b-04-04-55",
          "max_idle_conns_per_host": 1
        }
      },
      "real_power_scale_factor": 2
    },

I can use the serial numbers to match the device to get "location". Unfortunately, it doesn't look like we can get firmware.

@jgleigh
Copy link

jgleigh commented Jun 5, 2024

The locations in config looked correct. I have four active meters. Two on solar, one in the gateway, and one site on a subpanel. So the gateway plus the site meter equals the real total load.

@jgleigh
Copy link

jgleigh commented Jun 5, 2024

@jasonacox Okay back to the usual corrupted packets. Anyway to better see why these are getting rejected?

2024-06-05 16:32:29 06/05/2024 04:32:29 PM [proxy] [ERROR] Socket broken sending API response to client [doGET]: [Errno 32] Broken pipe

@richbaron
Copy link

richbaron commented Jun 6, 2024

@jasonacox Okay back to the usual corrupted packets. Anyway to better see why these are getting rejected?

2024-06-05 16:32:29 06/05/2024 04:32:29 PM [proxy] [ERROR] Socket broken sending API response to client [doGET]: [Errno 32] Broken pipe

@jgleigh how is your gateway connected? WiFi or hardwired (Ethernet)?

If WiFi, this behavior could be explained through the connection being unstable. I have not seen a similar error since going to either beta release, but my gateway is hardwired.

@jgleigh
Copy link

jgleigh commented Jun 7, 2024

@richbaron Both, but using hardwired for the proxy currently. This has been happening for quite a while, but trying to figure out where the error is getting injected into the packets. I'm curious, does your Ethernet cable enter from the top or the bottom of the Gateway? Mine is routed from the bottom and has to pass by all the AC lines before getting up to the RJ45 jack.

@jasonacox New error popped up today.

2024-06-06 07:07:50 ----------------------------------------
2024-06-06 07:07:50 Exception occurred during processing of request from ('172.18.0.5', 50062)
2024-06-06 07:07:50 Traceback (most recent call last):
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 467, in _make_request
2024-06-06 07:07:50     self._validate_conn(conn)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 1099, in _validate_conn
2024-06-06 07:07:50     conn.connect()
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/connection.py", line 653, in connect
2024-06-06 07:07:50     sock_and_verified = _ssl_wrap_socket_and_match_hostname(
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/connection.py", line 806, in _ssl_wrap_socket_and_match_hostname
2024-06-06 07:07:50     ssl_sock = ssl_wrap_socket(
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 465, in ssl_wrap_socket
2024-06-06 07:07:50     ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/util/ssl_.py", line 509, in _ssl_wrap_socket_impl
2024-06-06 07:07:50     return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/ssl.py", line 513, in wrap_socket
2024-06-06 07:07:50     return self.sslsocket_class._create(
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/ssl.py", line 1104, in _create
2024-06-06 07:07:50     self.do_handshake()
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/ssl.py", line 1375, in do_handshake
2024-06-06 07:07:50     self._sslobj.do_handshake()
2024-06-06 07:07:50 ssl.SSLEOFError: [SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1007)
2024-06-06 07:07:50 
2024-06-06 07:07:50 During handling of the above exception, another exception occurred:
2024-06-06 07:07:50 
2024-06-06 07:07:50 Traceback (most recent call last):
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 793, in urlopen
2024-06-06 07:07:50     response = self._make_request(
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 491, in _make_request
2024-06-06 07:07:50     raise new_e
2024-06-06 07:07:50 urllib3.exceptions.SSLError: [SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1007)
2024-06-06 07:07:50 
2024-06-06 07:07:50 The above exception was the direct cause of the following exception:
2024-06-06 07:07:50 
2024-06-06 07:07:50 Traceback (most recent call last):
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 667, in send
2024-06-06 07:07:50     resp = conn.urlopen(
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 847, in urlopen
2024-06-06 07:07:50     retries = retries.increment(
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/urllib3/util/retry.py", line 515, in increment
2024-06-06 07:07:50     raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
2024-06-06 07:07:50 urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='192.168.91.1', port=443): Max retries exceeded with url: /tedapi/v1 (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1007)')))
2024-06-06 07:07:50 
2024-06-06 07:07:50 During handling of the above exception, another exception occurred:
2024-06-06 07:07:50 
2024-06-06 07:07:50 Traceback (most recent call last):
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/socketserver.py", line 683, in process_request_thread
2024-06-06 07:07:50     self.finish_request(request, client_address)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/socketserver.py", line 360, in finish_request
2024-06-06 07:07:50     self.RequestHandlerClass(request, client_address, self)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/socketserver.py", line 747, in __init__
2024-06-06 07:07:50     self.handle()
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/http/server.py", line 433, in handle
2024-06-06 07:07:50     self.handle_one_request()
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/http/server.py", line 421, in handle_one_request
2024-06-06 07:07:50     method()
2024-06-06 07:07:50   File "/app/server.py", line 387, in do_GET
2024-06-06 07:07:50     alerts = pw.alerts()
2024-06-06 07:07:50   File "/app/pypowerwall/__init__.py", line 561, in alerts
2024-06-06 07:07:50     devices: dict = self.vitals() or {}
2024-06-06 07:07:50   File "/app/pypowerwall/__init__.py", line 355, in vitals
2024-06-06 07:07:50     output = self.client.vitals()
2024-06-06 07:07:50   File "/app/pypowerwall/local/pypowerwall_local.py", line 354, in vitals
2024-06-06 07:07:50     return self.tedapi.vitals()
2024-06-06 07:07:50   File "/app/pypowerwall/tedapi/__init__.py", line 351, in vitals
2024-06-06 07:07:50     status = self.get_status(force)
2024-06-06 07:07:50   File "/app/pypowerwall/tedapi/__init__.py", line 262, in get_status
2024-06-06 07:07:50     r = requests.post(url, auth=('Tesla_Energy_Device', self.gw_pwd), verify=False,
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/requests/api.py", line 115, in post
2024-06-06 07:07:50     return request("post", url, data=data, json=json, **kwargs)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/requests/api.py", line 59, in request
2024-06-06 07:07:50     return session.request(method=method, url=url, **kwargs)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 589, in request
2024-06-06 07:07:50     resp = self.send(prep, **send_kwargs)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 703, in send
2024-06-06 07:07:50     r = adapter.send(request, **kwargs)
2024-06-06 07:07:50   File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 698, in send
2024-06-06 07:07:50     raise SSLError(e, request=request)
2024-06-06 07:07:50 requests.exceptions.SSLError: HTTPSConnectionPool(host='192.168.91.1', port=443): Max retries exceeded with url: /tedapi/v1 (Caused by SSLError(SSLEOFError(8, '[SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1007)')))
2024-06-06 07:07:50 ----------------------------------------

@jasonacox
Copy link
Owner Author

2024-06-06 07:07:50 ssl.SSLEOFError: [SSL: UNEXPECTED_EOF_WHILE_READING] EOF occurred in violation of protocol (_ssl.c:1007)

@jgleigh This is low level python code that handles https calls. Some quick research and it shows these as potential causes:

  1. Network Issues: Temporary network issues or interruptions can cause the SSL connection to be closed unexpectedly.
  2. Server-Side Problems: The server you're trying to connect to might be misconfigured, overloaded, or experiencing issues that cause it to close the connection prematurely.
  3. Client-Side Issues: Your client (e.g., a Python script using requests or another HTTP library) might have an issue such as incorrect SSL configuration or insufficient resources.
  4. Firewall or Proxy Interference: Firewalls, proxies, or other security devices might terminate the SSL connection if they detect suspicious activity or if they are misconfigured.

I can't replicate it and there doesn't appear to be any way for me to adjust the code to better handle this that wouldn't just mask the problem. The error is indicating something is truly wrong. I'm not sure if that helps you, but I would suggest trying:

  • Ensure no host or network firewall is activated (eliminate firewall issues)
  • Deploy the powerall dashboard stack on a new server (eliminate client side)
  • Run a temporary new network cable to new switch/gear (eliminate physical network issues)
  • Optional/unlikely fix: Reduce the polling of data in telegraf.conf to 10s via interval = "10s" (reduce load on gateway)

2024-06-05 16:32:29 06/05/2024 04:32:29 PM [proxy] [ERROR] Socket broken sending API response to client [doGET]: [Errno 32] Broken pipe

I have been thinking about dropping these to DEBUG logging levels because they can be confusing. They are typically harmless and everyone should be getting them occasionally anyway (e.g. force closing your browser that is rendering the powerflow animation can cause this if it hits at the same time one of the 5s updates hit). It just means the client hung up before getting the payload. Another (more likely) possible cause is that the Powerwall takes longer than 5s to deliver the packet, at which time telegraf (the client in this case) would timeout and try again. Pypowerwall would log the timeout as a disconnect. Unlike the above error, I don't think these provide actionable help.

@jgleigh
Copy link

jgleigh commented Jun 8, 2024

@jasonacox Okay, still pointing to possible bad cabling on my side. Maybe I'll run a cable test this weekend.

@mcbirse
Copy link
Collaborator

mcbirse commented Jun 8, 2024

@jasonacox - this is brilliant! Nice work.

Sorry I have been out of the loop for the past few weeks. I wish I had more time to be able contribute and help with review/testing, however too much going on IRL at the moment though. 😞

Testing TEDAPI support with jasonacox/pypowerwall:0.10.1t58-beta4 and it appears to be working great! I'm not seeing any problems on my setup.

image

@jasonacox
Copy link
Owner Author

Thanks @mcbirse (and no worries)!! That's looks great! thanks for testing.

@jgleigh I updated the debug information to provide less ambiguous messages during these client disconnect events. It should still record any error level event that isn't the cause of the client hanging up early. That is the only change in the latest beta:

jasonacox/pypowerwall:0.10.1t59-beta

I'm planning on pushing the pypowerwall beta patch (0.10.1) to latest and merging this PR today. I fully expect to see some edge case fixes we will need, but at this point I think we have found most of them.

Thanks for the help, everyone!

@jasonacox
Copy link
Owner Author

Hey @jgleigh - I forgot to add your discovery about the Neurio block. I added logic to pull the correct location. Also, I noticed the power scale factor was not being applied. I added that so the CT RealPower values will match the aggregate power data now (hopefully). Sadly, still no way to get the firmware version (at least I haven't found it). Please give this latest image a test and let me know how it looks (http://localhost:8675/vitals):

jasonacox/pypowerwall:0.10.1t59-beta3

Vitals

"NEURIO--VAHxxxxxxxxxxx": {
    "NEURIO_CT0_InstCurrent": 4.820000171661377,
    "NEURIO_CT0_InstReactivePower": 1.7999999523162842,
    "NEURIO_CT0_InstRealPower": 1132.5799560546875,
    "NEURIO_CT0_InstVoltage": 121.12999725341797,
    "NEURIO_CT0_Location": "solarRGM",
    "componentParentDin": "1232100-00-E--TG121048001E4G",
    "firmwareVersion": null,
    "lastCommunicationTime": "2024-06-08T08:39:00-07:00",
    "manufacturer": "NEURIO",
    "meterAttributes": {
        "meterLocation": []
    },
    "serialNumber": "VAHxxxxxxxxxxx"
}

@jgleigh
Copy link

jgleigh commented Jun 8, 2024

@jasonacox Looks good. I didn't see any firmware version reporting in all the tedapi data. Looks like they removed it unfortunately.

@jasonacox
Copy link
Owner Author

Thanks, Jeff!

Non-beta image:

jasonacox/pypowerwall:0.10.1t59

echo " 2 - Tesla Cloud (Solar-only systems or Powerwalls without LAN access)"
echo " 1 - Local Access (Powerwall 1, 2, or + using the Tesla Gateway on LAN) - Default"
echo " 2 - Tesla Cloud (Solar-only systems or Powerwalls without LAN access)"
echo " 3 - FleetAPI Cloud (Powerwall systems using Official Telsa API)"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SETUP SCRIPT: This release adds the ability to use FleetAPI. If selected, it will kick off the FleetAPI setup process. If FleetpAPI is set up, the pypowerwall will always prefer that over cloud (Tesla Owners unofficial API) as FleetAPI is a Tesla provided official API.

if [[ "$response" =~ ^([nN][oO]|[nN])$ ]]; then
IP=""
else
echo "Congratulations!"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SETUP: If local mode is selected, the setup script will attempt to find the Powerwall gateway at the default IP (192.168.91.1) and ask the user if they wish to set up the TEDAPI extended device vitals metrics. Otherwise, it will prompt the user for the IP address (or to scan).

This means that the user needs to set up the network routes to the PW Gateway prior to running setup.sh.

@jasonacox
Copy link
Owner Author

UPGRADE SCRIPT note: The upgrade script does nothing to switch to using FleetAPI or TEDAPI. This is by design. Upgrade should only update the version but keep the same mode. To switch modes, users will need to re-run setup.sh.

@jasonacox jasonacox merged commit 122fe76 into main Jun 8, 2024
@jasonacox jasonacox deleted the v4.4.0 branch June 8, 2024 18:21
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

Successfully merging this pull request may close these issues.

4 participants