Skip to content

Commit

Permalink
Fine tune component logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Limych committed Dec 11, 2020
1 parent c6139ff commit bd0e44e
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 66 deletions.
40 changes: 24 additions & 16 deletions custom_components/jq300/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
CONCENTRATION_PARTS_PER_MILLION,
)
from homeassistant.helpers import discovery
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.util import Throttle
from requests import PreparedRequest

Expand Down Expand Up @@ -61,9 +60,9 @@
PLATFORMS,
UPDATE_TIMEOUT,
ACCOUNT_CONTROLLER,
SIGNAL_UPDATE_JQ300,
CONF_ACCOUNT_ID,
MQTT_URL,
AVAILABLE_TIMEOUT,
)
from .util import mask_email

Expand Down Expand Up @@ -311,11 +310,11 @@ def _query(self, query_type, function: str, extra_params=None) -> Optional[dict]
return response

@property
def is_connected(self):
def is_connected(self) -> bool:
"""Return True if connected to account."""
return self.params["uid"] > 0

def connect(self, force=False) -> bool:
def connect(self, force: bool = False) -> bool:
"""(Re)Connect to account and return connection status."""
if not force and self.params["uid"] > 0:
return True
Expand Down Expand Up @@ -412,17 +411,16 @@ def _mqtt_process_message(self, message: dict):
)

elif message["type"] == "C":
_LOGGER.debug("Update online status for device %d", device_id)
if self.devices.get(device_id) is None:
return
self.devices[device_id]["onlinestat"] = message["content"]
online = int(message["content"])
_LOGGER.debug("Update online status for device %d: %d", device_id, online)
if online != self.devices[device_id].get("onlinestat"):
self.devices[device_id]["onlinets"] = monotonic()
self.devices[device_id]["onlinestat"] = online

else:
_LOGGER.warning("Unknown message type: %s", message)
return

if self.hass:
dispatcher_send(self.hass, SIGNAL_UPDATE_JQ300)

def _get_devices_mqtt_topics(self, device_ids: list) -> list:
devs = self.update_devices()
Expand Down Expand Up @@ -487,6 +485,7 @@ def update_devices(self, force=False) -> Optional[Dict[int, Dict[str, Any]]]:
tstamp = int(dt_util.now().timestamp() * 1000)
for dev in ret["deviceInfoBodyList"]:
dev[""] = tstamp
dev["onlinets"] = monotonic()
self._devices[dev["deviceid"]] = dev

for device_id in self._devices:
Expand Down Expand Up @@ -524,11 +523,23 @@ async def async_update_devices_or_timeout(self, timeout=UPDATE_TIMEOUT):

def device_available(self, device_id) -> bool:
"""Return True if device is available."""
return self.available and (
self.devices.get(device_id, {}).get("onlinestat") == "1"
or monotonic() - self._sensors_last_update < 60
dev = self.devices.get(device_id, {})
device_available = dev.get("onlinestat") == 1
device_timeout = (monotonic() - dev.get("onlinets", 0)) <= AVAILABLE_TIMEOUT
online = self.available and (device_available or device_timeout)

# pylint: disable=logging-too-many-args
_LOGGER.debug(
"Availability: %s (account) AND (%s (device %s) OR %s (timeout)) = $s",
self.available,
device_available,
device_id,
device_timeout,
online,
)

return online

def _extract_sensors_data(self, device_id, ts_now: int, sensors: dict):
res = {}
for sensor in sensors:
Expand Down Expand Up @@ -577,9 +588,6 @@ def update_sensors(self, _=None):

self._extract_sensors_data(device_id, ts_now, ret["deviceValueVos"])

if self.hass:
dispatcher_send(self.hass, SIGNAL_UPDATE_JQ300)

@Throttle(timedelta(minutes=10))
async def async_update_sensors_or_timeout(self, timeout=UPDATE_TIMEOUT):
"""Update current states of all active devices for account."""
Expand Down
29 changes: 9 additions & 20 deletions custom_components/jq300/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
from homeassistant import exceptions
from homeassistant.components.binary_sensor import ENTITY_ID_FORMAT
from homeassistant.const import CONF_DEVICES
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import async_generate_entity_id

# Code snippet to keep compatibility with Home Assistant 0.109
Expand All @@ -35,7 +33,6 @@
ATTR_DEVICE_MODEL,
ATTR_DEVICE_ID,
ACCOUNT_CONTROLLER,
SIGNAL_UPDATE_JQ300,
CONF_ACCOUNT_ID,
)

