Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ name: Tests

on:
push:
branches:
- main
- feature/observable-callback-coverage
pull_request:
branches:
- main

jobs:
host-tests:
Expand All @@ -15,3 +20,41 @@ jobs:
run: cmake --build build --parallel
- name: Test
run: ctest --test-dir build --output-on-failure

esp32-example:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
repository: Flowduino/ESPressio-Observable
ref: 3.0.1
path: deps/ESPressio-Observable
- name: Install PlatformIO
run: pip install platformio
- name: Create PlatformIO consumer project
shell: bash
run: |
mkdir -p "$RUNNER_TEMP/espressio-command-ci/src" "$RUNNER_TEMP/espressio-command-ci/lib"
rsync -a --exclude='.git' --exclude='deps' --exclude='build' ./ "$RUNNER_TEMP/espressio-command-ci/lib/ESPressio-Command/"
cp -R deps/ESPressio-Observable "$RUNNER_TEMP/espressio-command-ci/lib/ESPressio-Observable"
cat > "$RUNNER_TEMP/espressio-command-ci/platformio.ini" <<'EOF'
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
build_flags =
-std=gnu++17
-frtti
build_unflags =
-std=gnu++11
-fno-rtti
lib_deps =
ESPressio-Command
ESPressio-Observable
EOF
- name: Compile BasicCommand
shell: bash
run: |
cp examples/BasicCommand/BasicCommand.ino "$RUNNER_TEMP/espressio-command-ci/src/main.cpp"
pio run -d "$RUNNER_TEMP/espressio-command-ci"
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.3.0

- Added `ICommandRegistryObserver` and observer registration on `CommandRegistry`.
- Added notifications for root command registration and unregistration, including scoped `CommandRegistrationHandle` lifetime removal.
- Added ESPressio Observable as the registry-observer dependency.
- Added optional ESPressio Event bridge support through ESPressio Event 5.8.0.

## 0.2.0

- Added ownership-safe `CommandRegistrationHandle` for scoped command registration.
Expand Down
66 changes: 55 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ USB CDC, TCP, WebSocket, BLE, HTTP, test harnesses and programmatic callers can
therefore share the same Command tree, parameter definitions, validation and
callbacks without coupling application logic to a transport.

## 0.3.0 Development Update — Observable Callback Coverage

The `feature/observable-callback-coverage` branch targets **ESPressio Command 0.3.0**. The stable/pre-release information below remains the 0.2.0 documentation until 0.3.0 is released.

Command 0.3.0 adds a required dependency on **ESPressio Observable >= 3.0.1 and < 4.0.0** and introduces `ICommandRegistryObserver`. `CommandRegistry` now reports root command registration and successful unregistration, including scoped `CommandRegistrationHandle` cleanup. Command invocation itself deliberately remains on the existing callbacks, middleware, `Before(...)` and `After(...)` hooks rather than being duplicated as Observable traffic.

ESPressio Event remains **optional**. ESPressio Event 5.8.0 provides `CommandRegistryEventBridge`, which converts registry lifecycle observations into asynchronous `CommandRegisteredEvent` and `CommandUnregisteredEvent` instances without making Event a Command dependency.

Development-branch PlatformIO dependencies are:

```ini
lib_deps =
https://github.com/Flowduino/ESPressio-Command.git#feature/observable-callback-coverage
flowduino/ESPressio-Observable@^3.0.1
```

The host tests include dedicated registry-observer lifecycle coverage. See [CHANGELOG.md](CHANGELOG.md) for the complete 0.3.0 change list.

## Latest Stable Version

ESPressio Command is currently **0.2.0 (pre-release)**.
Expand All @@ -23,7 +41,7 @@ family under Arduino-ESP32** as part of the ESPressio Development Platform.

The Command core is deliberately transport-neutral and does not directly depend
on Arduino `Stream`, `Print`, ESPressio Serial, ESPressio Event, a network
stack, or any other ESPressio component library.
stack, or any other ESPressio component library. Beginning with the 0.3.0 development generation it does require ESPressio Observable 3.x for its registry lifecycle surface.

Host-side tests are also provided so that the transport-neutral core can be
validated with a conventional C++17 toolchain.
Expand Down Expand Up @@ -84,12 +102,9 @@ In the dependency chart:

### Required ESPressio dependencies

**None.**
The stable 0.2.0 pre-release has no ESPressio dependency. **The 0.3.0 development branch requires ESPressio Observable >= 3.0.1 and < 4.0.0.**

ESPressio Command is intentionally dependency-free within the ESPressio
ecosystem. Future Serial, Event, networking, Serializable or other integrations
should depend on Command or be provided as opt-in adapters; they must not become
mandatory dependencies of the Command core.
Serial, Event, networking, Serializable and other integrations should depend on Command or be provided as opt-in adapters; they must not become mandatory dependencies of the Command core. Event remains opt-in even though 5.8.0 provides a Command registry Event bridge.

## Namespace

Expand All @@ -110,16 +125,20 @@ The principal public types are:
- `TextCommandParser` — converts textual Command lines into tokens.
- `CommandLine` — incrementally consumes character/buffer input.
- `CommandFactory` — convenient facade for Command registration.
- `CommandRegistrationHandle` — ownership-safe scoped dynamic registration.
- `ICommandRegistryObserver` — 0.3.0 registry lifecycle observer.

## PlatformIO

You can add the published library to a PlatformIO project with:
For the stable/pre-release 0.2.0 generation:

```ini
lib_deps =
flowduino/ESPressio-Command@^0.2.0
```

