diff --git a/.github/workflows/host-tests.yml b/.github/workflows/host-tests.yml index 533a8cb..de55e1b 100644 --- a/.github/workflows/host-tests.yml +++ b/.github/workflows/host-tests.yml @@ -2,7 +2,7 @@ name: Host Tests on: push: - branches: [main] + branches: [main, feature/observable-callback-coverage] pull_request: jobs: @@ -11,15 +11,119 @@ jobs: steps: - name: Checkout Serial uses: actions/checkout@v4 - - name: Checkout ESPressio Command 0.2.0 + - name: Checkout ESPressio Command 0.3.0 uses: actions/checkout@v4 with: repository: Flowduino/ESPressio-Command - ref: 0.2.0 + ref: 0.3.0 path: deps/ESPressio-Command + - name: Checkout ESPressio Observable 3.0.1 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-Observable + ref: 3.0.1 + path: deps/ESPressio-Observable - name: Configure - run: cmake -S tests -B build -DESPRESSIO_COMMAND_INCLUDE_DIR="$GITHUB_WORKSPACE/deps/ESPressio-Command/src" + run: >- + cmake -S tests -B build + -DESPRESSIO_COMMAND_INCLUDE_DIR="$GITHUB_WORKSPACE/deps/ESPressio-Command/src" + -DESPRESSIO_OBSERVABLE_INCLUDE_DIR="$GITHUB_WORKSPACE/deps/ESPressio-Observable/src" - name: Build run: cmake --build build --parallel - name: Test run: ctest --test-dir build --output-on-failure + + esp32-observable-monitors: + runs-on: ubuntu-latest + steps: + - name: Checkout Serial + uses: actions/checkout@v4 + with: + path: project/ESPressio-Serial + - name: Checkout ESPressio Observable 3.0.1 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-Observable + ref: 3.0.1 + path: project/dependencies/ESPressio-Observable + - name: Checkout ESPressio Units 0.2.1 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-Units + ref: 0.2.1 + path: project/dependencies/ESPressio-Units + - name: Checkout ESPressio Timing 2.2.2 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-Timing + ref: 2.2.2 + path: project/dependencies/ESPressio-Timing + - name: Checkout ESPressio Command 0.3.0 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-Command + ref: 0.3.0 + path: project/dependencies/ESPressio-Command + - name: Checkout ESPressio Security 0.2.0 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-Security + ref: 0.2.0 + path: project/dependencies/ESPressio-Security + - name: Checkout ESPressio Sockets 0.5.0 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-Sockets + ref: 0.5.0 + path: project/dependencies/ESPressio-Sockets + - name: Checkout ESPressio ESP-Now 0.5.0 + uses: actions/checkout@v4 + with: + repository: Flowduino/ESPressio-ESP-Now + ref: 0.5.0 + path: project/dependencies/ESPressio-ESP-Now + - uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install PlatformIO + run: pip install platformio + - name: Create monitor compile project + shell: bash + run: | + mkdir -p project/compile/src + cat > project/compile/platformio.ini <<'EOF' + [env:esp32] + platform = espressif32 + board = esp32dev + framework = arduino + build_flags = + -std=gnu++17 + -frtti + -I../dependencies/ESPressio-Command/src + -I../dependencies/ESPressio-Security/src + -I../dependencies/ESPressio-Sockets/src + -I../dependencies/ESPressio-ESP-Now/src + build_unflags = + -std=gnu++11 + -fno-rtti + lib_ldf_mode = deep+ + lib_deps = + ../dependencies/ESPressio-Observable + ../dependencies/ESPressio-Units + ../dependencies/ESPressio-Timing + ../ESPressio-Serial + EOF + cat > project/compile/src/main.cpp <<'EOF' + #include + #include + #include + #include + #include + #include + #include + + void setup() {} + void loop() {} + EOF + - name: Compile ESP32 Observable monitors + run: pio run -d project/compile diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8b563..f0aae0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.5.0 + +- Added opt-in `CommandMonitor` for ESPressio Command 0.3.x registry lifecycle observation. +- Added opt-in `SecurityMonitor` for ESPressio Security 0.2.x configuration, session, replay and failure observation. +- Added opt-in `SocketWorkerMonitor` and `SocketSecuritySessionMonitor` for ESPressio Sockets 0.5.x lifecycle observation. +- Added opt-in `ESPNowTransportMonitor` for ESPressio ESP-Now 0.5.x transport, peer and send lifecycle observation. +- Extended `DiagnosticMonitor` with optional Command and ESP-Now monitoring while preserving its existing default behavior. +- Updated the validated optional ESPressio Event integration baseline to Event 5.8.0 within the 5.x line. +- Preserved Serial's dependency-free core: all new monitors are selected explicitly and observe the originating subsystem rather than duplicating its lifecycle semantics. + ## 0.4.0 - Added optional ESPressio Command 0.2.x integration through `CommandConsole`. diff --git a/ESPRESSIO_DEPENDENCY_CHART.md b/ESPRESSIO_DEPENDENCY_CHART.md index c9181e7..df06c04 100644 --- a/ESPRESSIO_DEPENDENCY_CHART.md +++ b/ESPRESSIO_DEPENDENCY_CHART.md @@ -4,7 +4,7 @@ ## Purpose -This document describes the current dependency relationships between ESPressio libraries. +This document describes the current dependency relationships between ESPressio libraries relevant to ESPressio Serial 0.5.0. The chart is hierarchical: libraries with no **required** ESPressio dependencies appear at the top, while libraries that build on progressively more of the ecosystem appear lower. @@ -12,80 +12,114 @@ The chart is hierarchical: libraries with no **required** ESPressio dependencies - **Dashed arrow** — opt-in dependency activated only by the associated feature/header. - Arrows point from the dependent library to the library it consumes. -## ESPressio Serial 0.4.0 +## ESPressio Serial 0.5.0 The ESPressio Serial core and generic `Console` have no required ESPressio dependency. All integrations remain opt-in. -### CommandConsole +### CommandConsole and CommandMonitor -`CommandConsole` consumes: +`CommandConsole` and `CommandMonitor` consume: ```text -ESPressio Command >= 0.2.0 < 1.0.0 +ESPressio Command >= 0.3.0 < 1.0.0 ``` -Command supplies the transport-neutral typed Command registry, parsing, validation, invocation, help/completion metadata, and ownership-safe scoped command registration used by dynamic Serial integrations. +Command supplies the transport-neutral typed Command registry, parsing, validation, invocation, help/completion metadata, scoped command registration, and Observable registry lifecycle used by Serial's Command integrations. -### EventMonitor +### SecurityMonitor -`EventMonitor` consumes: +`SecurityMonitor` consumes: ```text -ESPressio Event >= 5.7.1 < 6.0.0 -ESPressio Serializable >= 0.10.0 < 1.0.0 +ESPressio Security >= 0.2.0 < 1.0.0 ``` -Event supplies the Event Transport Transaction Observation stream. +Security supplies the Observable configuration, secure-session, replay-protection, and failure lifecycle observed directly by the monitor. -Serializable supplies structured payload decoding used for human-readable diagnostic output. +### Socket monitors -### Timing and Threads monitors +`SocketWorkerMonitor` consumes: -`SystemClockMonitor` optionally consumes: +```text +ESPressio Sockets >= 0.5.0 < 1.0.0 +``` + +`SocketSecuritySessionMonitor` consumes: ```text -ESPressio Timing >= 2.2.2 < 3.0.0 +ESPressio Sockets >= 0.5.0 < 1.0.0 +ESPressio Security >= 0.2.0 < 1.0.0 ``` -`ThreadMonitor` optionally consumes: +Sockets supplies the Observable socket worker and secure-session lifecycle contracts. Security is only relevant to the secure-session integration. + +### ESPNowTransportMonitor + +`ESPNowTransportMonitor` consumes: ```text -ESPressio Threads >= 3.1.2 < 4.0.0 +ESPressio ESP-Now >= 0.5.0 < 1.0.0 ``` -## ESPressio Serial Event Console +ESP-Now supplies the Observable transport, peer, and send lifecycle contract. -The legacy EventConsole initialization path remains supported for compatibility. +### EventMonitor and EventConsole -The recommended Serial 0.4.0 Command-backed EventConsole integration consumes: +`EventMonitor` consumes: ```text -ESPressio Command >= 0.2.0 < 1.0.0 -ESPressio Event >= 5.7.1 < 6.0.0 +ESPressio Event >= 5.8.0 < 6.0.0 ESPressio Serializable >= 0.10.0 < 1.0.0 ``` -Command supplies the shared `event`/`events` command tree and scoped registration lifetime. +Event supplies the Event Transport Transaction Observation stream. Serializable supplies structured payload decoding used for human-readable diagnostic output. -Event supplies runtime Serializable Event discovery, descriptors, construction and dispatch. +The legacy EventConsole initialization path remains supported for compatibility. The recommended Command-backed EventConsole integration consumes: -Serializable supplies `JsonArchive` and validation diagnostics. +```text +ESPressio Command >= 0.3.0 < 1.0.0 +ESPressio Event >= 5.8.0 < 6.0.0 +ESPressio Serializable >= 0.10.0 < 1.0.0 +``` + +Command supplies the shared `event`/`events` command tree and scoped registration lifetime. Event supplies runtime Serializable Event discovery, descriptors, construction and dispatch. Serializable supplies `JsonArchive` and validation diagnostics. The external ArduinoJson dependency is required only by the optional Serializable `JsonArchive`; it is outside this ESPressio-to-ESPressio dependency chart. -Applications using only the core ESPressio Serial layer acquire none of these optional ESPressio dependencies. +### Timing and Threads monitors + +`SystemClockMonitor` optionally consumes: + +```text +ESPressio Timing >= 2.2.2 < 3.0.0 +``` + +`ThreadMonitor` optionally consumes: -## Other current relationships +```text +ESPressio Threads >= 3.1.2 < 4.0.0 +``` + +### Event bridges versus Serial monitors + +The 0.5.0 Observable monitors subscribe directly to the originating subsystem. They do not require ESPressio Event. + +ESPressio Event 5.8.0 separately supplies optional Event bridges for Command, Security, Sockets, and ESP-Now when asynchronous Event conversion is desired. Serial diagnostics therefore remain usable without introducing Event as an intermediary. + +## Current ecosystem relationships - Observable 3.0.1 has no mandatory ESPressio dependencies. - Serializable 0.10.0 has no mandatory ESPressio dependencies. - Units 0.2.1 optionally consumes Serializable for Serializable Unit counterparts. - Timing 2.2.2 requires Units and Observable. - Threads 3.1.2 requires Timing and Observable. -- Event 5.7.1 requires Threads, Timing, and Observable; Serializable functionality remains opt-in. -- ESP-Now 0.2.3 requires Timing and optionally Event for ESP-NOW Event Transport. -- Sockets 0.2.3 has no mandatory ESPressio dependency but optionally consumes Event and Timing. -- Command 0.2.0 has no mandatory ESPressio dependencies. -- Serial 0.4.0 has no mandatory ESPressio dependencies; Command/Event/Serializable/Timing/Threads integrations are opt-in. +- Security 0.2.0 requires Observable; Event conversion is opt-in downstream through Event 5.8.0. +- Command 0.3.0 requires Observable; Event conversion is opt-in downstream through Event 5.8.0. +- Sockets 0.5.0 consumes Observable for lifecycle observation and optionally integrates Command and Security. +- ESP-Now 0.5.0 requires Timing and Observable and optionally integrates Command, Security, and Event transport functionality. +- Event 5.8.0 requires Threads, Timing, and Observable and optionally bridges Security, Command, Sockets, and ESP-Now observer contracts. +- Serial 0.5.0 has no mandatory ESPressio dependencies; Command, Security, Sockets, ESP-Now, Event, Serializable, Timing, and Threads integrations are all opt-in. + +Applications using only the core ESPressio Serial layer acquire none of these optional ESPressio dependencies. diff --git a/README.md b/README.md index baf374e..f848349 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,36 @@ Version 0.3.0 adds a reusable Stream/Print command console and an opt-in operato The latest stable version is **0.4.0**. +## Current Development Version — 0.5.0 + +The `feature/observable-callback-coverage` branch targets **0.5.0** and extends Serial's diagnostics layer to consume the new Observable lifecycle contracts provided by ESPressio Command, Security, Sockets, and ESP-Now. + +Core ESPressio Serial remains free of mandatory ESPressio-library dependencies. The new monitors are selected only when their corresponding upstream headers are available: + +```text +CommandMonitor + - - -> ESPressio Command >= 0.3.0 < 1.0.0 + +SecurityMonitor + - - -> ESPressio Security >= 0.2.0 < 1.0.0 + +SocketWorkerMonitor + - - -> ESPressio Sockets >= 0.5.0 < 1.0.0 + +SocketSecuritySessionMonitor + - - -> ESPressio Sockets >= 0.5.0 < 1.0.0 + - - -> ESPressio Security >= 0.2.0 < 1.0.0 + +ESPNowTransportMonitor + - - -> ESPressio ESP-Now >= 0.5.0 < 1.0.0 +``` + +`DiagnosticMonitor` can additionally compose `CommandMonitor` and `ESPNowTransportMonitor` when those dependencies are present. Security and Socket monitors remain instance-oriented because the application must choose the specific `TransportSecurity`, `SocketWorker`, or `SocketSecuritySession` object to observe. + +These monitors subscribe directly to the originating library's Observable contract. They do not invent parallel Serial lifecycle semantics and do not require ESPressio Event. Event-backed observation remains a separate opt-in integration in ESPressio Event 5.8.0. + +The complete historical/stable documentation below remains intact. + ## ESPressio Development Platform ESPressio is a collection of discrete, composable component libraries designed around a common development ethos: @@ -53,6 +83,8 @@ ESPressio Event >= 5.7.1 < 6.0.0 ESPressio Serializable >= 0.10.0 < 1.0.0 ``` +For the 0.5.0 development branch, the additional opt-in monitoring dependencies are listed in the development-version section above. Existing Event Monitor/EventConsole guidance below remains the stable 0.4.0 baseline unless explicitly identified otherwise. + For the complete ecosystem hierarchy, see: **[ESPressio Library Dependency Chart](ESPRESSIO_DEPENDENCY_CHART.md)** @@ -625,6 +657,8 @@ void setup() { The aggregate uses compile-time feature detection. It does not itself make Timing, Threads, Event, or Serializable mandatory package dependencies. +In the 0.5.0 development branch, `DiagnosticMonitorConfig` additionally supports `Commands` and `ESPNow`. These remain disabled by default and are available only when the corresponding optional upstream headers are present. + ## Dependency model ```text @@ -645,7 +679,7 @@ EventMonitor - - -> ESPressio Serializable >= 0.10.0 < 1.0.0 ``` -All ESPressio relationships remain opt-in. +All ESPressio relationships remain opt-in. The 0.5.0 development observer monitors add the additional optional relationships documented near the top of this README. --- diff --git a/component.mk b/component.mk index 3c836fc..02b1fdc 100644 --- a/component.mk +++ b/component.mk @@ -1,11 +1,15 @@ COMPONENT_ADD_INCLUDEDIRS := \ src \ src/console \ + src/command \ src/command-console \ src/diagnostics \ + src/espnow \ src/event \ src/event-console \ src/logging \ + src/security \ + src/sockets \ src/threads \ src/timing @@ -16,6 +20,6 @@ CXXFLAGS += -std=gnu++17 CPPFLAGS += \ -DESPRESSIO_SERIAL \ -DESPRESSIO_SERIAL_VERSION_MAJOR=0 \ - -DESPRESSIO_SERIAL_VERSION_MINOR=4 \ + -DESPRESSIO_SERIAL_VERSION_MINOR=5 \ -DESPRESSIO_SERIAL_VERSION_PATCH=0 \ - -DESPRESSIO_SERIAL_VERSION_STRING=\"0.4.0\" + -DESPRESSIO_SERIAL_VERSION_STRING=\"0.5.0\" diff --git a/library.json b/library.json index 10db741..bea5822 100644 --- a/library.json +++ b/library.json @@ -1,7 +1,7 @@ { "name": "ESPressio-Serial", - "description": "Serial and console-oriented components for ESPressio, including opt-in ESPressio Command and Event integrations.", - "keywords": "esp32,serial,console,monitor,event,transport,diagnostics,espressio", + "description": "Serial and console-oriented components for ESPressio, including opt-in Observable, Command and Event integrations.", + "keywords": "esp32,serial,console,monitor,event,transport,diagnostics,observable,espressio", "authors": { "name": "Flowduino", "maintainer": true, @@ -16,7 +16,7 @@ "type": "git", "url": "https://github.com/Flowduino/ESPressio-Serial.git" }, - "version": "0.4.0", + "version": "0.5.0", "license": "Apache-2.0", "frameworks": "arduino", "platforms": "espressif32" diff --git a/library.properties b/library.properties index a531a00..c1af497 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=ESPressio-Serial -version=0.4.0 +version=0.5.0 author=Flowduino maintainer=Flowduino sentence=Serial console, diagnostics, logging and operator tooling for the ESPressio ecosystem. -paragraph=Provides structured logging, diagnostics monitors, an extensible Stream/Print console, opt-in ESPressio Command integration, and opt-in runtime JSON composition and dispatch of registered Serializable ESPressio Events. +paragraph=Provides structured logging, diagnostics monitors, an extensible Stream/Print console, opt-in observable monitors for Command, Security, Sockets and ESP-Now, opt-in ESPressio Command integration, and opt-in runtime JSON composition and dispatch of registered Serializable ESPressio Events. category=Communication url=https://github.com/Flowduino/ESPressio-Serial architectures=esp32 diff --git a/src/ESPressio_CommandMonitor.hpp b/src/ESPressio_CommandMonitor.hpp new file mode 100644 index 0000000..a3d8b95 --- /dev/null +++ b/src/ESPressio_CommandMonitor.hpp @@ -0,0 +1,2 @@ +#pragma once +#include "command/ESPressio_CommandMonitor.hpp" diff --git a/src/ESPressio_ESPNowTransportMonitor.hpp b/src/ESPressio_ESPNowTransportMonitor.hpp new file mode 100644 index 0000000..efacabd --- /dev/null +++ b/src/ESPressio_ESPNowTransportMonitor.hpp @@ -0,0 +1,2 @@ +#pragma once +#include "espnow/ESPressio_ESPNowTransportMonitor.hpp" diff --git a/src/ESPressio_SecurityMonitor.hpp b/src/ESPressio_SecurityMonitor.hpp new file mode 100644 index 0000000..6857f22 --- /dev/null +++ b/src/ESPressio_SecurityMonitor.hpp @@ -0,0 +1,2 @@ +#pragma once +#include "security/ESPressio_SecurityMonitor.hpp" diff --git a/src/ESPressio_Serial.hpp b/src/ESPressio_Serial.hpp index bed8927..72cb2d2 100644 --- a/src/ESPressio_Serial.hpp +++ b/src/ESPressio_Serial.hpp @@ -3,4 +3,25 @@ #include "ESPressio_SerialTypes.hpp" #include "ESPressio_DiagnosticTypes.hpp" -/* Optional facilities are selected explicitly through ESPressio_Logging.hpp, ESPressio_SystemClockMonitor.hpp, ESPressio_ThreadMonitor.hpp, ESPressio_EventMonitor.hpp, or ESPressio_DiagnosticMonitor.hpp, ESPressio_CommandConsole.hpp, or ESPressio_EventConsole.hpp. */ +/* + * Optional facilities are selected explicitly. Core Serial remains free of + * mandatory ESPressio-library dependencies. + * + * Logging / diagnostics: + * ESPressio_Logging.hpp + * ESPressio_SystemClockMonitor.hpp + * ESPressio_ThreadMonitor.hpp + * ESPressio_EventMonitor.hpp + * ESPressio_DiagnosticMonitor.hpp + * + * Observable subsystem monitors: + * ESPressio_CommandMonitor.hpp -> Command >= 0.3.0 < 1.0.0 + * ESPressio_SecurityMonitor.hpp -> Security >= 0.2.0 < 1.0.0 + * ESPressio_SocketWorkerMonitor.hpp -> Sockets >= 0.5.0 < 1.0.0 + * ESPressio_SocketSecuritySessionMonitor.hpp + * ESPressio_ESPNowTransportMonitor.hpp -> ESP-Now >= 0.5.0 < 1.0.0 + * + * Interactive integrations: + * ESPressio_CommandConsole.hpp + * ESPressio_EventConsole.hpp + */ diff --git a/src/ESPressio_SocketSecuritySessionMonitor.hpp b/src/ESPressio_SocketSecuritySessionMonitor.hpp new file mode 100644 index 0000000..3a5caa7 --- /dev/null +++ b/src/ESPressio_SocketSecuritySessionMonitor.hpp @@ -0,0 +1,2 @@ +#pragma once +#include "sockets/ESPressio_SocketSecuritySessionMonitor.hpp" diff --git a/src/ESPressio_SocketWorkerMonitor.hpp b/src/ESPressio_SocketWorkerMonitor.hpp new file mode 100644 index 0000000..d32bfa5 --- /dev/null +++ b/src/ESPressio_SocketWorkerMonitor.hpp @@ -0,0 +1,2 @@ +#pragma once +#include "sockets/ESPressio_SocketWorkerMonitor.hpp" diff --git a/src/command/ESPressio_CommandMonitor.hpp b/src/command/ESPressio_CommandMonitor.hpp new file mode 100644 index 0000000..fdd2cc3 --- /dev/null +++ b/src/command/ESPressio_CommandMonitor.hpp @@ -0,0 +1,56 @@ +#pragma once + +#if !__has_include() +#error "CommandMonitor requires ESPressio Command >= 0.3.0 < 1.0.0." +#endif + +#include +#include +#include + +namespace ESPressio::Serial { + +class CommandMonitor final : + public ESPressio::Command::ICommandRegistryObserver { +private: + Print* _output = nullptr; + ESPressio::Observable::ObserverHandlePtr _handle; + + void Line(const char* operation, const std::vector& path) { + if (!_output) return; + _output->print("[ESPressio Command] "); + _output->print(operation); + if (!path.empty()) { + _output->print(" "); + for (std::size_t i = 0; i < path.size(); ++i) { + if (i) _output->print("/"); + _output->print(path[i].c_str()); + } + } + _output->println(); + } + +public: + bool Initialize(Print& output, ESPressio::Command::CommandRegistry& registry = ESPressio::Command::CommandRegistry::GetInstance()) { + if (_handle) return true; + _output = &output; + _handle = registry.RegisterObserver(this); + if (!_handle) { _output = nullptr; return false; } + return true; + } + + void Shutdown() { + _handle.reset(); + _output = nullptr; + } + + void OnCommandRegistered(const std::vector& path) override { + Line("Registered", path); + } + + void OnCommandUnregistered(const std::vector& path) override { + Line("Unregistered", path); + } +}; + +} // namespace ESPressio::Serial diff --git a/src/diagnostics/ESPressio_DiagnosticMonitor.hpp b/src/diagnostics/ESPressio_DiagnosticMonitor.hpp index 223fbe1..eb74a0d 100644 --- a/src/diagnostics/ESPressio_DiagnosticMonitor.hpp +++ b/src/diagnostics/ESPressio_DiagnosticMonitor.hpp @@ -16,12 +16,24 @@ #define ESPRESSIO_SERIAL_HAS_EVENT_MONITOR 1 #endif +#if __has_include() && __has_include() +#include "../command/ESPressio_CommandMonitor.hpp" +#define ESPRESSIO_SERIAL_HAS_COMMAND_MONITOR 1 +#endif + +#if __has_include() && __has_include() +#include "../espnow/ESPressio_ESPNowTransportMonitor.hpp" +#define ESPRESSIO_SERIAL_HAS_ESPNOW_MONITOR 1 +#endif + namespace ESPressio::Serial { struct DiagnosticMonitorConfig { bool SystemClock = true; bool Threads = true; bool Events = true; + bool Commands = false; + bool ESPNow = false; }; class DiagnosticMonitor final { @@ -34,6 +46,12 @@ class DiagnosticMonitor final { #ifdef ESPRESSIO_SERIAL_HAS_EVENT_MONITOR EventMonitor _events; #endif +#ifdef ESPRESSIO_SERIAL_HAS_COMMAND_MONITOR + CommandMonitor _commands; +#endif +#ifdef ESPRESSIO_SERIAL_HAS_ESPNOW_MONITOR + ESPNowTransportMonitor _espNow; +#endif public: bool Initialize(Print& output, const DiagnosticMonitorConfig& config = {}) { bool success = true; @@ -51,11 +69,27 @@ class DiagnosticMonitor final { if (config.Events) success = _events.Initialize(output) && success; #else if (config.Events) success = false; +#endif +#ifdef ESPRESSIO_SERIAL_HAS_COMMAND_MONITOR + if (config.Commands) success = _commands.Initialize(output) && success; +#else + if (config.Commands) success = false; +#endif +#ifdef ESPRESSIO_SERIAL_HAS_ESPNOW_MONITOR + if (config.ESPNow) success = _espNow.Initialize(output) && success; +#else + if (config.ESPNow) success = false; #endif return success; } void Shutdown() { +#ifdef ESPRESSIO_SERIAL_HAS_ESPNOW_MONITOR + _espNow.Shutdown(); +#endif +#ifdef ESPRESSIO_SERIAL_HAS_COMMAND_MONITOR + _commands.Shutdown(); +#endif #ifdef ESPRESSIO_SERIAL_HAS_EVENT_MONITOR _events.Shutdown(); #endif diff --git a/src/espnow/ESPressio_ESPNowTransportMonitor.hpp b/src/espnow/ESPressio_ESPNowTransportMonitor.hpp new file mode 100644 index 0000000..98f3403 --- /dev/null +++ b/src/espnow/ESPressio_ESPNowTransportMonitor.hpp @@ -0,0 +1,51 @@ +#pragma once + +#if !__has_include() +#error "ESPNowTransportMonitor requires ESPressio ESP-Now >= 0.5.0 < 1.0.0." +#endif + +#include +#include +#include + +namespace ESPressio::Serial { + +class ESPNowTransportMonitor final : + public ESPressio::ESPNow::IESPNowTransportObserver { +private: + Print* _output = nullptr; + ESPressio::Observable::ObserverHandlePtr _handle; + + void Line(const char* operation) { + if (!_output) return; + _output->print("[ESPressio ESP-Now] "); + _output->println(operation); + } + +public: + bool Initialize( + Print& output, + ESPressio::ESPNow::ESPNowTransport& transport = ESPressio::ESPNow::ESPNowTransport::GetInstance() + ) { + if (_handle) return true; + _output = &output; + _handle = transport.RegisterObserver(this); + if (!_handle) { _output = nullptr; return false; } + return true; + } + + void Shutdown() { + _handle.reset(); + _output = nullptr; + } + + void OnESPNowTransportInitialized() override { Line("Initialized"); } + void OnESPNowTransportInitializationFailed() override { Line("InitializationFailed"); } + void OnESPNowTransportShutdown() override { Line("Shutdown"); } + void OnESPNowPeerAdded(const ESPressio::ESPNow::MacAddress&) override { Line("PeerAdded"); } + void OnESPNowPeerRemoved(const ESPressio::ESPNow::MacAddress&) override { Line("PeerRemoved"); } + void OnESPNowSendAccepted(const ESPressio::ESPNow::MacAddress&, uint8_t, std::size_t) override { Line("SendAccepted"); } + void OnESPNowSendFailed(const ESPressio::ESPNow::MacAddress&, uint8_t, std::size_t) override { Line("SendFailed"); } +}; + +} // namespace ESPressio::Serial diff --git a/src/security/ESPressio_SecurityMonitor.hpp b/src/security/ESPressio_SecurityMonitor.hpp new file mode 100644 index 0000000..611b54f --- /dev/null +++ b/src/security/ESPressio_SecurityMonitor.hpp @@ -0,0 +1,72 @@ +#pragma once + +#if !__has_include() +#error "SecurityMonitor requires ESPressio Security >= 0.2.0 < 1.0.0." +#endif + +#include +#include +#include + +namespace ESPressio::Serial { + +class SecurityMonitor final : + public ESPressio::Security::ITransportSecurityObserver { +private: + Print* _output = nullptr; + ESPressio::Observable::ObserverHandlePtr _handle; + + void Line(const char* operation) { + if (!_output) return; + _output->print("[ESPressio Security] "); + _output->println(operation); + } + +public: + bool Initialize(Print& output, ESPressio::Security::TransportSecurity& security) { + if (_handle) return true; + _output = &output; + _handle = security.RegisterObserver(this); + if (!_handle) { _output = nullptr; return false; } + return true; + } + + void Shutdown() { + _handle.reset(); + _output = nullptr; + } + + void OnTransportSecurityConfigurationChanged( + const ESPressio::Security::TransportSecurityConfig&, + const ESPressio::Security::TransportSecurityConfig& + ) override { Line("ConfigurationChanged"); } + + void OnTransportSecuritySessionReset(uint64_t previousSessionID) override { + if (!_output) return; + _output->print("[ESPressio Security] SessionReset previous="); + _output->println(static_cast(previousSessionID)); + } + + void OnTransportSecuritySessionEstablished(uint64_t sessionID) override { + if (!_output) return; + _output->print("[ESPressio Security] SessionEstablished id="); + _output->println(static_cast(sessionID)); + } + + void OnTransportSecurityReplayProtectionReset() override { + Line("ReplayProtectionReset"); + } + + void OnTransportSecurityFailure(const ESPressio::Security::SecurityResult& result) override { + if (!_output) return; + _output->print("[ESPressio Security] Failure error="); + _output->print(static_cast(result.Error)); + if (!result.Message.empty()) { + _output->print(" message="); + _output->print(result.Message.c_str()); + } + _output->println(); + } +}; + +} // namespace ESPressio::Serial diff --git a/src/sockets/ESPressio_SocketSecuritySessionMonitor.hpp b/src/sockets/ESPressio_SocketSecuritySessionMonitor.hpp new file mode 100644 index 0000000..2d31a24 --- /dev/null +++ b/src/sockets/ESPressio_SocketSecuritySessionMonitor.hpp @@ -0,0 +1,50 @@ +#pragma once + +#if !__has_include() +#error "SocketSecuritySessionMonitor requires ESPressio Sockets >= 0.5.0 < 1.0.0 and ESPressio Security >= 0.2.0 < 1.0.0." +#endif + +#include +#include +#include + +namespace ESPressio::Serial { + +class SocketSecuritySessionMonitor final : + public ESPressio::Sockets::ISocketSecuritySessionObserver { +private: + Print* _output = nullptr; + ESPressio::Observable::ObserverHandlePtr _handle; + +public: + bool Initialize(Print& output, ESPressio::Sockets::SocketSecuritySession& session) { + if (_handle) return true; + _output = &output; + _handle = session.RegisterObserver(this); + if (!_handle) { _output = nullptr; return false; } + return true; + } + + void Shutdown() { + _handle.reset(); + _output = nullptr; + } + + void OnSocketSecuritySessionFaulted(const ESPressio::Security::SecurityResult& result) override { + if (!_output) return; + _output->print("[ESPressio Sockets] [SecuritySession] Faulted error="); + _output->print(static_cast(result.Error)); + if (!result.Message.empty()) { + _output->print(" message="); + _output->print(result.Message.c_str()); + } + _output->println(); + } + + void OnSocketSecuritySessionReset() override { + if (!_output) return; + _output->println("[ESPressio Sockets] [SecuritySession] Reset"); + } +}; + +} // namespace ESPressio::Serial diff --git a/src/sockets/ESPressio_SocketWorkerMonitor.hpp b/src/sockets/ESPressio_SocketWorkerMonitor.hpp new file mode 100644 index 0000000..eb8f91f --- /dev/null +++ b/src/sockets/ESPressio_SocketWorkerMonitor.hpp @@ -0,0 +1,49 @@ +#pragma once + +#if !__has_include() +#error "SocketWorkerMonitor requires ESPressio Sockets >= 0.5.0 < 1.0.0." +#endif + +#include +#include +#include + +namespace ESPressio::Serial { + +class SocketWorkerMonitor final : + public ESPressio::Sockets::ISocketWorkerObserver { +private: + Print* _output = nullptr; + ESPressio::Observable::ObserverHandlePtr _handle; + + void Line(const char* operation, const char* name = nullptr) { + if (!_output) return; + _output->print("[ESPressio Sockets] [Worker] "); + _output->print(operation); + if (name != nullptr) { + _output->print(" name="); + _output->print(name); + } + _output->println(); + } + +public: + bool Initialize(Print& output, ESPressio::Sockets::SocketWorker& worker) { + if (_handle) return true; + _output = &output; + _handle = worker.RegisterObserver(this); + if (!_handle) { _output = nullptr; return false; } + return true; + } + + void Shutdown() { + _handle.reset(); + _output = nullptr; + } + + void OnSocketWorkerStarted(const char* name) override { Line("Started", name); } + void OnSocketWorkerStartFailed(const char* name) override { Line("StartFailed", name); } + void OnSocketWorkerStopped() override { Line("Stopped"); } +}; + +} // namespace ESPressio::Serial diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fb5ec3f..29beb05 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,6 +4,7 @@ project(ESPressioSerialTests LANGUAGES CXX) enable_testing() set(ESPRESSIO_COMMAND_INCLUDE_DIR "" CACHE PATH "Path containing ESPressio_Command.hpp") +set(ESPRESSIO_OBSERVABLE_INCLUDE_DIR "" CACHE PATH "Path containing ESPressio_Observable.hpp") add_executable( test_console @@ -22,7 +23,7 @@ add_executable( target_compile_features(test_event_console PRIVATE cxx_std_17) target_compile_options(test_event_console PRIVATE -Wall -Wextra -Wpedantic -Werror) -target_include_directories(test_event_console PRIVATE stubs ../src ${ESPRESSIO_COMMAND_INCLUDE_DIR}) +target_include_directories(test_event_console PRIVATE stubs ../src ${ESPRESSIO_COMMAND_INCLUDE_DIR} ${ESPRESSIO_OBSERVABLE_INCLUDE_DIR}) add_test(NAME EventConsoleContract COMMAND test_event_console) add_executable( @@ -32,5 +33,5 @@ add_executable( target_compile_features(test_command_console PRIVATE cxx_std_17) target_compile_options(test_command_console PRIVATE -Wall -Wextra -Wpedantic -Werror) -target_include_directories(test_command_console PRIVATE stubs ../src ${ESPRESSIO_COMMAND_INCLUDE_DIR}) +target_include_directories(test_command_console PRIVATE stubs ../src ${ESPRESSIO_COMMAND_INCLUDE_DIR} ${ESPRESSIO_OBSERVABLE_INCLUDE_DIR}) add_test(NAME CommandConsoleContract COMMAND test_command_console)