adhuldas/edgecommand

0.1.1

Latest
uploaded 5 hours ago
Reliable command execution for IoT devices: persistent state, deduplication, execution tracking, timeout handling, cooperative cancellation, and restart recovery. Transport-independent (works with MQTT, HTTP, BLE, serial, or any custom protocol).

Readme

# EdgeCommand

Reliable command execution for IoT devices, for ESP-IDF.

EdgeCommand is a transport-independent framework for receiving, deduplicating,
persisting, queueing, executing, and reporting on inbound commands. It has no
dependency on MQTT, HTTP, BLE, or any cloud provider — your application is
responsible for receiving bytes over whatever transport it uses and calling
`edgecommand_submit()`.

## Features

- **Persistent state** — command records survive a restart (NVS-backed by default).
- **Deduplication** — resubmitting the same command ID is rejected, not re-run.
- **Execution tracking** — a documented state machine (`RECEIVED` → `PERSISTED` →
  `PENDING` → `EXECUTING` → terminal state) with progress reporting.
- **Timeout handling** — commands that exceed their timeout end in `TIMED_OUT`,
  not silently hang.
- **Cooperative cancellation** — `edgecommand_cancel()` plus
  `edgecommand_is_cancelled()` for long-running handlers to poll.
- **Restart recovery** — configurable policy for commands left `EXECUTING` or
  `PENDING` by an interrupted process (e.g. power loss).
- **Transport-independent** — works with MQTT, HTTP, BLE, serial, or any
  custom protocol; you own the transport, EdgeCommand owns execution.

## Installation

```
idf.py add-dependency "adhuldas/edgecommand^0.1.0"
```

Or add it to your project's `idf_component.yml`:

```yaml
dependencies:
  adhuldas/edgecommand: "^0.1.0"
```

## Quick start

```c
#include "edgecommand/edgecommand.h"

static esp_err_t ping_handler(const edgecommand_command_t *command, edgecommand_execution_ctx_t *execution,
                               edgecommand_result_t *result, void *user_ctx)
{
    result->status = EDGECOMMAND_RESULT_SUCCESS;
    result->code = 0;
    snprintf(result->message, sizeof(result->message), "pong");
    return ESP_OK;
}

void app_main(void)
{
    /* EdgeCommand's built-in NVS storage backend requires the application to
     * initialize NVS itself, exactly like any other component that uses it. */
    ESP_ERROR_CHECK(nvs_flash_init());

    edgecommand_config_t config = EDGECOMMAND_DEFAULT_CONFIG();

    edgecommand_handle_t engine;
    ESP_ERROR_CHECK(edgecommand_init(&config, &engine));
    ESP_ERROR_CHECK(edgecommand_register_handler(engine, "ping", ping_handler, NULL));
    ESP_ERROR_CHECK(edgecommand_start(engine));

    edgecommand_command_t command = {
        .id = "example-0001",
        .name = "ping",
        .timeout_ms = 5000,
    };
    ESP_ERROR_CHECK(edgecommand_submit(engine, &command));
}
```

Wire a reporter (`edgecommand_set_reporter()`) to publish status changes over
your transport of choice, instead of polling `edgecommand_get_status()`.

## Examples

| Example | Demonstrates |
| --- | --- |
| [`basic`](examples/basic) | Minimal end-to-end usage: register a handler, submit a command, observe its result. |
| [`long_running_command`](examples/long_running_command) | Progress reporting, cooperative timeout, and cooperative cancellation. |
| [`persistent_commands`](examples/persistent_commands) | Command records surviving an engine restart. |
| [`recovery`](examples/recovery) | Restart recovery policies for commands interrupted mid-execution. |

## API overview

- **Lifecycle**: `edgecommand_init`, `edgecommand_start`, `edgecommand_stop`, `edgecommand_deinit`
- **Handlers**: `edgecommand_register_handler`, `edgecommand_unregister_handler`
- **Commands**: `edgecommand_submit`, `edgecommand_cancel`, `edgecommand_get_status`
- **Inside a handler**: `edgecommand_report_progress`, `edgecommand_is_cancelled`
- **Reporting**: `edgecommand_set_reporter`
- **Events**: `edgecommand_register_event_callback`, `edgecommand_unregister_event_callback`

See [`include/edgecommand/edgecommand.h`](include/edgecommand/edgecommand.h) and
the other headers under `include/edgecommand/` for full per-function
documentation.

## Configuration

EdgeCommand is tuned through Kconfig (`idf.py menuconfig` → `Component config`
→ `EdgeCommand`), including max pending commands, worker task stack size, and
event callback support.

## License

Apache-2.0. See [`LICENSE`](LICENSE).

Links

Supports all targets

Maintainer

  • adhuldas <adhulamz@gmail.com>
To add this component to your project, run:

idf.py add-dependency "adhuldas/edgecommand^0.1.1"

download archive

Stats

  • Archive size
    Archive size ~ 65.88 KB
  • Downloaded in total
    Downloaded in total 0 times
  • Downloaded this version
    This version: 0 times

Badge

adhuldas/edgecommand version: 0.1.1
|