1 """Support for Waterfurnaces."""
3 from datetime
import timedelta
8 import voluptuous
as vol
9 from waterfurnace.waterfurnace
import WaterFurnace, WFCredentialError, WFException
15 EVENT_HOMEASSISTANT_STOP,
23 _LOGGER = logging.getLogger(__name__)
25 DOMAIN =
"waterfurnace"
26 UPDATE_TOPIC = f
"{DOMAIN}_update"
30 NOTIFICATION_ID =
"waterfurnace_website_notification"
31 NOTIFICATION_TITLE =
"WaterFurnace website status"
34 CONFIG_SCHEMA = vol.Schema(
38 vol.Required(CONF_PASSWORD): cv.string,
39 vol.Required(CONF_USERNAME): cv.string,
43 extra=vol.ALLOW_EXTRA,
47 def setup(hass: HomeAssistant, base_config: ConfigType) -> bool:
48 """Set up waterfurnace platform."""
50 config = base_config[DOMAIN]
52 username = config[CONF_USERNAME]
53 password = config[CONF_PASSWORD]
55 wfconn = WaterFurnace(username, password)
60 except WFCredentialError:
61 _LOGGER.error(
"Invalid credentials for waterfurnace login")
65 hass.data[DOMAIN].start()
67 discovery.load_platform(hass, Platform.SENSOR, DOMAIN, {}, config)
72 """WaterFurnace Data collector.
74 This is implemented as a dedicated thread polling a websocket in a
75 tight loop. The websocket will shut itself from the server side if
76 a packet is not sent at least every 30 seconds. The reading is
77 cheap, the login is less cheap, so keeping this open and polling
78 on a very regular cadence is actually the least io intensive thing
83 """Initialize the data object."""
93 """Reconnect on a failure."""
96 if self.
_fails_fails > MAX_FAILS:
97 _LOGGER.error(
"Failed to refresh login credentials. Thread stopped")
98 persistent_notification.create(
101 "Error:<br/>Connection to waterfurnace website failed "
102 "the maximum number of times. Thread has stopped"
104 title=NOTIFICATION_TITLE,
105 notification_id=NOTIFICATION_ID,
112 _LOGGER.debug(
"Sleeping for fail # %s", self.
_fails_fails)
113 time.sleep(self.
_fails_fails * ERROR_INTERVAL.total_seconds())
119 _LOGGER.exception(
"Failed to reconnect attempt %s", self.
_fails_fails)
121 _LOGGER.debug(
"Reconnected to furnace")
125 """Thread run loop."""
129 """Connect to hass for shutdown."""
132 """Shutdown the thread."""
133 _LOGGER.debug(
"Signaled to shutdown")
137 self.
hasshass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, shutdown)
139 self.
hasshass.add_job(register)
149 _LOGGER.debug(
"Graceful shutdown")
159 _LOGGER.exception(
"Failed to read data, attempting to recover")
164 time.sleep(SCAN_INTERVAL.total_seconds())
def __init__(self, hass, client)
def register(HomeAssistant hass, Heos controller)
bool setup(HomeAssistant hass, ConfigType base_config)
None dispatcher_send(HomeAssistant hass, str signal, *Any args)