Expand Down Expand Up @@ -114,19 +111,6 @@ def __init__(
self._icon = BINARY_SENSORS[sensor_id][2]
self._device_class = BINARY_SENSORS[sensor_id][3]

async def async_added_to_hass(self):
"""Register callbacks."""
self.async_on_remove(
async_dispatcher_connect(
self.hass, SIGNAL_UPDATE_JQ300, self._update_callback
)
)

@callback
def _update_callback(self):
"""Call update method."""
self.async_schedule_update_ha_state(True)

@property
def name(self):
"""Return the name of the binary sensor."""
Expand Down Expand Up @@ -169,11 +153,16 @@ def icon(self):
@property
def should_poll(self):
"""Return the polling state."""
return False
return True

def update(self):
"""Update the sensor state if it needed."""
ret = self._account.get_sensors_raw(self._device_id)
if ret:
self._state = ret[self._sensor_id]
_LOGGER.debug("Update state: %s = %s", self.entity_id, self._state)
if not ret:
return

if self._state == ret[self._sensor_id]:
return

self._state = ret[self._sensor_id]
_LOGGER.debug("Update state: %s = %s", self.entity_id, self._state)
3 changes: 1 addition & 2 deletions custom_components/jq300/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,9 @@

SENSORS_FILTER_FRAME = timedelta(minutes=5)

SIGNAL_UPDATE_JQ300 = "jq300_update"

QUERY_TIMEOUT = 7 # seconds
UPDATE_TIMEOUT = 12 # seconds
AVAILABLE_TIMEOUT = 30 # seconds

MWEIGTH_TVOC = 56.1060 # g/mol
MWEIGTH_HCHO = 30.0260 # g/mol
42 changes: 14 additions & 28 deletions custom_components/jq300/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
from homeassistant import exceptions
from homeassistant.components.sensor import ENTITY_ID_FORMAT
from homeassistant.const import CONF_DEVICES
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity, async_generate_entity_id

from . import JqAccount, CannotConnect
Expand All @@ -29,7 +27,6 @@
ATTR_DEVICE_ID,
ACCOUNT_CONTROLLER,
CONF_ACCOUNT_ID,
SIGNAL_UPDATE_JQ300,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -109,19 +106,6 @@ def __init__(
self._icon = SENSORS[sensor_id][2]
self._device_class = SENSORS[sensor_id][3]

async def async_added_to_hass(self):
"""Register callbacks."""
self.async_on_remove(
async_dispatcher_connect(
self.hass, SIGNAL_UPDATE_JQ300, self._update_callback
)
)

@callback
def _update_callback(self):
"""Call update method."""
self.async_schedule_update_ha_state(True)

@property
def name(self):
"""Return the name of the sensor."""
Expand Down Expand Up @@ -170,19 +154,21 @@ def unit_of_measurement(self):
@property
def should_poll(self):
"""Return the polling state."""
return False
return True

def update(self):
"""Update the sensor state if it needed."""
ret = self._account.get_sensors(self._device_id)
if ret:
self._state = ret[self._sensor_id]
self._state_raw = self._account.get_sensors_raw(self._device_id)[
self._sensor_id
]
_LOGGER.debug(
"Update state: %s = %s (%s)",
self.entity_id,
self._state,
self._state_raw,
)
if not ret:
return

state = ret[self._sensor_id]
state_raw = self._account.get_sensors_raw(self._device_id)[self._sensor_id]
if self._state == state and self._state_raw == state_raw:
return

self._state = state
self._state_raw = state_raw
_LOGGER.debug(
"Update state: %s = %s (%s)", self.entity_id, self._state, self._state_raw,
)

0 comments on commit bd0e44e

Please sign in to comment.