KeyError, when serving include_events=True in request_thermostats call
vosslab opened this issue · 8 comments
Was working fine yesterday, but today the KeyError comes up similar to issue #5 . Is there a better workaround for these KeyErrors?
Traceback (most recent call last):
File "/home/user/myecobeelib.py", line 67, in _request_data
thermostat_response = self.ecobee_service.request_thermostats(selection)
File "/usr/local/lib/python3.7/dist-packages/pyecobee/service.py", line 292, in request_thermostats
return Utilities.process_http_response(response, EcobeeThermostatResponse)
File "/usr/local/lib/python3.7/dist-packages/pyecobee/utilities.py", line 317, in process_http_response
is_top_level=True)
File "/usr/local/lib/python3.7/dist-packages/pyecobee/utilities.py", line 118, in dictionary_to_object
cls.dictionary_to_object(data[key], property_type, response_properties, parent_classes, indent + 4)
File "/usr/local/lib/python3.7/dist-packages/pyecobee/utilities.py", line 176, in dictionary_to_object
indent + 8)
File "/usr/local/lib/python3.7/dist-packages/pyecobee/utilities.py", line 176, in dictionary_to_object
indent + 8)
File "/usr/local/lib/python3.7/dist-packages/pyecobee/utilities.py", line 203, in dictionary_to_object
generated_code = '{0}={1!r}'.format(parent_classes[-1].attribute_name_map[key], data[key])
KeyError: 'fanSpeed'
Though I should include the Selection class instance:
selection = pyecobee.Selection(
selection_type=pyecobee.SelectionType.REGISTERED.value,
selection_match=self.thermostat_id,
include_events=True,
)
Me too! Working code, unchanged for weeks, suddenly died at 2:17 EDT today. The code is in a service on my Raspberry Pi, and I was away and did not see the crash notification until just now. Running the service code from the command line produces an almost identical cascade of errors to vosslab's. The clue, I think, is in the 'KeyError: fanSpeed' note. Has ecobee removed a key/value pair that pyecobee is looking for from their api structure?
I've reproduced the issue. ecobee added a new setting 'fanSpeed' which causes the error as the Setting object doesn't have an attribute to hold the value. Will fix and push shortly.
Long term I'll look into how to skip such fields instead of throwing an exception.
v1.3.6 pushed to Github and published to PyPI.
I'll close the issue but please re-open it if the issue persists.
I actually just published v1.3.7 which will prevent issues such as this one from happening again. Going forward if ecobee introduce a property that Pyecobee doesn't expect then Pyecobee will just skip this property and log an error message such as this one
YYYY-mm-dd HH:MM:SS,sss pyecobee.utilities ERROR Missing attribute in class Settings
Attribute name => fanSpeed
Attribute value => low
Please open a new issue here (https://github.com/sfanous/Pyecobee/issues/new)
You'll only see this error message if you enable debugging for the Pyecobee library from within your code with code similar to this
...
logging.getLogger('pyecobee').setLevel(logging.ERROR)
logging.getLogger('pyecobee').addHandler(rotating_file_handler)
...
Thanks for the prompt response. I can confirm that everything seems to be working normally again after installing the update.
Thanks for fixing this so quickly, I am impressed. I did not realize was that ecobee added a feature. Like @pfletch101 I just assumed they removed a feature.
Here's how this library works at a high level.
- A request is made to an ecobee endpoint. The response comes back as a JSON payload.
- The library unmarshalls/deserializes the JSON payload to an instance of one of the classes from pyecobee.objects.X
- The deserialized instance is returned
The issue that comes about every once in a while is that ecobee will add a new property to an object.
So let's look at this last occurrence. ecobee introduced the fanSpeed property into the Settings object.
pyecobee.objects.settings.Settings is the class that creates instances of Settings. However when the JSON payload came with the property fanSpeed which pyecobee.objects.Settings knows nothing about the code breaks throwing the KeyError exception.
The good news is that with 1.3.7 this won't occur anymore, Prior to 1.3.7 if the payload came with a new property an exception would be thrown, but now with 1.3.7 that property will be ignore (i.e. The generated object will not include it although the JSON payload does). I did add a log entry in that case but the only way you'd be able to see that log entry is by enabling the library logging as explained here.