mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Merge pull request #1142 from kk7ds/add-honeywellus-thermostat
Add Honeywell US thermostat support
This commit is contained in:
commit
d38ad57b7d
@ -9,33 +9,32 @@ https://home-assistant.io/components/thermostat.honeywell/
|
|||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
from homeassistant.components.thermostat import ThermostatDevice
|
from homeassistant.components.thermostat import ThermostatDevice
|
||||||
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, TEMP_CELCIUS)
|
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, TEMP_CELCIUS,
|
||||||
|
TEMP_FAHRENHEIT)
|
||||||
|
|
||||||
REQUIREMENTS = ['evohomeclient==0.2.4']
|
REQUIREMENTS = ['evohomeclient==0.2.4']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_AWAY_TEMP = "away_temperature"
|
CONF_AWAY_TEMP = "away_temperature"
|
||||||
|
US_SYSTEM_SWITCH_POSITIONS = {1: 'Heat',
|
||||||
|
2: 'Off',
|
||||||
|
3: 'Cool'}
|
||||||
|
US_BASEURL = 'https://mytotalconnectcomfort.com/portal'
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
def _setup_round(username, password, config, add_devices):
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
|
||||||
""" Sets up the honeywel thermostat. """
|
|
||||||
from evohomeclient import EvohomeClient
|
from evohomeclient import EvohomeClient
|
||||||
|
|
||||||
username = config.get(CONF_USERNAME)
|
|
||||||
password = config.get(CONF_PASSWORD)
|
|
||||||
try:
|
try:
|
||||||
away_temp = float(config.get(CONF_AWAY_TEMP, 16))
|
away_temp = float(config.get(CONF_AWAY_TEMP, 16))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.error("value entered for item %s should convert to a number",
|
_LOGGER.error("value entered for item %s should convert to a number",
|
||||||
CONF_AWAY_TEMP)
|
CONF_AWAY_TEMP)
|
||||||
return False
|
return False
|
||||||
if username is None or password is None:
|
|
||||||
_LOGGER.error("Missing required configuration items %s or %s",
|
|
||||||
CONF_USERNAME, CONF_PASSWORD)
|
|
||||||
return False
|
|
||||||
|
|
||||||
evo_api = EvohomeClient(username, password)
|
evo_api = EvohomeClient(username, password)
|
||||||
|
|
||||||
@ -53,6 +52,24 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
|
""" Sets up the honeywel thermostat. """
|
||||||
|
username = config.get(CONF_USERNAME)
|
||||||
|
password = config.get(CONF_PASSWORD)
|
||||||
|
thermostat_id = config.get('id')
|
||||||
|
|
||||||
|
if username is None or password is None:
|
||||||
|
_LOGGER.error("Missing required configuration items %s or %s",
|
||||||
|
CONF_USERNAME, CONF_PASSWORD)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if thermostat_id:
|
||||||
|
add_devices([HoneywellUSThermostat(thermostat_id, username, password)])
|
||||||
|
else:
|
||||||
|
return _setup_round(username, password, config, add_devices)
|
||||||
|
|
||||||
|
|
||||||
class RoundThermostat(ThermostatDevice):
|
class RoundThermostat(ThermostatDevice):
|
||||||
""" Represents a Honeywell Round Connected thermostat. """
|
""" Represents a Honeywell Round Connected thermostat. """
|
||||||
|
|
||||||
@ -135,3 +152,117 @@ class RoundThermostat(ThermostatDevice):
|
|||||||
else:
|
else:
|
||||||
self._name = data['name']
|
self._name = data['name']
|
||||||
self._is_dhw = False
|
self._is_dhw = False
|
||||||
|
|
||||||
|
|
||||||
|
class HoneywellUSThermostat(ThermostatDevice):
|
||||||
|
""" Represents a Honeywell US Thermostat. """
|
||||||
|
|
||||||
|
def __init__(self, ident, username, password):
|
||||||
|
self._ident = ident
|
||||||
|
self._username = username
|
||||||
|
self._password = password
|
||||||
|
self._session = requests.Session()
|
||||||
|
# Maybe this should be configurable?
|
||||||
|
self._timeout = 30
|
||||||
|
# Yeah, really.
|
||||||
|
self._session.headers['X-Requested-With'] = 'XMLHttpRequest'
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
def _login(self):
|
||||||
|
self._session.get(US_BASEURL, timeout=self._timeout)
|
||||||
|
params = {'UserName': self._username,
|
||||||
|
'Password': self._password,
|
||||||
|
'RememberMe': 'false',
|
||||||
|
'timeOffset': 480}
|
||||||
|
resp = self._session.post(US_BASEURL, params=params,
|
||||||
|
timeout=self._timeout)
|
||||||
|
if resp.status_code != 200:
|
||||||
|
_LOGGER('Login failed for user %(user)s',
|
||||||
|
dict(user=self._username))
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _get_data(self):
|
||||||
|
if not self._login():
|
||||||
|
return
|
||||||
|
url = '%s/Device/CheckDataSession/%s' % (US_BASEURL, self._ident)
|
||||||
|
resp = self._session.get(url, timeout=self._timeout)
|
||||||
|
if resp.status_code < 300:
|
||||||
|
return resp.json()
|
||||||
|
else:
|
||||||
|
return {'error': resp.status_code}
|
||||||
|
|
||||||
|
def _set_data(self, data):
|
||||||
|
if not self._login():
|
||||||
|
return
|
||||||
|
url = '%s/Device/SubmitControlScreenChanges' % US_BASEURL
|
||||||
|
data['DeviceID'] = self._ident
|
||||||
|
resp = self._session.post(url, data=data, timeout=self._timeout)
|
||||||
|
if resp.status_code < 300:
|
||||||
|
return resp.json()
|
||||||
|
else:
|
||||||
|
return {'error': resp.status_code}
|
||||||
|
|
||||||
|
def _update(self):
|
||||||
|
self._data = self._get_data()['latestData']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_fan_on(self):
|
||||||
|
return self._data['fanData']['fanIsRunning']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return 'honeywell'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unit_of_measurement(self):
|
||||||
|
unit = self._data['uiData']['DisplayUnits']
|
||||||
|
if unit == 'F':
|
||||||
|
return TEMP_FAHRENHEIT
|
||||||
|
else:
|
||||||
|
return TEMP_CELCIUS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_temperature(self):
|
||||||
|
self._update()
|
||||||
|
return self._data['uiData']['DispTemperature']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_temperature(self):
|
||||||
|
setpoint = US_SYSTEM_SWITCH_POSITIONS.get(
|
||||||
|
self._data['uiData']['SystemSwitchPosition'],
|
||||||
|
'Off')
|
||||||
|
return self._data['uiData']['%sSetpoint' % setpoint]
|
||||||
|
|
||||||
|
def set_temperature(self, temperature):
|
||||||
|
""" Set target temperature. """
|
||||||
|
data = {'SystemSwitch': None,
|
||||||
|
'HeatSetpoint': None,
|
||||||
|
'CoolSetpoint': None,
|
||||||
|
'HeatNextPeriod': None,
|
||||||
|
'CoolNextPeriod': None,
|
||||||
|
'StatusHeat': None,
|
||||||
|
'StatusCool': None,
|
||||||
|
'FanMode': None}
|
||||||
|
setpoint = US_SYSTEM_SWITCH_POSITIONS.get(
|
||||||
|
self._data['uiData']['SystemSwitchPosition'],
|
||||||
|
'Off')
|
||||||
|
data['%sSetpoint' % setpoint] = temperature
|
||||||
|
self._set_data(data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_state_attributes(self):
|
||||||
|
""" Return device specific state attributes. """
|
||||||
|
fanmodes = {0: "auto",
|
||||||
|
1: "on",
|
||||||
|
2: "circulate"}
|
||||||
|
return {"fan": (self._data['fanData']['fanIsRunning'] and
|
||||||
|
'running' or 'idle'),
|
||||||
|
"fanmode": fanmodes[self._data['fanData']['fanMode']]}
|
||||||
|
|
||||||
|
def turn_away_mode_on(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def turn_away_mode_off(self):
|
||||||
|
pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user