ESPectre SDK
2.8.0-280-gac7af68
Wi-Fi CSI motion sensing for ESP32 firmware
Toggle main menu visibility
Loading...
Searching...
No Matches
runtime_events.h
Go to the documentation of this file.
1
/*
2
* ESPectre - Runtime Events
3
*
4
* Runtime listener and event contracts.
5
*
6
* Author: Francesco Pace <francesco.pace@gmail.com>
7
* SPDX-License-Identifier: GPL-3.0-only
8
* Commercial licensing available under separate agreement; see LICENSING.md.
9
*/
10
#pragma once
11
12
#include <cstdint>
13
14
#include "
runtime_snapshot.h
"
15
16
namespace
espectre
{
17
18
/**
19
* Everything the runtime tells your firmware.
20
*
21
* Subclass it, override only what your product reacts to, and install it with
22
* `RuntimeFrontendController::setup(listener)`. Every callback has an empty
23
* default, so an integration that only cares about motion overrides one method.
24
*
25
* @par Threading and reentrancy
26
* Callbacks are always delivered on the caller's task, never from an interrupt
27
* or the Wi-Fi driver:
28
* - Sensing events (motion, periodic, live telemetry, calibration completion,
29
* and detector-driven threshold adaptation) originate in the CSI callback
30
* but are deferred through an internal mailbox and dispatched from `loop()`.
31
* - Control-driven events (runtime threshold writes and detector selection)
32
* fire inline on whichever task called the corresponding setter.
33
* `on_threshold_changed()` is used for both: a setter, calibration finish,
34
* or Lightweight settled-level recovery.
35
*
36
* Keep callbacks bounded and non-blocking. Slow work delays the next `loop()`
37
* iteration and can fill the bounded CSI mailbox, causing incoming frames to be
38
* dropped. Queue network publication, NVS writes, and other potentially
39
* blocking work for another task. Calling back into the controller is allowed,
40
* with one exception noted on `on_runtime_fault()`.
41
*
42
* @par Snapshot lifetime
43
* The `snapshot` reference is only valid for the duration of the call. Copy it
44
* if you need it later.
45
*
46
* @par Readiness
47
* Snapshots are delivered during startup calibration as well. Gate anything
48
* user-visible on `RuntimeSnapshot::ready_to_publish` so you do not report
49
* motion from an uncalibrated detector.
50
*/
51
class
IRuntimeListener
{
52
public
:
53
virtual
~IRuntimeListener
() =
default
;
54
55
/**
56
* The debounced motion state changed.
57
*
58
* Edge-triggered and already filtered by `motion_on_hits` / `motion_off_hits`,
59
* so this is the hook for occupancy, relays, and notifications.
60
*
61
* It also fires with `MotionState::IDLE` when the Wi-Fi link drops, and that
62
* call carries `ready_to_publish == false`. The shipped frontends gate on
63
* that flag and therefore leave their last published value in place across a
64
* disconnect; if your product would rather fail open, handle the
65
* not-ready edge explicitly instead of returning early.
66
*
67
* @param snapshot Sensing state at the moment of the change.
68
*/
69
virtual
void
on_motion_state_changed
(
const
RuntimeSnapshot
&snapshot) {}
70
/**
71
* Heartbeat, emitted every `RuntimeConfig::publish_interval_ms` milliseconds.
72
*
73
* Use it for status logging and diagnostics sampling rather than sensing
74
* telemetry. Movement and canonical MQTT telemetry follow detector evaluation
75
* through `on_live_telemetry()`.
76
*
77
* @param snapshot Current sensing state, including the metric and threshold.
78
* @param packets_received CSI packets accepted since the previous heartbeat,
79
* which is the honest measure of the achieved capture rate.
80
*/
81
virtual
void
on_periodic_update
(
const
RuntimeSnapshot
&snapshot, uint32_t packets_received) {}
82
/**
83
* The active threshold changed, from a control call, calibration, or
84
* detector-driven adaptation such as Lightweight settled-level recovery.
85
*
86
* Refresh any threshold you mirror in a UI or a published entity. Live
87
* telemetry still carries the per-sample comparison value; this hook is the
88
* control-plane notification when that value itself has moved.
89
*/
90
virtual
void
on_threshold_changed
(
const
RuntimeSnapshot
&snapshot) {}
91
/**
92
* The active detector changed.
93
*
94
* Thresholds are per-detector, so `on_threshold_changed()` follows this one.
95
*/
96
virtual
void
on_detector_changed
(
const
RuntimeSnapshot
&snapshot) {}
97
/**
98
* Startup calibration began; detection results are not valid yet.
99
*
100
* Lightweight only. ML ships a fixed threshold and completes immediately.
101
*/
102
virtual
void
on_calibration_started
(
const
RuntimeSnapshot
&snapshot) {}
103
/**
104
* Startup calibration finished.
105
*
106
* @param snapshot Sensing state at completion, carrying the applied threshold.
107
* @param success false when calibration was cancelled or could not settle on
108
* a threshold. The runtime keeps sensing with the configured value,
109
* so treat this as a signal to surface, not a fatal error.
110
*/
111
virtual
void
on_calibration_finished
(
const
RuntimeSnapshot
&snapshot,
bool
success) {}
112
/**
113
* High-rate movement stream, one call per detector evaluation.
114
*
115
* Frontends publish canonical telemetry and Movement Score from this hook.
116
* Considerably more frequent than `on_periodic_update()`; suppress it with
117
* `set_live_telemetry_enabled(false)` when nothing is watching.
118
*
119
* @param movement Current motion metric.
120
* @param threshold Threshold it is compared against, on the same scale.
121
*/
122
virtual
void
on_live_telemetry
(
float
movement,
float
threshold) {}
123
/**
124
* A runtime-owned failure your firmware should surface.
125
*
126
* @param message Human-readable cause, valid only for this call.
127
*
128
* Do not drive the runtime from here beyond `shutdown()`: the fault is
129
* reported from inside runtime work, and re-entering control paths from it
130
* is not supported.
131
*/
132
virtual
void
on_runtime_fault
(
const
char
*message) {}
133
};
134
135
}
// namespace espectre
espectre::IRuntimeListener
Everything the runtime tells your firmware.
Definition
runtime_events.h:51
espectre::IRuntimeListener::~IRuntimeListener
virtual ~IRuntimeListener()=default
espectre::IRuntimeListener::on_live_telemetry
virtual void on_live_telemetry(float movement, float threshold)
High-rate movement stream, one call per detector evaluation.
Definition
runtime_events.h:122
espectre::IRuntimeListener::on_calibration_finished
virtual void on_calibration_finished(const RuntimeSnapshot &snapshot, bool success)
Startup calibration finished.
Definition
runtime_events.h:111
espectre::IRuntimeListener::on_motion_state_changed
virtual void on_motion_state_changed(const RuntimeSnapshot &snapshot)
The debounced motion state changed.
Definition
runtime_events.h:69
espectre::IRuntimeListener::on_detector_changed
virtual void on_detector_changed(const RuntimeSnapshot &snapshot)
The active detector changed.
Definition
runtime_events.h:96
espectre::IRuntimeListener::on_calibration_started
virtual void on_calibration_started(const RuntimeSnapshot &snapshot)
Startup calibration began; detection results are not valid yet.
Definition
runtime_events.h:102
espectre::IRuntimeListener::on_threshold_changed
virtual void on_threshold_changed(const RuntimeSnapshot &snapshot)
The active threshold changed, from a control call, calibration, or detector-driven adaptation such as...
Definition
runtime_events.h:90
espectre::IRuntimeListener::on_runtime_fault
virtual void on_runtime_fault(const char *message)
A runtime-owned failure your firmware should surface.
Definition
runtime_events.h:132
espectre::IRuntimeListener::on_periodic_update
virtual void on_periodic_update(const RuntimeSnapshot &snapshot, uint32_t packets_received)
Heartbeat, emitted every RuntimeConfig::publish_interval_ms milliseconds.
Definition
runtime_events.h:81
espectre
Definition
espectre_sdk_version.h:62
runtime_snapshot.h
espectre::RuntimeSnapshot
A consistent view of the sensing state at one instant.
Definition
runtime_snapshot.h:76
src
cpp
runtime
runtime_events.h
Generated by
1.17.0