FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

SMART energy module stubs get_daily_stats/get_monthly_stats even when the firmware supports get_energy_data · Issue #1734 · python-kasa/python-kasa · GitHub

SMART energy module stubs get_daily_stats/get_monthly_stats even when the firmware supports get_energy_data #1734

Description

SMART energy module stubs get_daily_stats/get_monthly_stats even when the firmware supports get_energy_data

Summary

The SMART energy module unconditionally raises KasaException("Device does not support periodic statistics") for both get_daily_stats and get_monthly_stats, for every SMART/KLAP device — regardless of whether the device firmware actually supports historical energy queries.

Many SMART metering devices (e.g. KP125M, P110/P115, etc.) implement a get_energy_data method that returns per-day and per-month history. Because the module stubs the interface methods out, none of that history is reachable through python-kasa, even though the equivalent IOT module (kasa/iot/modules/emeter.py) does implement get_daily_stats/get_monthly_stats. The result is that the library can only report current month/day totals (get_energy_usage) for SMART meters, while the Kasa mobile app shows the full history from the same device.

Where

async def get_daily_stats(
self, *, year: int | None = None, month: int | None = None, kwh: bool = True
) -> dict:
"""Return daily stats for the given year & month.
The return value is a dictionary of {day: energy, ...}.
"""
raise KasaException("Device does not support periodic statistics")
async def get_monthly_stats(
self, *, year: int | None = None, kwh: bool = True
) -> dict:
"""Return monthly stats for the given year."""
raise KasaException("Device does not support periodic statistics")

async def get_daily_stats(self, *, year=None, month=None, kwh=True) -> dict:
    """Return daily stats for the given year & month."""
    raise KasaException("Device does not support periodic statistics")

async def get_monthly_stats(self, *, year=None, kwh=True) -> dict:
    """Return monthly stats for the given year."""
    raise KasaException("Device does not support periodic statistics")

Affected / tested device

  • Model: KP125M(US)
  • Type: SMART.KASAPLUG, encryption KLAP, login v2
  • Energy component: {'id': 'energy_monitoring', 'ver_code': 2}
  • python-kasa: 0.10.2 (stub also present on master @ a29d061)

Reproduction

energy = dev.modules[Module.Energy]
await energy.get_monthly_stats(year=2026)
# kasa.exceptions.KasaException: Device does not support periodic statistics

…yet the firmware answers get_energy_data directly. A raw query returns real history:

resp = await dev.protocol.query({
    "get_energy_data": {
        "start_timestamp": <local Jan 1 00:00 of the year>,
        "end_timestamp":   <local Jan 1 00:00 of the next year>,
        "interval": 43200,   # minutes; 43200 = monthly, 1440 = daily, 60 = hourly
    }
})
# -> {"get_energy_data": {
#      "start_timestamp": ..., "end_timestamp": ..., "interval": 43200, "local_time": ...,
#      "data": [<Wh for Jan>, <Wh for Feb>, ... 12 buckets ...]
#    }}

Behaviour notes discovered while testing (relevant to any implementation)

These are firmware constraints on get_energy_data, not python-kasa bugs, but an implementation has to respect them:

  1. The request must be period-aligned, and the interval selects the bucket size:
    • interval=43200 (monthly): start_timestamp = local Jan 1 of a year → returns that year's 12 monthly buckets.
    • interval=1440 (daily): start_timestamp = first day of a quarter → returns that quarter's daily buckets.
    • interval=60 (hourly): start_timestamp = midnight of a day → returns 24 hourly buckets.
      A too-large / misaligned window returns PARAMS_ERROR(-1008).
  2. Responses can paginate — response.end_timestamp may be earlier than the requested end_timestamp; the app re-issues the request with that value as the new start_timestamp and concatenates the data arrays.
  3. Retention differs by resolution: monthly totals are kept for the whole year, but daily granularity only covers a rolling recent window (~3 months on the tested device). Older daily buckets return 0, while the monthly total for that same month is still populated. An implementation should not treat trailing/older zeros as "no data".
  4. Values are in Wh (consistent with get_energy_usage.month_energy).

Proposed approach

  • Implement get_daily_stats/get_monthly_stats in kasa/smart/modules/energy.py on top of get_energy_data, mapping the returned data arrays into the interface's {day: energy} / {month: energy} dict contract and honouring the kwh flag.
  • Gate on capability (component ver_code, and/or a graceful PARAMS_ERROR/unknown-method fallback) so devices that genuinely lack get_energy_data keep raising the existing exception.
  • Encode the alignment + pagination rules above.

Contribution

Happy to open a PR. I have a working KP125M against real hardware and can supply a fixture with representative get_energy_data responses (monthly + daily) plus component_nego / get_energy_usage. Guidance welcome on how you'd prefer to fixture a parameterized call like get_energy_data in the current SMART test framework, since the existing fixtures capture static responses.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


    Back | FazBrowse Home | New Git URL