For 0.3.0, consume ESPressio Observable 3.x as shown in the development update above.

Until a release/tag is published, or when deliberately consuming the latest
integration sources, use:

Expand Down Expand Up @@ -302,6 +321,31 @@ These extension points allow policy, diagnostics and integration behaviour to
be layered around Command execution without coupling those concerns to the
Command callback itself.

## Observable Registry Lifecycle (0.3.0)

Registry topology changes can now be observed without changing command execution semantics:

```cpp
class RegistryObserver final :
public ESPressio::Command::ICommandRegistryObserver {
public:
void OnCommandRegistered(const std::vector<std::string>& path) override {
// Passive diagnostics / discovery refresh.
}

void OnCommandUnregistered(const std::vector<std::string>& path) override {
// Owned registration lifetime ended.
}
};

RegistryObserver observer;
auto observerHandle = commands.RegisterObserver(&observer);
```

New root creation and successful root removal emit notifications. Duplicate registration attempts that do not change the tree do not emit. `CommandRegistrationHandle::Reset()` and handle destruction flow through the same successful-unregistration path.

With ESPressio Event 5.8.0 selected, `CommandRegistryEventBridge` can convert these facts into asynchronous Events. Event remains an optional downstream adapter.

## Incremental Text Input

`CommandLine` accepts characters or buffers and submits complete lines to a
Expand Down Expand Up @@ -386,7 +430,7 @@ rules:
5. **Transport and protocol integrations belong outside the core.**
6. **Cross-cutting behaviour should be implemented through middleware or
focused hooks rather than embedded in application callbacks.**
7. **The core remains independently useful and dependency-free.**
7. **The core remains independently useful; from 0.3.0 its only required ESPressio dependency is Observable.**

## Examples

Expand All @@ -404,7 +448,7 @@ Host-side tests are provided beneath [`tests/`](tests/).
They exercise the transport-neutral Command implementation independently of
Arduino hardware. This keeps parsing, resolution, validation and invocation
behaviour testable with a conventional C++17 toolchain while embedded examples
validate intended ESP32 integration usage.
validate intended ESP32 integration usage. The 0.3.0 generation also validates registry-observer registration lifetime and notification semantics.

## Future Integration Direction

Expand All @@ -420,15 +464,15 @@ ESPressio Command is intended to become the common invocation layer for:
- cancellation/progress for asynchronous operations;
- remote Command invocation;
- JSON/Serializable argument adapters; and
- Event bridges for Command completion/result Events.
- Event bridges for Command lifecycle/completion/result Events where those asynchronous representations are justified.

These integrations should remain **opt-in**. The dependency direction is
important:

```text
Serial adapter --------+
Network adapter -------+
Serializable adapter --+--> ESPressio Command
Serializable adapter --+--> ESPressio Command --> ESPressio Observable
Event bridge ----------+
```

Expand Down
4 changes: 2 additions & 2 deletions component.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ COMPONENT_SRCDIRS := src

CXXFLAGS += -DESPRESSIO_COMMAND
CXXFLAGS += -DESPRESSIO_COMMAND_VERSION_MAJOR=0
CXXFLAGS += -DESPRESSIO_COMMAND_VERSION_MINOR=2
CXXFLAGS += -DESPRESSIO_COMMAND_VERSION_MINOR=3
CXXFLAGS += -DESPRESSIO_COMMAND_VERSION_PATCH=0
CXXFLAGS += -DESPRESSIO_COMMAND_VERSION_STRING=\"0.2.0\"
CXXFLAGS += -DESPRESSIO_COMMAND_VERSION_STRING=\"0.3.0\"
CXXFLAGS += -std=gnu++17
13 changes: 10 additions & 3 deletions library.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ESPressio-Command",
"description": "Transport-neutral typed command definition, parsing, routing and invocation framework for ESP32 and C++17",
"keywords": "command,commands,cli,console,parser,router,dispatcher,espressio",
"keywords": "command,commands,cli,console,parser,router,dispatcher,observable,espressio",
"authors": {
"name": "Flowduino",
"maintainer": true,
Expand All @@ -17,8 +17,15 @@
"type": "git",
"url": "https://github.com/Flowduino/ESPressio-Command.git"
},
"version": "0.2.0",
"version": "0.3.0",
"license": "Apache-2.0",
"frameworks": "*",
"platforms": "*"
"platforms": "*",
"dependencies": [
{
"name": "Flowduino ESPressio-Observable",
"version": ">=3.0.1 <4.0.0",
"url": "https://github.com/Flowduino/ESPressio-Observable.git"
}
]
}
5 changes: 3 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name=Flowduino ESPressio-Command
version=0.2.0
version=0.3.0
author=Simon J. Stuart
maintainer=Flowduino.com
sentence=Transport-neutral typed command routing and invocation framework
paragraph=Defines hierarchical commands, typed positional and named parameters, validation, help, completion, middleware and callbacks independently of Serial, TCP, WebSocket or other input transports.
paragraph=Defines hierarchical commands, typed positional and named parameters, validation, help, completion, middleware, callbacks and observable command-registry lifecycle notifications independently of Serial, TCP, WebSocket or other input transports.
category=Other
url=https://github.com/Flowduino/ESPressio-Command
architectures=*
includes=ESPressio_Command.hpp,ESPressio_CommandFactory.hpp,ESPressio_CommandLine.hpp,ESPressio_Commands.hpp
depends=Flowduino ESPressio-Observable (>=3.0.1)
Loading
Loading