155 lines
4.4 KiB
Python
Executable File
155 lines
4.4 KiB
Python
Executable File
import logging
|
|
|
|
import voluptuous as vol
|
|
import traceback
|
|
from datetime import timedelta
|
|
|
|
from .APSystemsECUR import APSystemsECUR, APSystemsInvalidData
|
|
from homeassistant.helpers.discovery import load_platform
|
|
import homeassistant.helpers.config_validation as cv
|
|
from homeassistant.const import CONF_HOST
|
|
from homeassistant.helpers.entity import Entity
|
|
from homeassistant.util import Throttle
|
|
|
|
from homeassistant.helpers.update_coordinator import (
|
|
CoordinatorEntity,
|
|
DataUpdateCoordinator,
|
|
UpdateFailed,
|
|
)
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
from .const import DOMAIN
|
|
|
|
CONF_INTERVAL = "interval"
|
|
|
|
CONFIG_SCHEMA = vol.Schema({
|
|
DOMAIN : vol.Schema({
|
|
vol.Required(CONF_HOST): cv.string,
|
|
vol.Optional(CONF_INTERVAL) : cv.time_period_seconds
|
|
})
|
|
}, extra=vol.ALLOW_EXTRA)
|
|
|
|
PLATFORMS = [ "sensor", "binary_sensor" ]
|
|
|
|
|
|
## handle all the communications with the ECUR class and deal with our need for caching, etc
|
|
class ECUR():
|
|
|
|
def __init__(self, ipaddr):
|
|
self.ecu = APSystemsECUR(ipaddr)
|
|
self.cache_count = 0
|
|
self.cache_max = 5
|
|
self.data_from_cache = False
|
|
self.querying = True
|
|
self.error_messge = ""
|
|
self.cached_data = {}
|
|
|
|
async def stop_query(self):
|
|
self.querying = False
|
|
|
|
async def start_query(self):
|
|
self.querying = True
|
|
|
|
async def update(self):
|
|
data = {}
|
|
|
|
# if we aren't actively quering data, pull data form the cache
|
|
# this is so we can stop querying after sunset
|
|
if not self.querying:
|
|
|
|
_LOGGER.debug("Not querying ECU due to stopped")
|
|
data = self.cached_data
|
|
self.data_from_cache = True
|
|
|
|
data["data_from_cache"] = self.data_from_cache
|
|
data["querying"] = self.querying
|
|
return self.cached_data
|
|
|
|
_LOGGER.debug("Querying ECU")
|
|
try:
|
|
data = await self.ecu.async_query_ecu()
|
|
_LOGGER.debug("Got data from ECU")
|
|
|
|
# we got good results, so we store it and set flags about our
|
|
# cache state
|
|
self.cached_data = data
|
|
self.cache_count = 0
|
|
self.data_from_cache = False
|
|
self.error_message = ""
|
|
|
|
except APSystemsInvalidData as err:
|
|
|
|
msg = f"Using cached data from last successful communication from ECU. Error: {err}"
|
|
_LOGGER.warning(msg)
|
|
|
|
# we got invalid data, so we need to pull from cache
|
|
self.error_msg = msg
|
|
self.cache_count += 1
|
|
self.data_from_cache = True
|
|
data = self.cached_data
|
|
|
|
if self.cache_count > self.cache_max:
|
|
raise Exception(f"Error using cached data for more than {self.cache_max} times.")
|
|
|
|
except Exception as err:
|
|
|
|
msg = f"Using cached data from last successful communication from ECU. Error: {err}"
|
|
_LOGGER.warning(msg)
|
|
|
|
# we got invalid data, so we need to pull from cache
|
|
self.error_msg = msg
|
|
self.cache_count += 1
|
|
self.data_from_cache = True
|
|
data = self.cached_data
|
|
|
|
if self.cache_count > self.cache_max:
|
|
raise Exception(f"Error using cached data for more than {self.cache_max} times.")
|
|
|
|
data["data_from_cache"] = self.data_from_cache
|
|
data["querying"] = self.querying
|
|
_LOGGER.debug(f"Returning {data}")
|
|
return data
|
|
|
|
async def async_setup(hass, config):
|
|
""" Setup the APsystems platform """
|
|
hass.data.setdefault(DOMAIN, {})
|
|
|
|
host = config[DOMAIN].get(CONF_HOST)
|
|
interval = config[DOMAIN].get(CONF_INTERVAL)
|
|
if not interval:
|
|
interval = timedelta(seconds=60)
|
|
|
|
ecu = ECUR(host)
|
|
|
|
coordinator = DataUpdateCoordinator(
|
|
hass,
|
|
_LOGGER,
|
|
name=DOMAIN,
|
|
update_method=ecu.update,
|
|
update_interval=interval,
|
|
)
|
|
|
|
await coordinator.async_refresh()
|
|
|
|
hass.data[DOMAIN] = {
|
|
"ecu" : ecu,
|
|
"coordinator" : coordinator
|
|
}
|
|
|
|
async def handle_stop_query(call):
|
|
await ecu.stop_query()
|
|
coordinator.async_refresh()
|
|
|
|
async def handle_start_query(call):
|
|
await ecu.start_query()
|
|
coordinator.async_refresh()
|
|
|
|
hass.services.async_register(DOMAIN, "start_query", handle_start_query)
|
|
hass.services.async_register(DOMAIN, "stop_query", handle_stop_query)
|
|
|
|
for component in PLATFORMS:
|
|
load_platform(hass, component, DOMAIN, {}, config)
|
|
|
|
return True
|