Skip to content
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
24 changes: 24 additions & 0 deletions custom_components/petlibro/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,30 @@ async def device_get_bound_pets(self, device_sn: str) -> list[dict]:
_LOGGER.debug("Bound pets retrieved successfully")
return data or []

async def device_wear_list(self, device_sn: str) -> list[dict]:
"""Get wear/RFID data for pets bound to a device, with caching."""
now = utcnow()
cache_key = f"{device_sn}_wearListV2"
last_call_time = self._last_api_call_times.get(cache_key)

if last_call_time and (now - last_call_time) < timedelta(seconds=10):
_LOGGER.debug(f"Skipping wearListV2 request for {device_sn}, using cached response.")
return self._cached_responses.get(cache_key, [])

try:
response = await self.session.request("POST", "/device/device/wear/wearListV2", json={
"deviceSn": device_sn,
"type": 1
})

self._last_api_call_times[cache_key] = now
self._cached_responses[cache_key] = response if isinstance(response, list) else []

return self._cached_responses[cache_key]
except Exception as e:
_LOGGER.error(f"Error fetching wearListV2 for device {device_sn}: {e}")
raise PetLibroAPIError(f"Error fetching wearListV2 for device {device_sn}: {e}")

# Support for new switch functions
async def set_feeding_plan(self, serial: str, enable: bool):
"""Set the feeding plan on/off."""
Expand Down
52 changes: 52 additions & 0 deletions custom_components/petlibro/pets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,45 @@ async def refresh(self) -> None:
"""Refresh the pet info from the API."""
pet_details = await self.api.pets.get_details(self.id)
bound_devices = await self.api.pets.get_bound_devices(self.id)

# Fetch per-pet drinking data from RFID fountains
fountain_drinking = {"todayFountainDrinkingCount": 0,
"todayFountainDrinkingAmount": 0,
"todayFountainDrinkingTime": 0}

# Collect RFID fountain serial numbers from bound devices and hub devices
fountain_sns = set()
for d in (bound_devices or []):
if d.get("productName") == "Dockstream Smart RFID Fountain":
sn = d.get("deviceSn")
if sn:
fountain_sns.add(sn)

# Also check hub's loaded devices for RFID fountains (shared accounts
# return empty from getBoundDevices)
if self.hub and self.hub.devices:
from ..devices.fountains.dockstream_smart_rfid_fountain import DockstreamSmartRFIDFountain
for device in self.hub.devices.values():
if isinstance(device, DockstreamSmartRFIDFountain):
fountain_sns.add(device.serial)

for device_sn in fountain_sns:
try:
wear_list = await self.api.device_wear_list(device_sn)
for entry in wear_list:
if entry.get("petId") == self.id:
fountain_drinking["todayFountainDrinkingCount"] += (entry.get("todayDrinkTimes") or 0)
fountain_drinking["todayFountainDrinkingAmount"] += (entry.get("todayDrinkAmount") or 0)
fountain_drinking["todayFountainDrinkingTime"] += (entry.get("petEatingTime") or 0)
break
except Exception:
_LOGGER.warning("Failed to fetch wearListV2 for fountain %s", device_sn)

self.update_data(
{
**pet_details,
"boundDevices": bound_devices,
**fountain_drinking,
}
)

Expand Down Expand Up @@ -298,3 +333,20 @@ def trainingGoal(self) -> float:
def walkingGoal(self) -> float:
"""Walking goal of pet in minutes per day."""
return self._data.get("walkingGoal") or 0

# --- Fountain Drinking (from wearListV2)

@property
def today_fountain_drinking_count(self) -> int:
"""Number of drinking sessions at RFID fountains today."""
return self._data.get("todayFountainDrinkingCount") or 0

@property
def today_fountain_drinking_amount(self) -> int:
"""Total milliliters consumed at RFID fountains today."""
return self._data.get("todayFountainDrinkingAmount") or 0

@property
def today_fountain_drinking_time(self) -> int:
"""Total seconds spent drinking at RFID fountains today."""
return self._data.get("todayFountainDrinkingTime") or 0
28 changes: 27 additions & 1 deletion custom_components/petlibro/pets/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
SensorEntityDescription,
dataclass,
)
from homeassistant.components.sensor.const import SensorDeviceClass
from homeassistant.components.sensor.const import SensorDeviceClass, SensorStateClass
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import (
Expand Down Expand Up @@ -557,6 +557,32 @@ async def _async_update_avatar(self, url: str | None) -> None:
else (bday.replace(year=today.year + 1) - today).days,
} if pet.age else None,
),
PL_PetSensorEntityDescription(
key="today_fountain_drinking_count",
translation_key="today_fountain_drinking_count",
name="Today's Fountain Drinking Count",
icon="mdi:water-plus",
state_class=SensorStateClass.TOTAL_INCREASING,
),
PL_PetSensorEntityDescription(
key="today_fountain_drinking_amount",
translation_key="today_fountain_drinking_amount",
name="Today's Fountain Water Consumption",
icon="mdi:cup-water",
state_class=SensorStateClass.TOTAL_INCREASING,
device_class=SensorDeviceClass.VOLUME,
native_unit_of_measurement=UnitOfVolume.MILLILITERS,
petlibro_unit=API.WATER_UNIT,
),
PL_PetSensorEntityDescription(
key="today_fountain_drinking_time",
translation_key="today_fountain_drinking_time",
name="Today's Fountain Drinking Time",
icon="mdi:timer-outline",
state_class=SensorStateClass.TOTAL_INCREASING,
device_class=SensorDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.SECONDS,
),
),
PL_PetImageEntity: (
PL_PetImageEntityDescription(
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,15 @@
},
"rfid": {
"name": "طوق RFID"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/bn.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "RFID কলার"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "RFID-halsbånd"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "RFID-Halsband"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,15 @@
},
"rfid": {
"name": "RFID Collar"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "Collar RFID"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "Collier RFID"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "RFID कॉलर"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
21 changes: 15 additions & 6 deletions custom_components/petlibro/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
}
}
},
"options": {
"options": {
"abort": {
"no_member_data": "Dati membro non caricati, controlla i log",
"account_settings_abort": "{account_settings_abort}",
Expand All @@ -35,13 +35,13 @@
"error": {
"unknown": "Errore imprevisto"
},
"step": {
"init": {
"step": {
"init": {
"menu_options": {
"integration_settings": "Impostazioni integrazione",
"account_settings": "Impostazioni account"
}
},
},
"integration_settings": {
"title": "Impostazioni Integrazione",
"data": {
Expand Down Expand Up @@ -274,6 +274,15 @@
},
"rfid": {
"name": "Collare RFID"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down Expand Up @@ -517,7 +526,7 @@
"pet_sex": {
"name": "Sesso",
"state": {
"none":"Nessuno",
"none": "Nessuno",
"male": "Maschio",
"female": "Femmina"
}
Expand All @@ -534,4 +543,4 @@
}
}
}
}
}
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "RFID首輪"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "RFID-halsband"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "Coleira RFID"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
9 changes: 9 additions & 0 deletions custom_components/petlibro/translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@
},
"rfid": {
"name": "RFID-ошейник"
},
"today_fountain_drinking_count": {
"name": "Today's Fountain Drinking Count"
},
"today_fountain_drinking_amount": {
"name": "Today's Fountain Water Consumption"
},
"today_fountain_drinking_time": {
"name": "Today's Fountain Drinking Time"
}
},
"image": {
Expand Down
Loading
Loading