{ "info": { "author": "Sherif Fanous", "author_email": "pyecobee_support@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython" ], "description": "Pyecobee: A Python implementation of the `ecobee API `_\r\n===========================================================================================================================\r\n\r\nIntroduction\r\n============\r\nPyecobee is a simple, elegant, and object oriented implementation of the ecobee API in Python. It is compatible with Python 2.6/2.7/3.3/3.4/3.5/3.6\r\n\r\n**Warning:** Pyecobee has been tested with an ecobee Smart Si. Though the following methods have not been tested I\r\nbelieve they should work find. Please create an `issue `_ or even better\r\ncreate a `pull request `_ if you encounter an issue with any of\r\nthem.\r\n\r\n- control_plug: I don't own an ecobee smart plug, so couldn't test this function\r\n- reset_preferences: I didn't want to wipe my thermostat's settings\r\n- set_occupied: Can only be used by an EMS thermostat\r\n- update_sensor: Requires an ecobee3 or ecobee4 thermostat\r\n- All Hierarchy requests: Accessible to EMS and Utility accounts only\r\n - list_sets\r\n - list_users\r\n - add_set\r\n - remove_set\r\n - rename_set\r\n - move_set\r\n - add_user\r\n - remove_user\r\n - unregister_user\r\n - update_user\r\n - register_thermostat\r\n - unregister_thermostat\r\n - move_thermostat\r\n - assign_thermostat\r\n- All Utility requests: Accessible to Utility accounts only\r\n - list_demand_response\r\n - issue_demand_response\r\n - cancel_demand_response\r\n - issue_demand_management\r\n- All Runtime Report Job requests: Accessible to Utility accounts only\r\n - create_runtime_report_job\r\n - list_runtime_report_job_status\r\n - cancel_runtime_report_job\r\n\r\n**Disclaimer:** Any ecobee API Keys, Authorization/Access/Refresh Tokens used in the following examples are fake.\r\n\r\nJSON Vs Objects\r\n===============\r\nWhereas JSON notation is used for the serialization/deserialization of request/response objects sent to and from the\r\necobee API, Pyecobee's interface is based on core Python data types and user defined objects instead. Pyecobee\r\nhandles the serialization of Python objects into JSON request objects and deserialization of JSON response objects\r\ninto Python objects thus completely alleviating the developer's need to create/parse JSON objects.\r\n\r\nPyecobee response from an authorize request\r\n-------------------------------------------\r\n\r\n.. code-block:: python\r\n\r\n authorize_response = ecobee_service.authorize()\r\n pin = authorize_response.ecobee_pin\r\n code = authorize_response.code\r\n scope = authorize_response.scope\r\n expires_in = authorize_response.expires_in\r\n interval = authorize_response.interval\r\n\r\nInstallation\r\n============\r\nTo install Pyecobee:\r\n\r\n.. code-block:: bash\r\n\r\n $ pip install pyecobee\r\n\r\nEnjoy.\r\n\r\n\r\nDocumentation\r\n=============\r\nPyecobee comes with extensive documentation. Use dir and help to explore all the details.\r\n.. code-block:: python\r\n\r\n >>> from pyecobee import *\r\n >>> dir(EcobeeService)\r\n >>> help(EcobeeService)\r\n\r\nGeneral usage\r\n=============\r\nThe **EcobeeService** class provides the ecobee API implementation.\r\n\r\nEcobeeService Class Diagram\r\n---------------------------\r\n.. image:: https://cdn.rawgit.com/sfanous/33688c4e0db84fc062f56ee1b7ffe444/raw/b1c780fde067445578ad0b8f9af1d7be1f3f418c/EcobeeService.svg\r\n\r\nTo use Pyecobee follow these steps\r\n\r\n- Import the modules\r\n- Instantiate an EcobeeService object\r\n- Complete the authorization sequence if required (authorize + request_tokens)\r\n- Refresh tokens if required (refresh_tokens)\r\n- Invoke the needed ecobee API requests/functions\r\n\r\nAll Pyecobee user defined objects overload __repr__, __str__, and implement a pretty_format method.\r\n\r\n.. code-block:: python\r\n\r\n >>> repr(authorize_response)\r\n AuthorizeResponse(ecobee_pin='bv29', code='uiNQok9Uhy5iScG4gncCAilcFUMK0zWT', scope='smartWrite', expires_in=9, interval=30)\r\n\r\n >>> str(authorize_response)\r\n AuthorizeResponse(ecobeePin=bv29, code=uiNQok9Uhy5iScG4gncCAilcFUMK0zWT, scope=smartWrite, expires_in=9, interval=30)\r\n\r\n >>> authorize_response.pretty_format()\r\n AuthorizeResponse(\r\n ecobeePin=bv29,\r\n code=uiNQok9Uhy5iScG4gncCAilcFUMK0zWT,\r\n scope=smartWrite,\r\n expires_in=9,\r\n interval=30\r\n )\r\n\r\nImport the modules\r\n------------------\r\n.. code-block:: python\r\n\r\n from pyecobee import *\r\n\r\nInstantiate an EcobeeService object\r\n-----------------------------------\r\n\r\n.. code-block:: python\r\n\r\n ecobee_service = EcobeeService(thermostat_name='My Thermostat',\r\n application_key='jiNXJ2Q6dyeAPXxy4HsFGUp1nK94C9VF')\r\n\r\nAuthorization & Token Requests\r\n------------------------------\r\nAuthorize\r\n^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n authorize_response = ecobee_service.authorize()\r\n logger.info(authorize_response.pretty_format())\r\n logger.info('Authorization Token => {0}'.format(ecobee_service.authorization_token))\r\n\r\nA successful invocation of authorize() returns an EcobeeAuthorizeResponse instance\r\n\r\nEcobeeAuthorizeResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/4263de2c38a41c2023234932ba6dd8c4/raw/0c199673fc7bef5ae4980d6a34478aec018c8add/EcobeeAuthorizeResponse.svg\r\n\r\nRequest Tokens\r\n^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n token_response = ecobee_service.request_tokens()\r\n logger.info(token_response.pretty_format())\r\n logger.info(\r\n 'Access Token => {0}\\n'\r\n 'Access Token Expires On => {1}\\n'\r\n 'Refresh Token => {2}\\n'\r\n 'Refresh Token Expires On => {3}'.format(ecobee_service.access_token,\r\n ecobee_service.access_token_expires_on,\r\n ecobee_service.refresh_token,\r\n ecobee_service.refresh_token_expires_on))\r\n\r\nA successful invocation of request_tokens() returns an EcobeeTokenResponse instance\r\n\r\nEcobeeTokenResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/61c4e7fe3bbcae96b237da1cfcc2fa63/raw/8d93d36fa2207208e9c1093f8a7c3b8f1420f20b/EcobeeTokensResponse.svg\r\n\r\nRefresh Tokens\r\n^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n token_response = ecobee_service.refresh_tokens()\r\n logger.info(token_response.pretty_format())\r\n logger.info(\r\n 'Access Token => {0}\\n'\r\n 'Access Token Expires On => {1}\\n'\r\n 'Refresh Token => {2}\\n'\r\n 'Refresh Token Expires On => {3}'.format(ecobee_service.access_token,\r\n ecobee_service.access_token_expires_on,\r\n ecobee_service.refresh_token,\r\n ecobee_service.refresh_token_expires_on))\r\n\r\nA successful invocation of refresh_tokens() returns an EcobeeTokenResponse instance\r\n\r\nEcobeeTokenResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/61c4e7fe3bbcae96b237da1cfcc2fa63/raw/8d93d36fa2207208e9c1093f8a7c3b8f1420f20b/EcobeeTokensResponse.svg\r\n\r\nThermostat Requests\r\n--------------------\r\nRequest Thermostat Summary\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n thermostat_summary_response = ecobee_service.request_thermostats_summary(selection=Selection(\r\n selection_type=SelectionType.REGISTERED.value,\r\n selection_match='',\r\n include_equipment_status=True))\r\n logger.info(thermostat_summary_response.pretty_format())\r\n\r\nA successful invocation of request_thermostats_summary() returns an EcobeeThermostatsSummaryResponse instance\r\n\r\nEcobeeThermostatsSummaryResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/957474de7596100c37aab58dcfe81a1a/raw/66f63ee5e08ed86ad87490132a80f448c5da2344/EcobeeThermostatsSummaryResponse.svg\r\n\r\nRequest Thermostats\r\n^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n # Only set the include options you need to True. I've set most of them to True for illustrative purposes only.\r\n selection = Selection(selection_type=SelectionType.REGISTERED.value, selection_match='', include_alerts=True,\r\n include_device=True, include_electricity=True, include_equipment_status=True,\r\n include_events=True, include_extended_runtime=True, include_house_details=True,\r\n include_location=True, include_management=True, include_notification_settings=True,\r\n include_oem_cfg=False, include_privacy=False, include_program=True, include_reminders=True,\r\n include_runtime=True, include_security_settings=False, include_sensors=True,\r\n include_settings=True, include_technician=True, include_utility=True, include_version=True,\r\n include_weather=True)\r\n thermostat_response = ecobee_service.request_thermostats(selection)\r\n logger.info(thermostat_response.pretty_format())\r\n assert thermostat_response.status.code == 0, 'Failure while executing request_thermostats:\\n{0}'.format(\r\n thermostat_response.pretty_format())\r\n\r\nA successful invocation of request_thermostats() returns an EcobeeThermostatResponse instance\r\n\r\nEcobeeThermostatResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/a674640718e63fdb2f1cb5ed9c2f2466/raw/c8c79fe0a2820b953647cb306f191b46437e5902/EcobeeThermostatResponse.svg\r\n\r\nUpdate Thermostat\r\n^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n update_thermostat_response = ecobee_service.update_thermostats(\r\n selection=Selection(\r\n selection_type=SelectionType.REGISTERED.value,\r\n selection_match=''),\r\n thermostat=Thermostat(\r\n settings=Settings(\r\n hvac_mode='off')),\r\n functions=[\r\n Function(\r\n type='deleteVacation',\r\n params={'name': 'My vacation'})])\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing update_thermostats:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\nA successful invocation of update_thermostats() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nReport Requests\r\n---------------\r\nMeter Report\r\n^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n eastern = timezone('US/Eastern')\r\n meter_reports_response = ecobee_service.request_meter_reports(\r\n selection=Selection(\r\n selection_type=SelectionType.THERMOSTATS.value,\r\n selection_match='123456789012'),\r\n start_date_time=eastern.localize(datetime(2013, 4, 4, 0, 0, 0), is_dst=True),\r\n end_date_time=eastern.localize(datetime(2013, 4, 4, 23, 59, 0), is_dst=True))\r\n logger.info(meter_report_response.pretty_format())\r\n assert meter_report_response.status.code == 0, 'Failure while executing request_meter_reports:\\n{0}'.format(\r\n meter_report_response.pretty_format())\r\n\r\nA successful invocation of request_meter_reports() returns an EcobeeMeterReportsResponse instance\r\n\r\nEcobeeMeterReportsResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/6abbae0f9c85d75304557d306b8777e6/raw/208fb6df5efc9a6fbd37c0e059fc4904fdca501d/EcobeeMeterReportsResponse.svg\r\n\r\nRuntime Report\r\n^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n eastern = timezone('US/Eastern')\r\n runtime_report_response = ecobee_service.request_runtime_reports(\r\n selection=Selection(\r\n selection_type=SelectionType.THERMOSTATS.value,\r\n selection_match='123456789012'),\r\n start_date_time=eastern.localize(datetime(2010, 1, 1, 0, 0, 0), is_dst=False),\r\n end_date_time=eastern.localize(datetime(2010, 1, 2, 0, 0, 0), is_dst=False),\r\n columns='auxHeat1,auxHeat2,auxHeat3,compCool1,compCool2,compHeat1,compHeat2,dehumidifier,dmOffset,'\r\n 'economizer,fan,humidifier,hvacMode,outdoorHumidity,outdoorTemp,sky,ventilator,wind,zoneAveTemp,'\r\n 'zoneCalendarEvent,zoneClimate,zoneCoolTemp,zoneHeatTemp,zoneHumidity,zoneHumidityHigh,'\r\n 'zoneHumidityLow,zoneHvacMode,zoneOccupancy')\r\n logger.info(runtime_report_response.pretty_format())\r\n assert runtime_report_response.status.code == 0, 'Failure while executing request_runtime_reports:\\n{0}'.format(\r\n runtime_report_response.pretty_format())\r\n\r\nA successful invocation of request_runtime_reports() returns an EcobeeRuntimeReportsResponse instance\r\n\r\nEcobeeRuntimeReportsResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/5816b010e7207d756984805521015ba0/raw/46e7b690f39a33b4fd52b5b4aa36eb5102fea9ea/EcobeeRuntimeReportsResponse.svg\r\n\r\nGroup Requests\r\n--------------\r\nRequest Groups\r\n^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n group_response = ecobee_service.request_groups(\r\n selection=Selection(\r\n selection_type=SelectionType.REGISTERED.value))\r\n logger.info(group_response.pretty_format())\r\n assert group_response.status.code == 0, 'Failure while executing request_groups:\\n{0}'.format(\r\n group_response.pretty_format())\r\n\r\nA successful invocation of request_groups() returns an EcobeeGroupsResponse instance\r\n\r\nEcobeeGroupsResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/72918aca65419a8edecbb263623738a1/raw/dbee17f1e67f21b5b5ab42d645e69e833ce2b465/EcobeeGroupsResponse.svg\r\n\r\nUpdate Groups\r\n^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n # Create Groups\r\n group_response = ecobee_service.update_groups(\r\n selection=Selection(\r\n selection_type=SelectionType.REGISTERED.value),\r\n groups=[\r\n Group(\r\n group_ref='3d03a26fd80001',\r\n group_name='ground_floor',\r\n synchronize_alerts=True,\r\n synchronize_vacation=True,\r\n thermostats=[\r\n '123456789101']),\r\n Group(\r\n group_ref='3bb5a91b180001',\r\n group_name='first_floor',\r\n synchronize_reset=True,\r\n synchronize_vacation=True,\r\n thermostats=[\r\n '123456789102'])])\r\n logger.info(group_response.pretty_format())\r\n assert group_response.status.code == 0, 'Failure while executing update_groups:\\n{0}'.format(\r\n group_response.pretty_format())\r\n\r\n # Update a Group\r\n group_response = ecobee_service.update_groups(\r\n selection=Selection(\r\n selection_type=SelectionType.REGISTERED.value),\r\n groups=[\r\n Group(\r\n group_ref='3d03a26fd80001',\r\n synchronize_system_mode=True)])\r\n logger.info(group_response.pretty_format())\r\n assert group_response.status.code == 0, 'Failure while executing update_groups:\\n{0}'.format(\r\n group_response.pretty_format())\r\n\r\n # Delete a group (Set the thermostats parameter of the group to an empty list)\r\n group_response = ecobee_service.update_groups(\r\n selection=Selection(\r\n selection_type=SelectionType.REGISTERED.value),\r\n groups=[\r\n Group(\r\n group_ref='3d03a26fd80001',\r\n thermostats=[])])\r\n logger.info(group_response.pretty_format())\r\n assert group_response.status.code == 0, 'Failure while executing update_groups:\\n{0}'.format(\r\n group_response.pretty_format())\r\n\r\nA successful invocation of request_groups() returns an EcobeeGroupsResponse instance\r\n\r\nEcobeeGroupsResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/72918aca65419a8edecbb263623738a1/raw/dbee17f1e67f21b5b5ab42d645e69e833ce2b465/EcobeeGroupsResponse.svg\r\n\r\nHierarchy Set Requests\r\n----------------------\r\nList Hierarchy Sets\r\n^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n list_hierarchy_sets_response = ecobee_service.list_hierarchy_sets(set_path='/',\r\n recursive=True,\r\n include_privileges=True,\r\n include_thermostats=True)\r\n logger.info(list_hierarchy_sets_response.pretty_format())\r\n assert list_hierarchy_sets_response.status.code == 0, 'Failure while executing list_hierarchy_sets:\\n{0}'.format(\r\n list_hierarchy_sets_response.pretty_format())\r\n\r\nA successful invocation of list_hierarchy_sets() returns an EcobeeListHierarchySetsResponse instance\r\n\r\nEcobeeListHierarchySetsResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/a68c63860b11e4b1c51193a6cbd2f817/raw/e904c5f40e6e1681c4c7a35e7bccd41e5e15d642/EcobeeListHierarchySetsResponse.svg\r\n\r\nAdd Hierarchy Set\r\n^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n add_hierarchy_set_response = ecobee_service.add_hierarchy_set(set_name='NewSet',\r\n parent_path='/')\r\n logger.info(add_hierarchy_set_response.pretty_format())\r\n assert add_hierarchy_set_response.status.code == 0, 'Failure while executing add_hierarchy_set:\\n{0}'.format(\r\n add_hierarchy_set_response.pretty_format())\r\n\r\nA successful invocation of add_hierarchy_set() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nRemove Hierarchy Set\r\n^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n remove_hierarchy_set_response = ecobee_service.remove_hierarchy_set(set_path='/NewSet')\r\n logger.info(remove_hierarchy_set_response.pretty_format())\r\n assert remove_hierarchy_set_response.status.code == 0, 'Failure while executing remove_hierarchy_set:\\n{0}'.format(\r\n remove_hierarchy_set_response.pretty_format())\r\n\r\nA successful invocation of remove_hierarchy_set() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nRename Hierarchy Set\r\n^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n rename_hierarchy_set_response = ecobee_service.rename_hierarchy_set(set_path='/NewSet',\r\n new_name='ToRename')\r\n logger.info(rename_hierarchy_set_response.pretty_format())\r\n assert rename_hierarchy_set_response.status.code == 0, 'Failure while executing rename_hierarchy_set:\\n{0}'.format(\r\n rename_hierarchy_set_response.pretty_format())\r\n\r\nA successful invocation of rename_hierarchy_set() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nMove Hierarchy Set\r\n^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n move_hierarchy_set_response = ecobee_service.move_hierarchy_set(set_path='/ToMove',\r\n to_path='MainNode')\r\n logger.info(move_hierarchy_set_response.pretty_format())\r\n assert move_hierarchy_set_response.status.code == 0, 'Failure while executing move_hierarchy_set:\\n{0}'.format(\r\n move_hierarchy_set_response.pretty_format())\r\n\r\nA successful invocation of move_hierarchy_set() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nHierarchy User Requests\r\n-----------------------\r\nList Hierarchy Users\r\n^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n list_hierarchy_users_response = ecobee_service.list_hierarchy_users(set_path='/',\r\n recursive=True,\r\n include_privileges=True)\r\n logger.info(list_hierarchy_users_response.pretty_format())\r\n assert list_hierarchy_users_response.status.code == 0, 'Failure while executing list_hierarchy_users:\\n{0}'.format(\r\n list_hierarchy_users_response.pretty_format())\r\n\r\nA successful invocation of list_hierarchy_users() returns an EcobeeListHierarchyUsersResponse instance\r\n\r\nEcobeeListHierarchyUsersResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/6ab4920c897067424001148f881a1591/raw/f9935beee3a8ae64ee146c466ad04f421a2a49c5/EcobeeListHierarchyUsersResponse.svg\r\n\r\nAdd Hierarchy Users\r\n^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n add_hierarchy_users_response = ecobee_service.add_hierarchy_users(\r\n users=[\r\n HierarchyUser(\r\n user_name='new@user1.com',\r\n first_name='User',\r\n last_name='1'),\r\n HierarchyUser(\r\n user_name='new@user2.com',\r\n first_name='User',\r\n last_name='2')],\r\n privileges=[\r\n HierarchyPrivilege(\r\n set_path='/MainNode',\r\n user_name='new@user1.com',\r\n allow_view=True),\r\n HierarchyPrivilege(\r\n set_path='/OtherNode',\r\n user_name='new@user1.com',\r\n allow_view=True)])\r\n logger.info(add_hierarchy_users_response.pretty_format())\r\n assert add_hierarchy_users_response.status.code == 0, (\r\n 'Failure while executing add_hierarchy_users:\\n{0}'.format(\r\n add_hierarchy_users_response.pretty_format()))\r\n\r\nA successful invocation of add_hierarchy_users() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nRemove Hierarchy Users\r\n^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n remove_hierarchy_users_response = ecobee_service.remove_hierarchy_users(\r\n set_path='/',\r\n users=[\r\n HierarchyUser(\r\n user_name='todelete@hierarchy.com'),\r\n HierarchyUser(\r\n user_name='todelete2@hierarchy.com')])\r\n logger.info(remove_hierarchy_users_response.pretty_format())\r\n assert remove_hierarchy_users_response.status.code == 0, (\r\n 'Failure while executing remove_hierarchy_users:\\n{0}'.format(\r\n remove_hierarchy_users_response.pretty_format()))\r\n\r\nA successful invocation of remove_hierarchy_users() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nUnregister Hierarchy Users\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n unregister_hierarchy_users_response = ecobee_service.unregister_hierarchy_users(\r\n users=[\r\n HierarchyUser(\r\n user_name='todelete@hierarchy.com'),\r\n HierarchyUser(\r\n user_name='todelete2@hierarchy.com')])\r\n logger.info(unregister_hierarchy_users_response.pretty_format())\r\n assert unregister_hierarchy_users_response.status.code == 0, (\r\n 'Failure while executing unregister_hierarchy_users_response:\\n{0}'.format(\r\n unregister_hierarchy_users_response.pretty_format()))\r\n\r\nA successful invocation of unregister_hierarchy_users() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nUpdate Hierarchy Users\r\n^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n update_hierarchy_users_response = update_hierarchy_users_response = ecobee_service.update_hierarchy_users(\r\n users=[\r\n HierarchyUser(\r\n user_name='user1@update.com',\r\n first_name='Updated',\r\n last_name='User',\r\n phone='222-333-4444',\r\n email_alerts=False)],\r\n privileges=[\r\n HierarchyPrivilege(\r\n set_path='/MainNode',\r\n user_name='user1@update.com',\r\n allow_view=True),\r\n HierarchyPrivilege(\r\n set_path='/MainNode',\r\n user_name='user2@update.com',\r\n allow_view=True),\r\n HierarchyPrivilege(\r\n set_path='/OtherNode',\r\n user_name='user2@update.com',\r\n allow_view=True)])\r\n logger.info(update_hierarchy_users_response.pretty_format())\r\n assert update_hierarchy_users_response.status.code == 0, (\r\n 'Failure while executing update_hierarchy_users_response:\\n{0}'.format(\r\n update_hierarchy_users_response.pretty_format()))\r\n\r\nA successful invocation of update_hierarchy_users() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nHierarchy Thermostat Requests\r\n-----------------------------\r\nRegister Thermostat\r\n^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n register_hierarchy_thermostats_response = ecobee_service.register_hierarchy_thermostats(set_path='/OtherNode',\r\n thermostats=(\r\n '123456789012,'\r\n '123456789013'))\r\n logger.info(register_hierarchy_thermostats_response.pretty_format())\r\n assert register_hierarchy_thermostats_response.status.code == 0, (\r\n 'Failure while executing register_hierarchy_thermostats_response:\\n{0}'.format(\r\n register_hierarchy_thermostats_response.pretty_format()))\r\n\r\nA successful invocation of register_hierarchy_thermostats() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nUnregister Thermostat\r\n^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n unregister_hierarchy_thermostats_response = ecobee_service.unregister_hierarchy_thermostats(\r\n thermostats='123456789012,123456789013')\r\n logger.info(unregister_hierarchy_thermostats_response.pretty_format())\r\n assert unregister_hierarchy_thermostats_response.status.code == 0, (\r\n 'Failure while executing unregister_hierarchy_thermostats_response:\\n{0}'.format(\r\n unregister_hierarchy_thermostats_response.pretty_format()))\r\n\r\nA successful invocation of unregister_hierarchy_thermostats() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nMove Thermostat\r\n^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n move_hierarchy_thermostats_response = ecobee_service.move_hierarchy_thermostats(set_path='/MainNode',\r\n to_path='/OtherNode',\r\n thermostats=('123456789012,'\r\n '123456789013'))\r\n logger.info(move_hierarchy_thermostats_response.pretty_format())\r\n assert move_hierarchy_thermostats_response.status.code == 0, (\r\n 'Failure while executing move_hierarchy_thermostats_response:\\n{0}'.format(\r\n move_hierarchy_thermostats_response.pretty_format()))\r\n\r\nA successful invocation of move_hierarchy_thermostats() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nAssign Thermostat\r\n^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n assign_hierarchy_thermostats_response = ecobee_service.assign_hierarchy_thermostats(set_path='/MainNode',\r\n thermostats=('123456789012,'\r\n '123456789013'))\r\n logger.info(assign_hierarchy_thermostats_response.pretty_format())\r\n assert assign_hierarchy_thermostats_response.status.code == 0, (\r\n 'Failure while executing assign_hierarchy_thermostats_response:\\n{0}'.format(\r\n assign_hierarchy_thermostats_response.pretty_format()))\r\n\r\nA successful invocation of assign_hierarchy_thermostats() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nUtility Requests\r\n----------------\r\nList Demand Responses\r\n^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n list_demand_responses_response = ecobee_service.list_demand_responses()\r\n logger.info(list_demand_responses_response.pretty_format())\r\n assert list_demand_responses_response.status.code == 0, (\r\n 'Failure while executing list_demand_responses_response:\\n{0}'.format(\r\n list_demand_responses_response.pretty_format()))\r\n\r\nA successful invocation of list_demand_responses() returns an EcobeeListDemandResponsesResponse instance\r\n\r\nEcobeeListDemandResponsesResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/c60426de08616e85843dd7528956c204/raw/c9e90a75aedbb35561fbb39dc67c5a6157a77561/EcobeeListDemandResponsesResponse.svg\r\n\r\nIssue Demand Response\r\n^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n issue_demand_response_response = ecobee_service.issue_demand_response(\r\n selection=Selection(\r\n selection_type=SelectionType.MANAGEMENT_SET.value,\r\n selection_match='/'),\r\n demand_response=DemandResponse(\r\n name='myDR',\r\n message='This is a DR!',\r\n event=Event(\r\n heat_hold_temp=790,\r\n end_time='11:37:18',\r\n end_date='2011-01-10',\r\n name='apiDR',\r\n type='useEndTime',\r\n cool_hold_temp=790,\r\n start_date='2011-01-09',\r\n start_time='11:37:18',\r\n is_temperature_absolute=True)))\r\n logger.info(issue_demand_response_response.pretty_format())\r\n assert issue_demand_response_response.status.code == 0, (\r\n 'Failure while executing issue_demand_response_response:\\n{0}'.format(\r\n issue_demand_response_response.pretty_format()))\r\n\r\nA successful invocation of issue_demand_response() returns an EcobeeIssueDemandResponsesResponse instance\r\n\r\nEcobeeIssueDemandResponsesResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/7b8cc714ba9fb7d00e6ad70dc2fdc618/raw/989b8b0b90f81af0859a1c81160236c30dc0eaf9/EcobeeIssueDemandResponsesResponse.svg\r\n\r\nCancel Demand Response\r\n^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n cancel_demand_response_response = ecobee_service.cancel_demand_response(\r\n demand_response_ref='c253a12e0b3c3c93800095')\r\n logger.info(cancel_demand_response_response.pretty_format())\r\n assert cancel_demand_response_response.status.code == 0, (\r\n 'Failure while executing cancel_demand_response_response:\\n{0}'.format(\r\n cancel_demand_response_response.pretty_format()))\r\n\r\nA successful invocation of cancel_demand_response() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nIssue Demand Management\r\n^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n issue_demand_management_response = ecobee_service.issue_demand_managements(\r\n selection=Selection(\r\n selection_type=SelectionType.MANAGEMENT_SET.value,\r\n selection_match='/'),\r\n demand_managements=[\r\n DemandManagement(\r\n date='2012-01-01',\r\n hour=5,\r\n temp_offsets=[20, 20, 20, 0, 0, 0, 0, -20, -20, -20, 0, 0]),\r\n DemandManagement(\r\n date='2012-01-01',\r\n hour=6,\r\n temp_offsets=[0, 0, 20, 20, 0, 0, 0, 0, 0, -20, -20, -20])])\r\n logger.info(issue_demand_management_response.pretty_format())\r\n assert issue_demand_management_response.status.code == 0, (\r\n 'Failure while executing issue_demand_management_response:\\n{0}'.format(\r\n issue_demand_management_response.pretty_format()))\r\n\r\nRuntime Report Job Requests\r\n---------------------------\r\nCreate Runtime Report Job\r\n^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n create_runtime_report_job_response = ecobee_service.create_runtime_report_job(\r\n selection=Selection(\r\n selection_type=SelectionType.THERMOSTATS.value,\r\n selection_match='123456789012'),\r\n start_date=date(2016, 7, 1),\r\n end_date=date(2016, 10, 1),\r\n columns='zoneCalendarEvent,zoneHvacMode,zoneHeatTemp,zoneCoolTemp,zoneAveTemp,dmOffset')\r\n logger.info(create_runtime_report_job_response.pretty_format())\r\n assert create_runtime_report_job_response.status.code == 0, (\r\n 'Failure while executing create_runtime_report_job_response:\\n{0}'.format(\r\n create_runtime_report_job_response.pretty_format()))\r\n\r\nA successful invocation of create_runtime_report_job() returns an EcobeeCreateRuntimeReportJobResponse instance\r\n\r\nEcobeeCreateRuntimeReportJobResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/e19e2d2e529a780baad57d91bbc74d3a/raw/0f97f260fabfcc6deaa9b1bf0663a755264e921d/EcobeeCreateRuntimeReportJobResponse.svg\r\n\r\nList Runtime Report Job Status\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n list_runtime_report_job_status_response = ecobee_service.list_runtime_report_job_status(job_id='123')\r\n logger.info(list_runtime_report_job_status_response.pretty_format())\r\n assert list_runtime_report_job_status_response.status.code == 0, (\r\n 'Failure while executing list_runtime_report_job_status_response:\\n{0}'.format(\r\n list_runtime_report_job_status_response.pretty_format()))\r\n\r\nA successful invocation of list_runtime_report_job_status() returns an EcobeeListRuntimeReportJobStatusResponse instance\r\n\r\nEcobeeListRuntimeReportJobStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/45e7a445e3f643be0439438d0b66821e/raw/385c9711be5ce0f95c3ee6bdbf7dba453795ea0d/EcobeeListRuntimeReportJobStatusResponse.svg\r\n\r\nCancel Runtime Report Job\r\n^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n cancel_runtime_report_response = ecobee_service.cancel_runtime_report_job(job_id='123')\r\n logger.info(cancel_runtime_report_response.pretty_format())\r\n assert cancel_runtime_report_response.status.code == 0, (\r\n 'Failure while executing cancel_runtime_report_response:\\n{0}'.format(\r\n cancel_runtime_report_response.pretty_format()))\r\n\r\nA successful invocation of cancel_runtime_report_job() returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nThermostat Functions\r\n--------------------\r\nA successful invocation of any function returns an EcobeeStatusResponse instance\r\n\r\nEcobeeStatusResponse Class Diagram\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n.. image:: https://cdn.rawgit.com/sfanous/ce50523143e93b25d0ac9954aded53e5/raw/35154d91be6ee93b1dd8ffefa0b6d194d5c5de77/EcobeeStatusResponse.svg\r\n\r\nSend Message\r\n^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n update_thermostat_response = ecobee_service.send_message('Hello World')\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert thermostat_response.status.code == 0, 'Failure while executing request_thermostats:\\n{0}'.format(\r\n thermostat_response.pretty_format())\r\n\r\nAcknowledge\r\n^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n selection = Selection(selection_type=SelectionType.REGISTERED.value, selection_match='', include_alerts=True)\r\n thermostat_response = ecobee_service.request_thermostats(selection)\r\n thermostat = thermostat_response.thermostat_list[0]\r\n alerts = [alert for alert in thermostat.alerts if alert.text == message]\r\n\r\n update_thermostat_response = ecobee_service.acknowledge(thermostat_identifier=thermostat.identifier,\r\n ack_ref=alerts[0].acknowledge_ref,\r\n ack_type=AckType.ACCEPT)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing acknowledge:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\nSet Hold\r\n^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n # Simplest form\r\n update_thermostat_response = ecobee_service.set_hold(hold_climate_ref='away', hold_type=HoldType.NEXT_TRANSITION)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing set_hold:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\n # Using specific start/end date and time\r\n eastern = timezone('US/Eastern')\r\n update_thermostat_response = ecobee_service.set_hold(hold_climate_ref='away',\r\n start_date_time=eastern.localize(datetime(\r\n 2017, 5, 10, 13, 0, 0),\r\n is_dst=True),\r\n end_date_time=eastern.localize(datetime(\r\n 2017, 5, 10, 14, 0, 0),\r\n is_dst=True),\r\n hold_type=HoldType.DATE_TIME)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing set_hold:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\n # Using duration\r\n eastern = timezone('US/Eastern')\r\n update_thermostat_response = ecobee_service.set_hold(hold_climate_ref='away',\r\n start_date_time=eastern.localize(datetime(\r\n 2017, 5, 10, 13, 0, 0),\r\n is_dst=True),\r\n hold_type=HoldType.HOLD_HOURS,\r\n hold_hours=1)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing set_hold:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\n # Specifically the cooling temperature to use and hold indefinitely\r\n update_thermostat_response = ecobee_service.set_hold(cool_hold_temp=65, hold_type=HoldType.INDEFINITE)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing set_hold:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\n # Specifically the heating temperature to use and hold indefinitely\r\n update_thermostat_response = ecobee_service.set_hold(heat_hold_temp=72, hold_type=HoldType.INDEFINITE)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing set_hold:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\nResume Program\r\n^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n update_thermostat_response = ecobee_service.resume_program(resume_all=False)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing resume_program:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\nCreate Vacation\r\n^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n eastern = timezone('US/Eastern')\r\n update_thermostat_response = ecobee_service.create_vacation(name='Christmas Vacation!',\r\n cool_hold_temp=104,\r\n heat_hold_temp=59,\r\n start_date_time=eastern.localize(datetime(\r\n 2017, 12, 23, 10, 0, 0),\r\n is_dst=True),\r\n end_date_time=eastern.localize(datetime(\r\n 2017, 12, 28, 17, 0, 0),\r\n is_dst=True),\r\n fan_mode=FanMode.AUTO,\r\n fan_min_on_time=0)\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing create_vacation:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\nDelete Vacation\r\n^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n update_thermostat_response = ecobee_service.delete_vacation(name='Christmas Vacation!')\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing delete_vacation:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\nReset Preferences\r\n^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n # Danger zone!!!\r\n update_thermostat_response = ecobee_service.reset_preferences()\r\n logger.info(update_thermostat_response.pretty_format())\r\n assert update_thermostat_response.status.code == 0, 'Failure while executing reset_preferences:\\n{0}'.format(\r\n update_thermostat_response.pretty_format())\r\n\r\nPersistence\r\n===========\r\nThe ecobee API specifies that all tokens issued must be stored by the application. These tokens represent the credentials of the user and must be kept secure. A simple way is to use the Python shelve module as follows\r\n\r\n.. code-block:: python\r\n\r\n import shelve\r\n from datetime import datetime\r\n\r\n import pytz\r\n from six.moves import input\r\n\r\n from pyecobee import *\r\n\r\n\r\n def persist_to_shelf(file_name, ecobee_service):\r\n pyecobee_db = shelve.open(file_name, protocol=2)\r\n pyecobee_db[ecobee_service.thermostat_name] = ecobee_service\r\n pyecobee_db.close()\r\n\r\n\r\n def refresh_tokens(ecobee_service):\r\n token_response = ecobee_service.refresh_tokens()\r\n logger.debug('TokenResponse returned from ecobee_service.refresh_tokens():\\n{0}'.format(\r\n token_response.pretty_format()))\r\n\r\n persist_to_shelf('pyecobee_db', ecobee_service)\r\n\r\n\r\n def request_tokens(ecobee_service):\r\n token_response = ecobee_service.request_tokens()\r\n logger.debug('TokenResponse returned from ecobee_service.request_tokens():\\n{0}'.format(\r\n token_response.pretty_format()))\r\n\r\n persist_to_shelf('pyecobee_db', ecobee_service)\r\n\r\n\r\n def authorize(ecobee_service):\r\n authorize_response = ecobee_service.authorize()\r\n logger.debug('AutorizeResponse returned from ecobee_service.authorize():\\n{0}'.format(\r\n authorize_response.pretty_format()))\r\n\r\n persist_to_shelf('pyecobee_db', ecobee_service)\r\n\r\n logger.info('Please goto ecobee.com, login to the web portal and click on the settings tab. Ensure the My '\r\n 'Apps widget is enabled. If it is not click on the My Apps option in the menu on the left. In the '\r\n 'My Apps widget paste \"{0}\" and in the textbox labelled \"Enter your 4 digit pin to '\r\n 'install your third party app\" and then click \"Install App\". The next screen will display any '\r\n 'permissions the app requires and will ask you to click \"Authorize\" to add the application.\\n\\n'\r\n 'After completing this step please hit \"Enter\" to continue.'.format(\r\n authorize_response.ecobee_pin))\r\n input()\r\n\r\n\r\n if __name__ == '__main__':\r\n thermostat_name = 'My Thermostat'\r\n try:\r\n pyecobee_db = shelve.open('pyecobee_db', protocol=2)\r\n ecobee_service = pyecobee_db[thermostat_name]\r\n except KeyError:\r\n application_key = input('Please enter the API key of your ecobee App: ')\r\n ecobee_service = EcobeeService(thermostat_name=thermostat_name, application_key=application_key)\r\n finally:\r\n pyecobee_db.close()\r\n\r\n if not ecobee_service.authorization_token:\r\n authorize(ecobee_service)\r\n\r\n if not ecobee_service.access_token:\r\n request_tokens(ecobee_service)\r\n\r\n now_utc = datetime.now(pytz.utc)\r\n if now_utc > ecobee_service.refresh_token_expires_on:\r\n authorize(ecobee_service)\r\n request_tokens(ecobee_service)\r\n elif now_utc > ecobee_service.access_token_expires_on:\r\n token_response = ecobee_service.refresh_tokens()\r\n\r\n # Now make your requests :)\r\n\r\n\r\nTokens Refresh\r\n==============\r\nAll access tokens must be refreshed periodically. Access tokens expire 3600 seconds (1 hour) from the time they were\r\nrefreshed. There are two patterns to refresh the access token.\r\n\r\nPro-active\r\n----------\r\n- Get the current date/time in UTC\r\n- Compare the current date/time to the date/time on which the access and refresh token are due to expire\r\n- Re-authorize app if the current date/time is later than the refresh token expiry date/time\r\n- Refresh tokens if the current date/time is later than the access token expiry date/time\r\n\r\n.. code-block:: python\r\n\r\n now_utc = datetime.now(pytz.utc)\r\n if now_utc > ecobee_service.refresh_token_expires_on:\r\n authorize(ecobee_service)\r\n request_tokens(ecobee_service)\r\n elif now_utc > ecobee_service.access_token_expires_on:\r\n token_response = ecobee_service.refresh_tokens()\r\n\r\nReactive\r\n--------\r\nThe ecobee API returns status code 14 to indicate that a request was attempted using an expired access token. All\r\nnon-successful ecobee API responses are wrapped into the EcobeeApiException. The following code snippet demonstrates\r\nhow to refresh an expired access token\r\n\r\n.. code-block:: python\r\n\r\n try:\r\n thermostat_summary_response = ecobee_service.request_thermostats_summary(selection=Selection(\r\n selection_type=SelectionType.REGISTERED.value,\r\n selection_match='',\r\n include_equipment_status=True))\r\n except EcobeeApiException as e:\r\n if e.status_code == 14:\r\n token_response = ecobee_service.refresh_tokens()\r\n\r\nDate & Time Handling\r\n====================\r\nSome of the ecobee API requests expect the date and time to be in thermostat time, while others expect the date and time to be in UTC time.\r\n\r\nAny EcobeeService method that accepts a datetime object as an argument expects the argument to be passed in thermostat time. The datetime object passed **must be a timezone aware** object.\r\n\r\n.. code-block:: python\r\n\r\n import pytz\r\n from datetime import datetime\r\n\r\n from pytz import timezone\r\n\r\n eastern = timezone('US/Eastern')\r\n start_date_time=eastern.localize(datetime(2017, 5, 1, 10, 0, 0), is_dst=True) # 2017/05/01 10:00:00 -0400\r\n\r\nThe method will then either use the passed in datetime object as is, or convert it to its UTC time equivalent depending on the requirements of the ecobee API request being executed.\r\n\r\nException Handling\r\n==================\r\nYour code should be prepared to handle the following Exceptions\r\n\r\n- **EcobeeApiException**: Raised if a request results in an ecobee API error response\r\n- **EcobeeAuthorizationException**: Raised if a request results in a standard or extended OAuth error response\r\n- **EcobeeRequestsException**: Raised if a request results in an exception being raised by the underlying requests module\r\n- **EcobeeHttpException**: Raised if a request results in any other HTTP error\r\n\r\nEcobee Exceptions Class Diagram\r\n-------------------------------\r\n.. image:: https://cdn.rawgit.com/sfanous/58a8e5b281b6e40035fb80b097154fc8/raw/3766a676ccc2942bc9a18c1d0dc0a284683f1b39/EcobeeExceptions.svg\r\n\r\nRelease History\r\n===============\r\n\r\n1.2.1 (2017-06-01)\r\n------------------\r\n\r\n* Internal __slots__ improvements\r\n\r\n1.2.0 (2017-05-31)\r\n------------------\r\n\r\n* Internal refactoring of EcobeeObject and EcobeeResponse\r\n\r\n\r\n1.1.1 (2017-05-31)\r\n------------------\r\n\r\n* Miscellaneous minor internal changes to facilitate the automatic generation of PlantUML Class Diagrams\r\n\r\n\r\n1.1.0 (2017-05-24)\r\n------------------\r\n\r\n* Added ecobee API operations that are only accessible by EMS and Utility accounts\r\n\r\n\r\n1.0.0 (2017-05-12)\r\n------------------\r\n\r\n* First public release supporting all ecobee API operations except those that are only accessible by EMS and Utility accounts", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/sfanous/Pyecobee", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "pyecobee", "package_url": "https://pypi.org/project/pyecobee/", "platform": "", "project_url": "https://pypi.org/project/pyecobee/", "project_urls": { "Homepage": "https://github.com/sfanous/Pyecobee" }, "release_url": "https://pypi.org/project/pyecobee/1.2.1/", "requires_dist": [ "enum34 (>=1.1.6)", "pytz (>=2017.2)", "requests (>=2.13.0)", "six (>=1.10.0)" ], "requires_python": "", "summary": "A Python implementation of the ecobee API", "version": "1.2.1" }, "last_serial": 2920037, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "023e7bb76a564aa03ce5e87991f3e7cd", "sha256": "fe0ebb818086e740018769c9834b61c70997500a4a6583f454dd7dbc3bc1d4d4" }, "downloads": -1, "filename": "pyecobee-1.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "023e7bb76a564aa03ce5e87991f3e7cd", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 100850, "upload_time": "2017-05-12T19:09:41", "url": "https://files.pythonhosted.org/packages/35/2d/de16c7e02f4e4c91077e3c646660b3854a11760de9a1bedc3ef3292354c6/pyecobee-1.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b3ca0f8f97469bc856443278fd2614b5", "sha256": "0d870a0a38e0d6302fee2b9f9716d423dac0e06925311592dc9608d50b4296d4" }, "downloads": -1, "filename": "pyecobee-1.0.0.tar.gz", "has_sig": false, "md5_digest": "b3ca0f8f97469bc856443278fd2614b5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 71135, "upload_time": "2017-05-12T19:09:43", "url": "https://files.pythonhosted.org/packages/9e/6e/41f4988272849b1aa3a80895fa42f25dacc7b8538830eddf32d0df005988/pyecobee-1.0.0.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "9b793341a7c53ba227b11a834dc033b4", "sha256": "9e96bf16157d3b094ea05864d15973258daf6532e3abbfc17f1af9c064ae44f5" }, "downloads": -1, "filename": "pyecobee-1.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "9b793341a7c53ba227b11a834dc033b4", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 114647, "upload_time": "2017-05-24T20:19:12", "url": "https://files.pythonhosted.org/packages/14/ac/950043eba0f324b624c03c5ee3586937278c711358c4695681b906fea85e/pyecobee-1.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "471b7c37e7303834dfbbedac605350d9", "sha256": "d60f96fc334511602e4ed3b2c9503d9145484835ef812949f793ba8a1b79d6e3" }, "downloads": -1, "filename": "pyecobee-1.1.0.tar.gz", "has_sig": false, "md5_digest": "471b7c37e7303834dfbbedac605350d9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 90003, "upload_time": "2017-05-24T20:19:13", "url": "https://files.pythonhosted.org/packages/a7/86/87cd7346ba95da69011d882e94cdcebcd37bf8cd0d4bbdaebc1d676404e1/pyecobee-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "2f32fa36658d3dfffd10e93c77265eea", "sha256": "206a06cd7eee4492739817b7e344854188d319cf5f2a0d958300d7ea50dcec74" }, "downloads": -1, "filename": "pyecobee-1.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2f32fa36658d3dfffd10e93c77265eea", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 117851, "upload_time": "2017-05-31T15:58:36", "url": "https://files.pythonhosted.org/packages/6b/f1/3ed2dd3bf937c46c8d9bf61863d40c71ee52c218e50108469b1731c571fd/pyecobee-1.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b9fcc99f62cdcf920898503744641d75", "sha256": "e41eb9e13ec118f52b44a2f6d0c6e395988f205819a1822daf173992e0d0c9fb" }, "downloads": -1, "filename": "pyecobee-1.1.1.tar.gz", "has_sig": false, "md5_digest": "b9fcc99f62cdcf920898503744641d75", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 94771, "upload_time": "2017-05-31T15:58:39", "url": "https://files.pythonhosted.org/packages/26/3b/be536c5b9aa7bd20ac24db524631e4bd9dd379f5e3cd01dcdbb7a1ff6373/pyecobee-1.1.1.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "81b539e31c77e2f01d019cbdb0efc13a", "sha256": "6a38db65171d725113732e5372dfd7d4aa3253d939572789d5d5c0271b47bc67" }, "downloads": -1, "filename": "pyecobee-1.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "81b539e31c77e2f01d019cbdb0efc13a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 118301, "upload_time": "2017-05-31T19:17:43", "url": "https://files.pythonhosted.org/packages/b6/37/74630ea90efecbb6e40106354a0b892521fdf90431d4b28a9e6e65e8c263/pyecobee-1.2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c4e34bf0e21e86f5cad7c5ef681739f2", "sha256": "8896ceb70199bf9fc77e32b9205f0c926ae894cca0250194127196c152624fc7" }, "downloads": -1, "filename": "pyecobee-1.2.0.tar.gz", "has_sig": false, "md5_digest": "c4e34bf0e21e86f5cad7c5ef681739f2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 94258, "upload_time": "2017-05-31T19:17:46", "url": "https://files.pythonhosted.org/packages/7c/27/d3196da23451fa41df005782eee4299f239ec50c80a74e245750429d8c1f/pyecobee-1.2.0.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "ddad4a4a6c886363fbf0902ffa63f94d", "sha256": "f08f986a7fca5be8c5ccfb1946e5ff45fabf9b37787b62ebb5d60ab83e41edb1" }, "downloads": -1, "filename": "pyecobee-1.2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ddad4a4a6c886363fbf0902ffa63f94d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 118865, "upload_time": "2017-06-01T20:34:31", "url": "https://files.pythonhosted.org/packages/5d/24/f6d0b200659ebb13048d5c2dee576f716bd2195c0c65f75a1d1422d2559c/pyecobee-1.2.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6963f94a5d533dfe6d5445b639eb493e", "sha256": "d0d7313f519fba9952e680329278ec01383f98659b81db0492ca844acfdcb922" }, "downloads": -1, "filename": "pyecobee-1.2.1.tar.gz", "has_sig": false, "md5_digest": "6963f94a5d533dfe6d5445b639eb493e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 94878, "upload_time": "2017-06-01T20:35:28", "url": "https://files.pythonhosted.org/packages/80/da/e9c94a250d344058938a25c6d62f4e25c9eafee00c92f748c00e41aa9363/pyecobee-1.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ddad4a4a6c886363fbf0902ffa63f94d", "sha256": "f08f986a7fca5be8c5ccfb1946e5ff45fabf9b37787b62ebb5d60ab83e41edb1" }, "downloads": -1, "filename": "pyecobee-1.2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ddad4a4a6c886363fbf0902ffa63f94d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 118865, "upload_time": "2017-06-01T20:34:31", "url": "https://files.pythonhosted.org/packages/5d/24/f6d0b200659ebb13048d5c2dee576f716bd2195c0c65f75a1d1422d2559c/pyecobee-1.2.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6963f94a5d533dfe6d5445b639eb493e", "sha256": "d0d7313f519fba9952e680329278ec01383f98659b81db0492ca844acfdcb922" }, "downloads": -1, "filename": "pyecobee-1.2.1.tar.gz", "has_sig": false, "md5_digest": "6963f94a5d533dfe6d5445b639eb493e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 94878, "upload_time": "2017-06-01T20:35:28", "url": "https://files.pythonhosted.org/packages/80/da/e9c94a250d344058938a25c6d62f4e25c9eafee00c92f748c00e41aa9363/pyecobee-1.2.1.tar.gz" } ] }