|
| 1 | +"""The myIO integration.""" |
| 2 | +import asyncio |
| 3 | +from datetime import timedelta |
| 4 | +import logging |
| 5 | + |
| 6 | +from myio.comms_thread import CommsThread # pylint: disable=import-error |
| 7 | + |
| 8 | +from homeassistant.const import CONF_NAME |
| 9 | +from homeassistant.exceptions import PlatformNotReady |
| 10 | +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator |
| 11 | +from homeassistant.util import slugify |
| 12 | + |
| 13 | +from .const import CLIMATE, CONF_REFRESH_TIME, COVER, DOMAIN, LIGHT, SENSOR, DEFAULT_REFRESH_TIME |
| 14 | +from .comm.comms_thread import CommsThread2 |
| 15 | + |
| 16 | +_LOGGER = logging.getLogger(__name__) |
| 17 | + |
| 18 | +PLATFORMS = [ |
| 19 | + SENSOR, |
| 20 | + LIGHT, |
| 21 | + COVER, |
| 22 | + CLIMATE, |
| 23 | +] |
| 24 | + |
| 25 | +COMMS_THREAD = CommsThread2() |
| 26 | + |
| 27 | +_LOGGER.debug("MYIO module is initiating") |
| 28 | + |
| 29 | +async def async_setup(hass, config): |
| 30 | + """Set up the myIO-server component.""" |
| 31 | + _LOGGER.debug("async_setup is called") |
| 32 | + return True |
| 33 | + |
| 34 | + |
| 35 | +async def async_setup_entry(hass, config_entry): |
| 36 | + """Set up config entry.""" |
| 37 | + confstr = str(config_entry) |
| 38 | + _LOGGER.debug(f'async_setup_entry is called: {confstr}') |
| 39 | + |
| 40 | + _server_name = slugify(config_entry.data[CONF_NAME]) |
| 41 | + |
| 42 | + hass.data.setdefault(DOMAIN, {})[_server_name] = {} |
| 43 | + |
| 44 | + hass.states.async_set(f"{_server_name}.state", "Offline") |
| 45 | + hass.states.async_set(f"{_server_name}.first_contact", "True") |
| 46 | + |
| 47 | + _refresh_timer = config_entry.options.get(CONF_REFRESH_TIME, DEFAULT_REFRESH_TIME) |
| 48 | + |
| 49 | + _LOGGER.debug("MYIO Config:") |
| 50 | + for key in config_entry.options: |
| 51 | + _LOGGER.debug(f"{key}: {config_entry.options(key)}") |
| 52 | + |
| 53 | + def server_data(): |
| 54 | + """Return the server data dictionary database.""" |
| 55 | + return hass.data[DOMAIN][_server_name] |
| 56 | + |
| 57 | + async def setup_config_entries(): |
| 58 | + """Set up myIO platforms with config entry.""" |
| 59 | + _temp_server_first_contact = hass.states.get( |
| 60 | + f"{_server_name}.first_contact" |
| 61 | + ).state |
| 62 | + if _temp_server_first_contact == "True": |
| 63 | + for component in PLATFORMS: |
| 64 | + hass.async_create_task( |
| 65 | + hass.config_entries.async_forward_entry_setup( |
| 66 | + config_entry, component |
| 67 | + ) |
| 68 | + ) |
| 69 | + |
| 70 | + async def async_update_data(): |
| 71 | + """Fetch data from API endpoint.""" |
| 72 | + |
| 73 | + was_offline = False |
| 74 | + _timeout = 4 |
| 75 | + _comms_thread_timeout = False |
| 76 | + _temp_server_state = hass.states.get(f"{_server_name}.state").state |
| 77 | + |
| 78 | + if _temp_server_state == "Offline": |
| 79 | + hass.states.async_set(f"{_server_name}.available", False) |
| 80 | + was_offline = True |
| 81 | + _timeout = 20 |
| 82 | + |
| 83 | + # Pull fresh data from server. |
| 84 | + try: |
| 85 | + [ |
| 86 | + hass.data[DOMAIN][_server_name], |
| 87 | + _temp_server_state, |
| 88 | + ] = await asyncio.wait_for( |
| 89 | + COMMS_THREAD.send( |
| 90 | + server_data=server_data(), |
| 91 | + server_status=_temp_server_state, |
| 92 | + config_entry=config_entry, |
| 93 | + _post=None |
| 94 | + ), |
| 95 | + timeout=_timeout, |
| 96 | + ) |
| 97 | + except asyncio.TimeoutError: |
| 98 | + _comms_thread_timeout = True |
| 99 | + _LOGGER.debug(f"{_server_name} - Comms_Thread timeout") |
| 100 | + |
| 101 | + hass.states.async_set(f"{_server_name}.state", _temp_server_state) |
| 102 | + |
| 103 | + if _temp_server_state.startswith("Online") and was_offline: |
| 104 | + hass.states.async_set(f"{_server_name}.available", True) |
| 105 | + await setup_config_entries() |
| 106 | + hass.states.async_set(f"{_server_name}.first_contact", "False") |
| 107 | + elif not was_offline and _temp_server_state == "Offline": |
| 108 | + _LOGGER.debug(f"{_server_name} - Platform Not Ready") |
| 109 | + hass.states.async_set(f"{_server_name}.available", False) |
| 110 | + hass.states.async_set(f"{_server_name}.state", "Offline") |
| 111 | + # raise PlatformNotReady |
| 112 | + |
| 113 | + coordinator = DataUpdateCoordinator( |
| 114 | + hass, |
| 115 | + _LOGGER, |
| 116 | + # Name of the data. For logging purposes.pip |
| 117 | + name=f"{_server_name} status", |
| 118 | + update_method=async_update_data, |
| 119 | + # Polling interval. |
| 120 | + update_interval=timedelta(seconds=_refresh_timer), |
| 121 | + ) |
| 122 | + |
| 123 | + def listener(): |
| 124 | + """Listen to coordinator.""" |
| 125 | + |
| 126 | + await coordinator.async_refresh() |
| 127 | + |
| 128 | + coordinator.async_add_listener(listener) |
| 129 | + |
| 130 | + return True |
| 131 | + |
| 132 | + |
| 133 | +async def async_unload_entry( |
| 134 | + hass, config_entry |
| 135 | +): # async_add_devices because platforms |
| 136 | + """Unload a config entry.""" |
| 137 | + unload_ok = all( |
| 138 | + await asyncio.gather( |
| 139 | + *( |
| 140 | + hass.config_entries.async_forward_entry_unload(config_entry, component) |
| 141 | + for component in PLATFORMS |
| 142 | + ) |
| 143 | + ) |
| 144 | + ) |
| 145 | + return unload_ok |
0 commit comments