OzWrapper.OzAnomaly.detector.AnomalyDetector

class OzWrapper.OzAnomaly.detector.AnomalyDetector(device_id: str, device_type: str, config: Dict[str, Any], data_provider: OzWrapper.OzAnomaly.data_provider.DataProvider, *, scheduler: OzWrapper.OzAnomaly.scheduler.Scheduler | None = None)

Runs the full anomaly-check pipeline for a single device.

Instantiate once per device (or once and pass the device context at call time if you prefer; the current API takes the device in __init__ to match the cloud service it replaces). Call run() on a schedule.

The detector is stateless across runs — repeated calls are safe.

Args: device_id: Device identifier (e.g. "PM01P0013"). device_type: Measurement/type name ("DUSTROID",

"ODOSENSE", etc.).

config: Device config dict — shape matches the cloud service’s

expectation (ogs, soft.config, cloud.interval).

data_provider: Source of recent sensor data. See

DataProvider.

scheduler: Optional Scheduler for “run only once per N

hours” behaviour, persisted across reboots. When provided, callers should use run_if_due(). Without it, every run() / run_if_due() call executes immediately.

_collect_fields(window_24: OzWrapper.OzAnomaly.data_provider.Window, window_48: OzWrapper.OzAnomaly.data_provider.Window | None, rename_dict: Dict[str, str], missing_para_dict: Dict[str, int]) Dict[str, Any]

Run every check and merge into a single fields dict.

Implements the early-exit rule: if e3 exceeds _E3_EARLY_EXIT, the other fields are not trustworthy and we return only e3.

run() AnomalyResult | None

Fetch windows, run all checks, return a result.

Returns:

An AnomalyResult whose fields may be empty (no anomalies) or may contain only {"e3": ...} when data is too incomplete to evaluate other checks.

None is returned for:

  • Device IDs starting with OZ or TEST (test devices).

  • No 24 h data available.

run_if_due(schedule_hours: float) AnomalyResult | None

Run the detector only if the schedule says it’s time.

Behaviour:

  • No scheduler attached — always runs (equivalent to run()).

  • Scheduler present, not due — returns None immediately without touching the data provider.

  • Scheduler present, due — calls run(). On a non-None result the scheduler’s last-run timestamp is updated. A None result (test device, no data) leaves the scheduler clock alone so the next loop tick can retry.

Parameters:

schedule_hours – Minimum hours between runs. Fractional values are allowed (e.g. 0.25 for every 15 minutes).

Returns:

The AnomalyResult from run(), or None if the schedule blocked the run or run() returned None.

config
data_provider
device_id
device_type
scheduler = None