diff --git a/code/espurna/sensor.cpp b/code/espurna/sensor.cpp index 2a5ca470..c5929072 100644 --- a/code/espurna/sensor.cpp +++ b/code/espurna/sensor.cpp @@ -1908,6 +1908,32 @@ enum class State { Reading, }; +namespace notifications { +namespace internal { + +std::forward_list callbacks; +std::forward_list timers; + +} // namespace internal +} // namespace notifications + +void notify_after(duration::Milliseconds after, NotifyCallback callback) { + using namespace notifications; + + internal::timers.push_front(timer::SystemTimer()); + + auto& instance = internal::timers.front(); + instance.schedule_once( + after, + [callback]() { + internal::callbacks.push_front(callback); + }); +} + +void notify_now(NotifyCallback callback) { + notifications::internal::callbacks.push_front(callback); +} + namespace internal { std::vector sensors; @@ -3864,6 +3890,24 @@ bool try_init() { // Magnitude processing // ----------------------------------------------------------------------------- +void notify() { + decltype(notifications::internal::callbacks) callbacks; + std::swap(callbacks, notifications::internal::callbacks); + + for (auto sensor : internal::sensors) { + for (auto& callback : callbacks) { + if (callback(sensor.get())) { + sensor->notify(); + } + } + } + + notifications::internal::timers.remove_if( + [](const timer::SystemTimer& timer) { + return !static_cast(timer); + }); +} + void tick() { for (auto sensor : internal::sensors) { sensor->tick(); @@ -3941,6 +3985,9 @@ void loop() { return; } + // Notify hook, called when requested by sensor + sensor::notify(); + // Tick hook, called every loop() sensor::tick(); diff --git a/code/espurna/sensor.h b/code/espurna/sensor.h index d1f7f666..0d5f3f56 100644 --- a/code/espurna/sensor.h +++ b/code/espurna/sensor.h @@ -20,6 +20,8 @@ Copyright (C) 2020 by Maxim Prokhorov #include "system.h" +class BaseSensor; + namespace espurna { namespace sensor { @@ -238,6 +240,11 @@ struct Info { String description; }; +using NotifyCallback = bool (*)(const BaseSensor*); + +void notify_after(duration::Milliseconds, NotifyCallback); +void notify_now(NotifyCallback); + } // namespace sensor } // namespace espurna diff --git a/code/espurna/sensors/BaseSensor.h b/code/espurna/sensors/BaseSensor.h index e4002845..2f4d337a 100644 --- a/code/espurna/sensors/BaseSensor.h +++ b/code/espurna/sensors/BaseSensor.h @@ -144,6 +144,10 @@ public: virtual void resume() { } + // Custom hook (usually to update sensor state outside of normal methods) + virtual void notify() { + } + // Loop-like method, call it in your main loop virtual void tick() { }