Skip to content

Commit

Permalink
Merge pull request #103 from natekspencer/dev
Browse files Browse the repository at this point in the history
Limit firmware check to every 15 minutes unless forced
  • Loading branch information
natekspencer authored Jan 11, 2023
2 parents 2479719 + ffd82c5 commit 39d51d2
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# pylitterbot

Python package for controlling Whisker automatic robots.
Python package for controlling a Whisker connected self-cleaning litter boxes and feeders.

This is an unofficial API for controlling various Whisker automated robots. It currently supports Litter-Robot 3, Litter-Robot 4 and Feeder-Robot.

Expand Down
67 changes: 41 additions & 26 deletions pylitterbot/robot/litterrobot4.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ class LitterRobot4(LitterRobot): # pylint: disable=abstract-method
_litter_level = LITTER_LEVEL_EMPTY
_litter_level_exp: datetime | None = None

_firmware_details: dict[str, bool | dict[str, str]] | None = None
_firmware_details_requested: datetime | None = None

def __init__(self, data: dict, account: Account) -> None:
"""Initialize a Litter-Robot 4."""
super().__init__(data, account)
Expand Down Expand Up @@ -496,46 +499,58 @@ async def get_insight(
],
)

async def get_firmware_details(self) -> dict[str, bool | dict[str, str]] | None:
async def get_firmware_details(
self, force_check: bool = False
) -> dict[str, bool | dict[str, str]] | None:
"""Get the firmware details."""
data = await self._post(
json={
"query": """
query getFirmwareDetails($serial: String!) {
litterRobot4CompareFirmwareVersion(serial: $serial) {
isEspFirmwareUpdateNeeded
isPicFirmwareUpdateNeeded
isLaserboardFirmwareUpdateNeeded
latestFirmware {
espFirmwareVersion
picFirmwareVersion
laserBoardFirmwareVersion
if (
force_check
or not self._firmware_details
or (requested := self._firmware_details_requested) is None
or requested + timedelta(minutes=15) < utcnow()
):
data = await self._post(
json={
"query": """
query getFirmwareDetails($serial: String!) {
litterRobot4CompareFirmwareVersion(serial: $serial) {
isEspFirmwareUpdateNeeded
isPicFirmwareUpdateNeeded
isLaserboardFirmwareUpdateNeeded
latestFirmware {
espFirmwareVersion
picFirmwareVersion
laserBoardFirmwareVersion
}
}
}
}
""",
"variables": {"serial": self.serial},
}
)
data = cast(Dict[str, Dict[str, Dict[str, Union[bool, Dict[str, str]]]]], data)
return data.get("data", {}).get("litterRobot4CompareFirmwareVersion", {})
""",
"variables": {"serial": self.serial},
}
)
self._firmware_details = (
cast(Dict[str, Dict[str, Dict[str, Union[bool, Dict[str, str]]]]], data)
.get("data", {})
.get("litterRobot4CompareFirmwareVersion", {})
)
self._firmware_details_requested = utcnow()
return self._firmware_details

async def get_latest_firmware(self) -> str | None:
async def get_latest_firmware(self, force_check: bool = False) -> str | None:
"""Get the latest firmware available."""
if (firmware := await self.get_firmware_details()) is None:
if (firmware := await self.get_firmware_details(force_check)) is None:
return None

latest_firmware = (firmware).get("latestFirmware", {})
latest_firmware = cast(Dict[str, str], latest_firmware)
latest_firmware = cast(Dict[str, str], firmware.get("latestFirmware", {}))
return (
f"ESP: {latest_firmware.get('espFirmwareVersion')} / "
f"PIC: {latest_firmware.get('picFirmwareVersion')} / "
f"TOF: {latest_firmware.get('laserBoardFirmwareVersion')}"
)

async def has_firmware_update(self) -> bool:
async def has_firmware_update(self, force_check: bool = False) -> bool:
"""Check if a firmware update is available."""
if (firmware := await self.get_firmware_details()) is None:
if (firmware := await self.get_firmware_details(force_check)) is None:
return False
return any(value for value in firmware.values() if isinstance(value, bool))

Expand Down
6 changes: 2 additions & 4 deletions tests/test_litterrobot4.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,7 @@ async def test_litter_robot_4(
version_info["isEspFirmwareUpdateNeeded"] = False
version_info["isPicFirmwareUpdateNeeded"] = False
mock_aioresponse.post(LR4_ENDPOINT, payload=firmware_response)
assert not await robot.has_firmware_update()

mock_aioresponse.post(LR4_ENDPOINT, payload=firmware_response)
assert not await robot.has_firmware_update(True)
latest_firmware = await robot.get_latest_firmware()
assert latest_firmware == "ESP: 1.1.54 / PIC: 10512.2560.2.66 / TOF: 4.0.65.4"

Expand Down Expand Up @@ -302,7 +300,7 @@ async def test_litter_robot_4(
],
}
mock_aioresponse.post(LR4_ENDPOINT, payload=firmware_response, repeat=True)
assert not await robot.has_firmware_update()
assert not await robot.has_firmware_update(True)
assert not await robot.get_latest_firmware()

await robot._account.disconnect()
Expand Down

0 comments on commit 39d51d2

Please sign in to comment.