jasonacox / pypowerwall

Python API for Tesla Powerwall and Solar Power Data
MIT License
136 stars 25 forks source link

PyPowerwallFleetAPI() needs to handle non-energy products #111

Open gregrahn opened 2 months ago

gregrahn commented 2 months ago

In trying to get pypowerwall to use the fleet API I experienced several errors that I've tracked down.

When pypowerwall calls /api/1/products it returns both a car and power product for me like below (shorted and redacted). Because the car details do not contain a key energy_site_id, code that assumes this key exists throws a KeyError exception, and never gets to check sites[1] so an additional check is needed for that.

Also, I noticed that in trying to get the setup completed through some hacking, the site_id in .pypowerwall.fleetapi was stored as a string, not a number. This causes comparison checks to fail given the API for products returns energy_site_id as a number.

Once I changed site_id in .pypowerwall.fleetapi to be a number and added a key check, it worked as expected.

Shorted /api/1/products response:

{
  "response": [
    {
      "id": 12345,
      "user_id": 321,
      "vehicle_id": 12345,
      "vin": "VIN3E8MFJK147",
      "color": null,
      "access_type": "OWNER",
      "display_name": "Tesla"
    },
    {
      "energy_site_id": 2255994400559966,
      "resource_type": "battery",
      "site_name": "1 E Main",
      "id": "STE9999-9999",
      "gateway_id": "0000000-00-E--TG000000000FYN",
      "asset_site_id": "",
      "grid_installation_id": "",
      "warp_site_number": "",
      "percentage_charged": 49.69920997318257,
      "battery_type": "ac_powerwall",
      "battery_power": 10   
    }
  ],
  "count": 2
}

Key check

diff --git a/pypowerwall/fleetapi/pypowerwall_fleetapi.py b/pypowerwall/fleetapi/pypowerwall_fleetapi.py
index 091cab3..60ae0ce 100644
--- a/pypowerwall/fleetapi/pypowerwall_fleetapi.py
+++ b/pypowerwall/fleetapi/pypowerwall_fleetapi.py
@@ -154,10 +154,11 @@ class PyPowerwallFleetAPI(PyPowerwallBase):
         else:
             found = False
             for idx, site in enumerate(sites):
-                if site['energy_site_id'] == self.siteid:
-                    self.siteindex = idx
-                    found = True
-                    break
+                if 'energy_site_id' in site:
+                    if site['energy_site_id'] == self.siteid:
+                        self.siteindex = idx
+                        found = True
+                        break
jasonacox commented 2 months ago

Great find @gregrahn !!! Wow, that is bad. I don't have a car, so my tests were passing. Would you be willing to submit a PR? I want you to get credit for this great work.

jasonacox commented 1 month ago

I'll combine this with #112 for a hotfix release.

jasonacox commented 1 month ago

Thanks for your help with this @gregrahn !