schedule backup: object of type 'NoneType' has no len()
mptheone opened this issue · 21 comments
Hello,
i just wanted your nice python script to set schedules..therofore i wanted an example what is it look like currently:
During handling of the above exception, another exception occurred:
after running the command:
client.zone_schedules_backup('filename.json')
i get:
File "<stdin>", line 1, in <module>
File "C:\Users\xx\AppData\Local\Programs\Python\Python310\lib\site-packages\evohomeasync2\__init__.py", line 301, in zone_schedules_backup
return self._get_single_heating_system().zone_schedules_backup(filename)
File "C:\Users\xx\AppData\Local\Programs\Python\Python310\lib\site-packages\evohomeasync2\__init__.py", line 196, in _get_single_heating_system
if len(self.locations) != 1:
TypeError: object of type 'NoneType' has no len()
Please download the code with tag 0.4.11 or later.
Then try:
python client.py -u username@gmail.com -p password get-schedules
... and/or:
python client.py -u username@gmail.com -p password set-schedules -f schedules.json
You can also use: --loc_idx
, but I haven't fully tested this as yet, so YMMV.
Hello,
thanks for helping.., not sure whats still wrong.., becuase my instance has an sensor which really is nothing,
can we overjump "invalid" entries?
the issue is, there seems an "broken" temperature value in the instance..
2023-11-26 23:32:59 INFO evohomeasync2.client GET https://tccna.honeywell.com/WebAPI/emea/api/v1/temperatureZone/xxx/schedule (200) = {'dailySchedules': [{'dayOfWeek': 'Monday', 'switchpoints': [{'heatSetpoint': 10.0, 'timeOfDay': '07:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '22:30:00'}]}, {'dayOfWeek': 'Tuesday', 'switchpoints': [{'heatSetpoint': 11.0, 'timeOfDay': '07:00:00'}, {'heatSetpoint': 11.0, 'timeOfDay': '22:30:00'}]}, {'dayOfWeek': 'Wednesday', 'switchpoints': [{'heatSetpoint': 10.0, 'timeOfDay': '07:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '22:30:00'}]}, {'dayOfWeek': 'Thursday', 'switchpoints': [{'heatSetpoint': 23.0, 'timeOfDay': '07:00:00'}, {'heatSetpoint': 22.0, 'timeOfDay': '11:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '12:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '15:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '22:30:00'}]}, {'dayOfWeek': 'Friday', 'switchpoints': [{'heatSetpoint': 10.0, 'timeOfDay': '07:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '16:30:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '19:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '22:30:00'}]}, {'dayOfWeek': 'Saturday', 'switchpoints': [{'heatSetpoint': 10.0, 'timeOfDay': '07:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '12:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '17:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '22:30:00'}]}, {'dayOfWeek': 'Sunday', 'switchpoints': [{'heatSetpoint': 20.5, 'timeOfDay': '06:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '08:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '13:30:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '15:00:00'}, {'heatSetpoint': 10.0, 'timeOfDay': '22:30:00'}]}]}
now its where it seems broken:
2023-11-26 23:32:59 DEBUG evohomeasync2.client Getting schedule of yyyyyy (temperatureZone)...
2023-11-26 23:33:00 INFO evohomeasync2.client GET https://tccna.honeywell.com/WebAPI/emea/api/v1/temperatureZone/yyyyyyyy/schedule (400) = [{'code': 'ScheduleNotFound', 'message': 'Schedule not found.'}]
Traceback (most recent call last):
File "E:\evohome\evohome-async-master/src\evohomeasync2\broker.py", line 233, in get
response.raise_for_status()
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\aiohttp\client_reqrep.py", line 1059, in raise_for_status
raise ClientResponseError(
aiohttp.client_exceptions.ClientResponseError: 400, message='Bad Request', url=URL('https://tccna.honeywell.com/WebAPI/emea/api/v1/temperatureZone/7784771/schedule')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "E:\evohome\evohome-async-master\client.py", line 19, in <module>
main()
File "E:\evohome\evohome-async-master/src\evohomeasync2\__init__.py", line 192, in main
cli(obj={}) # default for ctx.obj is None
^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1157, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1078, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\decorators.py", line 33, in new_func
return f(get_current_context(), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master/src\evohomeasync2\__init__.py", line 153, in get_schedules
asyncio.run(get_schedules(ctx.obj[SZ_EVO], loc_idx))
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 664, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master/src\evohomeasync2\__init__.py", line 145, in get_schedules
schedules = await tcs._get_schedules()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master/src\evohomeasync2\controlsystem.py", line 302, in _get_schedules
schedule = await zone.get_schedule()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master/src\evohomeasync2\zone.py", line 131, in get_schedule
schedule: _EvoDictT = await self._broker.get(
^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master/src\evohomeasync2\broker.py", line 237, in get
raise RequestFailed(hint, status=exc.status) from exc
evohomeasync2.exceptions.RequestFailed: Bad request (invalid data/json?)
2023-11-26 23:33:00 ERROR asyncio Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x000001BAC46485F0>
2023-11-26 23:33:00 ERROR asyncio Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x000001BAC466CDD0>, 123780.171)]']
connector: <aiohttp.connector.TCPConnector object at 0x000001BAC4648590>
OK, it looks like you have a ghost zone.
I can easily enough work around this, but I cannot really test it at present (my mocked server isn't sophisticated enough):
for zone in self._zones:
try:
schedule = await zone.get_schedule()
except InvalidSchedule:
self._logger.warning(
f"Ignoring schedule of {zone.zoneId} ({zone.name}): missing/invalid"
)
schedule = {}
Can you pull down the latest master? If that works, I'll push a new version up to PyPi.
I would appreciate it that you keep the Ghost Zone, until I've finished testing this feature.
Hello,
i tried with your latest master but follwoing error:
Traceback (most recent call last):
File "E:\evohome\evohome-async-master\evohome-async-master\client.py", line 19, in <module>
main()
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 192, in main
cli(obj={}) # default for ctx.obj is None
^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1157, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1078, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\decorators.py", line 33, in new_func
return f(get_current_context(), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 153, in get_schedules
asyncio.run(get_schedules(ctx.obj[SZ_EVO], loc_idx))
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 664, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 144, in get_schedules
tcs: ControlSystem = _get_tcs(evo, loc_idx)
^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 93, in _get_tcs
return evo.locations[int(loc_idx)]._gateways[0]._control_systems[0]
~~~~~~~~~~~~~^^^^^^^^^^^^^^
IndexError: list index out of range
and in the json file i have:
client.py: Starting backup...
2023-11-27 14:58:58 ERROR asyncio Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x000002335B682F30>
2023-11-27 14:58:58 ERROR asyncio Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x000002335B6A0F50>, 179338.031)]']
connector: <aiohttp.connector.TCPConnector object at 0x000002335B683170>
You do not include the command that you are using. Could you kindly do so: it would be helpful, but do redact the username/password.
Your JSON file is because you are redirecting STDOUT:
python client.py -u username@gmail.com -p password get-schedules > schedules.json
... so you could try instead:
python client.py -u username@gmail.com -p password get-schedules -f schedules.json
This error:
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 93, in _get_tcs
return evo.locations[int(loc_idx)]._gateways[0]._control_systems[0]
~~~~~~~~~~~~~^^^^^^^^^^^^^^
IndexError: list index out of range
... suggest to me you're using:
python client.py -u username@gmail.com -p password get-schedules --loc-idx 1
How many locations do you have - most have only one per account.
Try:
python client.py -u username@gmail.com -p password get-schedules --loc-idx 0
... or drop the --loc-idx
option altogether?
hello,
i tried all zour comments.
I have only one location and 6 thermostats and one is a ghost, or an fake entry.
Also i am succesfull able to login via APP or webbrowser same username and PW.
here is the latest comment i tried.
E:\evohome\evohome-async-master\evohome-async-master>python client.py -u xxxxx -p xxxxxx get-schedules --loc-idx 0
client.py: Starting backup...
Traceback (most recent call last):
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\broker.py", line 196, in _obtain_access_token
response.raise_for_status()
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\aiohttp\client_reqrep.py", line 1059, in raise_for_status
raise ClientResponseError(
aiohttp.client_exceptions.ClientResponseError: 429, message='Too Many Requests', url=URL('https://tccna.honeywell.com/Auth/OAuth/Token')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "E:\evohome\evohome-async-master\evohome-async-master\client.py", line 19, in <module>
main()
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 192, in main
cli(obj={}) # default for ctx.obj is None
^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1157, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1078, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\click\decorators.py", line 33, in new_func
return f(get_current_context(), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 153, in get_schedules
asyncio.run(get_schedules(ctx.obj[SZ_EVO], loc_idx))
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 664, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\__init__.py", line 142, in get_schedules
await evo.login()
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\client.py", line 166, in login
await self.user_account()
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\client.py", line 199, in user_account
self._user_account = await self.broker.get(
^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\broker.py", line 230, in get
response, content = await self._client( # type: ignore[assignment]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\broker.py", line 102, in _client
headers = await self._headers()
^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\broker.py", line 136, in _headers
await self._basic_login()
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\broker.py", line 177, in _basic_login
await self._obtain_access_token(CREDS_USER_PASSWORD | self._credentials) # type: ignore[operator]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\evohome\evohome-async-master\evohome-async-master/src\evohomeasync2\broker.py", line 200, in _obtain_access_token
raise AuthenticationFailed(hint, status=exc.status) from exc
evohomeasync2.exceptions.AuthenticationFailed: Vendor's API rate limit exceeded (wait a while)
2023-11-27 17:08:27 ERROR asyncio Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x000002353403FBF0>
2023-11-27 17:08:27 ERROR asyncio Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x0000023534C71070>, 187107.875)]']
connector: <aiohttp.connector.TCPConnector object at 0x0000023534C57080>
The error is:
evohomeasync2.exceptions.AuthenticationFailed: Vendor's API rate limit exceeded (wait a while)
This is a temporary error. The vendor (Honeywell/Resideo) will only let you authenticate a limited number of times per unit time.
Wait a while, and try again.
Hang on, I've noticed a bug...
OK, try it now.
Make sure you pull the latest commit from master.
This is likely the best option for you:
python client.py -u username@gmail.com -p password get-schedules -f schedules.json
it works fantastic.. i just have to remove the fake room from the set schedule....
awesome now i can create my google calender bridge... thanks!
You should be able to remove the ghost zone via the TCC web portal.
awesome news... get schedule works.. but then i tried of course set.. which failed.
the error message that i tried to often is not true, because after that i tried and get and imemdaitly it created a new json.
> python client.py -u xxxxxx -p xxxx: set-schedules -f schedules.json
client.py: Starting restore...
2023-11-27 20:03:19 WARNING evohomeasync2.client JSON may be invalid (bad schema): PUT temperatureZone/7xxx71/schedule: required key not provided @ data['DailySchedules']
Traceback (most recent call last):
File "E:\evohome\evohome-async-master(1)\evohome-async-master/src\evohomeasync2\broker.py", line 274, in put
response.raise_for_status()
File "C:\Users\mp\AppData\Local\Programs\Python\Python312\Lib\site-packages\aiohttp\client_reqrep.py", line 1059, in raise_for_status
raise ClientResponseError(
aiohttp.client_exceptions.ClientResponseError: 400, message='Bad Request', url=URL('https://tccna.honeywell.com/WebAPI/emea/api/v1/temperatureZone/7xxxx1/schedule')
The above exception was the direct cause of the following exception:
File "E:\evohome\evohome-async-master(1)\evohome-async-master/src\evohomeasync2\broker.py", line 278, in put
raise exc.RequestFailed(hint, status=err.status) from err
evohomeasync2.exceptions.RequestFailed: Bad request (invalid data/json?)
one interesting thing.. i need to run it multiple times that it goes over the api rate error...
one interesting thing.. i need to run it multiple times that it goes over the api rate error...
The vendor is quite strict about it.
Regarding your error:
evohomeasync2.exceptions.RequestFailed: Bad request (invalid data/json?)
I am not sure what is happening - set-schedule
works perfectly for me.
Did you perhaps edit the JSON file?
if i try to send a 2nd time directly the json it stopped , yeah i had to remove the ghost entry.. but i can work with that state thanks!
OK, will close now - I have added a switch (-c
) that will cache access tokens, which will help a lot to avoid the API rate limit being exceeded. Will push that soon.
python client.py -u user@gmail.com -p passwd --cache-tokens get-schedules