jasonacox / Powerwall-Dashboard

Grafana Monitoring Dashboard for Tesla Solar and Powerwall Systems
MIT License
268 stars 57 forks source link

V4.4.0 - Vitals and FleetAPI #479

Closed jasonacox closed 3 weeks ago

jasonacox commented 1 month ago

Updates

TEDAPI Support for Device Vitals

FleetAPI Support

Other Updates

The Return of Vitals

image

image

jgleigh commented 1 month ago

@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 commented 1 month ago

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 commented 1 month ago

@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 commented 1 month ago

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 commented 1 month ago

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 commented 1 month ago

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 commented 1 month ago

@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 commented 1 month ago

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

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 commented 1 month ago

@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 commented 1 month ago

Here you go. config.json status.json

jasonacox commented 1 month ago

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 commented 1 month ago

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 commented 4 weeks ago

@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 commented 4 weeks ago

@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 commented 4 weeks ago

@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 commented 3 weeks ago

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:

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 commented 3 weeks ago

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

mcbirse commented 3 weeks ago

@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 commented 3 weeks ago

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 commented 3 weeks ago

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 commented 3 weeks ago

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

jasonacox commented 3 weeks ago

Thanks, Jeff!

Non-beta image:

jasonacox/pypowerwall:0.10.1t59
jasonacox commented 3 weeks ago

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.