Add Tapo C460 support (#1645)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CI / Python 3.11 on macos-latest (push) Has been cancelled
CI / Python 3.12 on macos-latest (push) Has been cancelled
CI / Python 3.13 on macos-latest (push) Has been cancelled
CI / Python 3.11 on ubuntu-latest (push) Has been cancelled
CI / Python 3.12 on ubuntu-latest (push) Has been cancelled
CI / Python 3.13 on ubuntu-latest (push) Has been cancelled
CI / Python 3.11 on windows-latest (push) Has been cancelled
CI / Python 3.12 on windows-latest (push) Has been cancelled
CI / Python 3.13 on windows-latest (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
Stale / stale (push) Has been cancelled

Changes include:
- New smartcam fixture for C460
- Battery module updates to safely handle optional temperature and
voltage fields
This commit is contained in:
Mark Van Praet
2026-02-21 10:20:01 -05:00
committed by GitHub
parent 55f9959777
commit ade64c64af
5 changed files with 1180 additions and 41 deletions

View File

@@ -1,8 +1,9 @@
"""Implementation of baby cry detection module."""
"""Implementation of smartcam battery module."""
from __future__ import annotations
import logging
from typing import Any
from ...feature import Feature
from ..smartcammodule import SmartCamModule
@@ -44,32 +45,37 @@ class Battery(SmartCamModule):
)
)
self._add_feature(
Feature(
self._device,
"battery_temperature",
"Battery temperature",
container=self,
attribute_getter="battery_temperature",
icon="mdi:battery",
unit_getter=lambda: "celsius",
category=Feature.Category.Debug,
type=Feature.Type.Sensor,
# Optional on some battery cameras (e.g., C460).
if self._optional_float_sysinfo("battery_temperature") is not None:
self._add_feature(
Feature(
self._device,
"battery_temperature",
"Battery temperature",
container=self,
attribute_getter="battery_temperature",
icon="mdi:battery",
unit_getter=lambda: "celsius",
category=Feature.Category.Debug,
type=Feature.Type.Sensor,
)
)
)
self._add_feature(
Feature(
self._device,
"battery_voltage",
"Battery voltage",
container=self,
attribute_getter="battery_voltage",
icon="mdi:battery",
unit_getter=lambda: "V",
category=Feature.Category.Debug,
type=Feature.Type.Sensor,
if self._optional_float_sysinfo("battery_voltage") is not None:
self._add_feature(
Feature(
self._device,
"battery_voltage",
"Battery voltage",
container=self,
attribute_getter="battery_voltage",
icon="mdi:battery",
unit_getter=lambda: "V",
category=Feature.Category.Debug,
type=Feature.Type.Sensor,
)
)
)
self._add_feature(
Feature(
self._device,
@@ -83,6 +89,18 @@ class Battery(SmartCamModule):
)
)
def _optional_float_sysinfo(self, key: str) -> float | None:
"""Return sys_info[key] as float, or None if not available or invalid."""
v_any: Any = self._device.sys_info.get(key)
if v_any in (None, "NO"):
return None
try:
# Accept ints/floats and numeric strings.
return float(v_any)
except (TypeError, ValueError):
return None
def query(self) -> dict:
"""Query to execute during the update cycle."""
return {}
@@ -98,16 +116,22 @@ class Battery(SmartCamModule):
return self._device.sys_info["low_battery"]
@property
def battery_temperature(self) -> bool:
"""Return battery voltage in C."""
return self._device.sys_info["battery_temperature"]
def battery_temperature(self) -> float | None:
"""Return battery temperature in °C (if available)."""
return self._optional_float_sysinfo("battery_temperature")
@property
def battery_voltage(self) -> bool:
"""Return battery voltage in V."""
return self._device.sys_info["battery_voltage"] / 1_000
def battery_voltage(self) -> float | None:
"""Return battery voltage in V (if available)."""
v = self._optional_float_sysinfo("battery_voltage")
return None if v is None else v / 1_000
@property
def battery_charging(self) -> bool:
"""Return True if battery is charging."""
return self._device.sys_info["battery_voltage"] != "NO"
v = self._device.sys_info.get("battery_charging")
if isinstance(v, bool):
return v
if v is None:
return False
return str(v).strip().lower() in ("yes", "true", "1", "charging", "on")