From 3233ed24cbe025d3f8bf8061243f794ab6e9c387 Mon Sep 17 00:00:00 2001 From: kloemi Date: Fri, 17 Nov 2023 23:26:04 +0100 Subject: [PATCH] Close socket if no game is nearby --- custom_components/samsvolleyball/__init__.py | 32 ++++++++++++++++---- custom_components/samsvolleyball/const.py | 12 ++++++-- custom_components/samsvolleyball/sensor.py | 19 +++++++++++- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/custom_components/samsvolleyball/__init__.py b/custom_components/samsvolleyball/__init__.py index d752a09..08e6989 100644 --- a/custom_components/samsvolleyball/__init__.py +++ b/custom_components/samsvolleyball/__init__.py @@ -13,7 +13,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.util import dt as dt_util -from .const import CONF_HOST, CONF_REGION, DOMAIN, NO_GAME_TIMEOUT, PLATFORMS, VERSION +from .const import CONF_HOST, CONF_REGION, DOMAIN, NO_GAME, PLATFORMS, TIMEOUT, VERSION _LOGGER = logging.getLogger(__name__) @@ -73,7 +73,7 @@ def __init__( self.last_receive_ts = dt_util.as_timestamp(dt_util.utcnow()) self.connected = False self.loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() - self.receive_timout = NO_GAME_TIMEOUT + self.receive_timout = TIMEOUT[NO_GAME] super().__init__(hass, _LOGGER, name=self.name) @@ -87,7 +87,7 @@ async def _on_close(self): self.connected = False async def _on_open(self): - _LOGGER.debug("Connection opened") + _LOGGER.info("Connection opened") self.connected = True async def update_data(self, data): @@ -100,8 +100,13 @@ async def _on_message(self, message: WSMessage): _LOGGER.debug("Received data: %s ", str(message)[1:500]) if data: await self.update_data(data) + if self.receive_timout == TIMEOUT[NO_GAME]: + _LOGGER.info("%s - no game active - close socket.", self.name) + self._disconnect() else: - _LOGGER.info("Received unexpected message: %s ", str(message)[1:500]) + _LOGGER.info( + "%s - received unexpected message: %s ", self.name, str(message)[1:500] + ) async def _process_messages(self): try: @@ -111,7 +116,7 @@ async def _process_messages(self): _LOGGER.warning("Sams Websocket runtime error %s", exc) await self._on_close() except ConnectionResetError: - _LOGGER.info("Sams Websocket Connection Reset") + _LOGGER.info("%s Websocket Connection Reset", self.name) await self._on_close() except Exception as exc: # pylint: disable=broad-except _LOGGER.warning( @@ -129,6 +134,7 @@ async def data_received(self): async def connect(self): try: self.ws = await self.session.ws_connect(self.websocket_url, autoclose=False) + self.loop = asyncio.get_event_loop() self.ws_task = self.loop.create_task(self._process_messages()) await self._on_open() except Exception as exc: # pylint: disable=broad-except @@ -146,13 +152,27 @@ async def disconnect(self): async def check_timeout(self, now): # check last received data time + await self.update_timeout() ts = dt_util.as_timestamp(now) diff = ts - self.last_receive_ts if diff > self.receive_timout: self.last_receive_ts = ts # prevent rush of reconnects - _LOGGER.info("Sams Websocket reset - receive data timeout") + _LOGGER.info("%s Sams Websocket reset - receive data timeout", self.name) + await self.disconnect() + await self.connect() + + async def update_timeout(self): + match_active = NO_GAME + for _, active_cb in list(self._listeners.values()): + # call function get_active_state + active = active_cb() + if active > match_active: + match_active = active + timeout = TIMEOUT[match_active] + if timeout < self.receive_timout: await self.disconnect() await self.connect() + self.receive_timout = timeout def hasListener(self) -> bool: return len(self._listeners) > 0 diff --git a/custom_components/samsvolleyball/const.py b/custom_components/samsvolleyball/const.py index 29fe199..14c0d05 100644 --- a/custom_components/samsvolleyball/const.py +++ b/custom_components/samsvolleyball/const.py @@ -41,8 +41,16 @@ "vvrp", ] -TIMEOUT_PERIOD_CHECK = 5 # sec -NO_GAME_TIMEOUT = 12 * 60 # 12 min. +TIMEOUT_PERIOD_CHECK = 30 # sec +NO_GAME = 0 +NEAR_GAME = 1 +IN_GAME = 2 + +TIMEOUT = { + NO_GAME: 2 * 60 * 60, # 2h min. + NEAR_GAME: 12 * 60, # 12 min. + IN_GAME: 5 * 60, # 5 min. +} DEFAULT_ICON = "mdi:volleyball" VOLLEYBALL = "volleyball" diff --git a/custom_components/samsvolleyball/sensor.py b/custom_components/samsvolleyball/sensor.py index 43e3bcb..05c4e64 100644 --- a/custom_components/samsvolleyball/sensor.py +++ b/custom_components/samsvolleyball/sensor.py @@ -12,6 +12,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.util import dt as dt_util from homeassistant.util import slugify from . import SamsDataCoordinator @@ -22,6 +23,10 @@ CONF_TEAM_UUID, DEFAULT_ICON, DOMAIN, + IN_GAME, + NEAR_GAME, + NO_GAME, + STATES_IN, STATES_NOT_FOUND, STATES_PRE, TIMEOUT_PERIOD_CHECK, @@ -73,7 +78,7 @@ def __init__( entry: ConfigEntry, ) -> None: """Initialize sensor base entity.""" - super().__init__(coordinator) + super().__init__(coordinator, context=self.get_active_state) self.hass = hass self._coordinator = coordinator @@ -114,6 +119,18 @@ def update_team(self, data): self._state = STATES_NOT_FOUND self._match = None + def get_active_state(self): + # check if we are nearby (2 hours before / 3 hours behind) + if self._state != STATES_NOT_FOUND: + if self._state == STATES_IN: + return IN_GAME + if self._match and "date" in self._attr: + date = self._attr["date"] + duration = (dt_util.now() - date).total_seconds() + if duration > (-2 * 60 * 60) and duration < (3 * 60 * 60): + return NEAR_GAME + return NO_GAME + @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator."""