Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed issue with cached data being fetched from the API #313

Merged
merged 2 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions custom_components/panasonic_cc/pcomfortcloud/apiclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
'''

import logging
import re
import aiohttp
import time
from datetime import datetime
Expand Down Expand Up @@ -43,6 +42,7 @@ def __init__(self,
self._groups = None
self._devices: list[PanasonicDeviceInfo] = None
self._unknown_devices: list[PanasonicDeviceInfo] = []
self._cache_devices = {}

self._device_indexer = {}
self._raw = raw
Expand Down Expand Up @@ -134,14 +134,27 @@ async def history(self, device_id, mode, date, time_zone=""):
}


async def _get_device_status(self, device_info: PanasonicDeviceInfo):
if (device_info.status_data_mode == constants.StatusDataMode.LIVE
or (device_info.id in self._cache_devices and self._cache_devices[device_info.id] <= 0)):
try:
json_response = await self.execute_get(self._get_device_status_url(device_info.guid), "get_status", 200)
device_info.status_data_mode = constants.StatusDataMode.LIVE
return json_response
except Exception as e:
_LOGGER.warning("Failed to get live status for device {} switching to cached data.".format(device_info.guid))
device_info.status_data_mode = constants.StatusDataMode.CACHED
self._cache_devices[device_info.id] = 10
json_response = await self.execute_get(self._get_device_status_now_url(device_info.guid), "get_status", 200)
self._cache_devices[device_info.id] -= 1
return json_response

async def get_device(self, device_info: PanasonicDeviceInfo) -> PanasonicDevice:
json_response = await self.execute_get(self._get_device_status_now_url(device_info.guid), "get_device", 200)
json_response = await self._get_device_status(device_info)
return PanasonicDevice(device_info, json_response)

async def try_update_device(self, device: PanasonicDevice) -> bool:
device_guid = device.info.guid
json_response = await self.execute_get(self._get_device_status_now_url(device_guid), "try_update", 200)
json_response = await self._get_device_status(device.info)
return device.load(json_response)

async def get_aquarea_device(self, device_info: PanasonicDeviceInfo):
Expand Down
4 changes: 4 additions & 0 deletions custom_components/panasonic_cc/pcomfortcloud/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ class IAutoXMode(Enum):
Off = 1
On = 2

class StatusDataMode(Enum):
LIVE = 0
CACHED = 1

INVALID_TEMPERATURE = 126

DEFAULT_X_APP_VERSION = "1.21.0"
Expand Down
20 changes: 19 additions & 1 deletion custom_components/panasonic_cc/pcomfortcloud/panasonicdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def read_enum(json, key, type, default_value):
try:
return type(json[key])
except Exception as es:
_LOGGER.warn("Error reading property '%s' with value '%s'", key, json[key], exc_info= es)
_LOGGER.warning("Error reading property '%s' with value '%s'", key, json[key], exc_info= es)
return default_value

def read_value(json, key, default_value):
Expand All @@ -34,6 +34,7 @@ def __init__(self, json = None) -> None:
self.model = ''
self._has_parameters = False
self._raw = None
self._status_data_mode = constants.StatusDataMode.LIVE
self.load(json)


Expand All @@ -58,6 +59,17 @@ def is_valid(self):
@property
def raw(self):
return self._raw

@property
def status_data_mode(self):
return self._status_data_mode
@status_data_mode.setter
def status_data_mode(self, value: constants.StatusDataMode):
self._status_data_mode = value






class PanasonicDevice:
Expand All @@ -66,11 +78,16 @@ def __init__(self, info: PanasonicDeviceInfo, json = None) -> None:
self._features: PanasonicDeviceFeatures = None
self._parameters: PanasonicDeviceParameters = None
self._last_update = datetime.now(timezone.utc)
self._timestamp: datetime = None
self.load(json)

@property
def id(self)->str:
return self.info.id

@property
def timestamp(self)->datetime:
return self._timestamp

@property
def info(self) -> PanasonicDeviceInfo:
Expand Down Expand Up @@ -150,6 +167,7 @@ def load(self, json) -> bool:
has_changed = True if self._parameters.load(json_parameters) else has_changed
if has_changed:
self._last_update = datetime.now(timezone.utc)
self._timestamp = datetime.fromtimestamp(json['timestamp'] / 1000, timezone.utc)
return has_changed


Expand Down
29 changes: 29 additions & 0 deletions custom_components/panasonic_cc/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
)

from .pcomfortcloud.panasonicdevice import PanasonicDevice, PanasonicDeviceEnergy, PanasonicDeviceZone
from .pcomfortcloud import constants

from .const import (
DOMAIN,
Expand Down Expand Up @@ -68,6 +69,32 @@ class PanasonicEnergySensorEntityDescription(SensorEntityDescription):
is_available=lambda device: True,
entity_registry_enabled_default=False,
)
DATA_AGE_DESCRIPTION = PanasonicSensorEntityDescription(
key="data_age",
translation_key="data_age",
name="Data Age",
icon="mdi:clock-outline",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=None,
native_unit_of_measurement=None,
get_state=lambda device: device.timestamp,
is_available=lambda device: True,
entity_registry_enabled_default=True,
)
DATA_MODE_DESCRIPTION = PanasonicSensorEntityDescription(
key="status_data_mode",
translation_key="status_data_mode",
name="Data Mode",
options=[opt.name for opt in constants.StatusDataMode],
device_class=SensorDeviceClass.ENUM,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=None,
native_unit_of_measurement=None,
get_state=lambda device: device.info.status_data_mode.name,
is_available=lambda device: True,
entity_registry_enabled_default=True,
)
DAILY_ENERGY_DESCRIPTION = PanasonicEnergySensorEntityDescription(
key="daily_energy_sensor",
translation_key="daily_energy_sensor",
Expand Down Expand Up @@ -151,6 +178,8 @@ async def async_setup_entry(hass, entry, async_add_entities):
entities.append(PanasonicSensorEntity(coordinator, INSIDE_TEMPERATURE_DESCRIPTION))
entities.append(PanasonicSensorEntity(coordinator, OUTSIDE_TEMPERATURE_DESCRIPTION))
entities.append(PanasonicSensorEntity(coordinator, LAST_UPDATE_TIME_DESCRIPTION))
entities.append(PanasonicSensorEntity(coordinator, DATA_AGE_DESCRIPTION))
entities.append(PanasonicSensorEntity(coordinator, DATA_MODE_DESCRIPTION))
if coordinator.device.has_zones:
for zone in coordinator.device.parameters.zones:
entities.append(PanasonicSensorEntity(
Expand Down