{"id":31588581,"url":"https://github.com/esptoolkit/esp-worker","last_synced_at":"2026-02-26T15:03:02.260Z","repository":{"id":315077841,"uuid":"1057788219","full_name":"ESPToolKit/esp-worker","owner":"ESPToolKit","description":"High-level task management for FreeRTOS so you can spawn work units, extend stacks into PSRAM and await completion with joins.","archived":false,"fork":false,"pushed_at":"2026-02-20T22:00:33.000Z","size":69,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-21T03:57:09.311Z","etag":null,"topics":["async","embedded","esp32","iot","process","task","thread","worker"],"latest_commit_sha":null,"homepage":"https://www.esptoolkit.hu/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ESPToolKit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-16T07:57:35.000Z","updated_at":"2026-02-20T22:00:38.000Z","dependencies_parsed_at":"2026-02-21T00:02:10.103Z","dependency_job_id":null,"html_url":"https://github.com/ESPToolKit/esp-worker","commit_stats":null,"previous_names":["esptoolkit/esp-worker"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ESPToolKit/esp-worker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ESPToolKit%2Fesp-worker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ESPToolKit%2Fesp-worker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ESPToolKit%2Fesp-worker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ESPToolKit%2Fesp-worker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ESPToolKit","download_url":"https://codeload.github.com/ESPToolKit/esp-worker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ESPToolKit%2Fesp-worker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29862471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T08:51:08.701Z","status":"ssl_error","status_checked_at":"2026-02-26T08:50:19.607Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","embedded","esp32","iot","process","task","thread","worker"],"created_at":"2025-10-06T02:11:00.171Z","updated_at":"2026-02-26T15:03:02.255Z","avatar_url":"https://github.com/ESPToolKit.png","language":"C++","funding_links":["https://ko-fi.com/esptoolkit"],"categories":[],"sub_categories":[],"readme":"# ESPWorker\n\nESPWorker is a C++17 helper library for ESP32 projects that want FreeRTOS power without the boilerplate. It wraps task creation, joins, diagnostics, PSRAM stacks, and lifecycle events into a simple API that works with both Arduino-ESP32 and ESP-IDF.\n\n## CI / Release / License\n[![CI](https://github.com/ESPToolKit/esp-worker/actions/workflows/ci.yml/badge.svg)](https://github.com/ESPToolKit/esp-worker/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/ESPToolKit/esp-worker?sort=semver)](https://github.com/ESPToolKit/esp-worker/releases)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE.md)\n\n## Features\n- Works with FreeRTOS tasks while keeping `std::function`/lambda ergonomics.\n- Joinable workers with runtime diagnostics (`JobDiag`) and cooperative destruction.\n- Pull worker-pool metrics (`WorkerDiag`) including counts and runtime stats.\n- Optional PSRAM stacks (`spawnExt`) for memory hungry jobs.\n- Thread-safe event and error callbacks so firmware can log or react centrally.\n- Configurable defaults and guardrails (max workers, priorities, affinities).\n\n## Examples\nQuick start:\n\n```cpp\n#include \u003cESPWorker.h\u003e\n\nESPWorker worker;\n\nvoid setup() {\n    Serial.begin(115200);\n\n    worker.init({\n        .maxWorkers = 4,\n        .stackSizeBytes = 4096,\n        .priority = 1,\n        .coreId = tskNO_AFFINITY,\n        .enableExternalStacks = true,\n    });\n\n    worker.onEvent([](WorkerEvent event) {\n        Serial.printf(\"[worker] %s\\n\", worker.eventToString(event));\n    });\n    worker.onError([](WorkerError error) {\n        Serial.printf(\"[worker][error] %s\\n\", worker.errorToString(error));\n    });\n\n    WorkerResult result = worker.spawn([]() {\n        Serial.println(\"[worker] running\");\n        vTaskDelay(pdMS_TO_TICKS(250));\n    }, {\n        .stackSizeBytes = 16 * 1024,\n        .priority = 3,\n        .name = \"sensor-task\",\n    });\n\n    if (result) {\n        result.handler-\u003ewait(pdMS_TO_TICKS(1000));  // or destroy() for long-lived loops\n    }\n\n    worker.deinit();\n}\n```\n\nNeed deterministic cleanup? Store the handler and call `destroy()` when shutting down:\n\n```cpp\nWorkerResult job = worker.spawn([](){ /* ... */ });\nif (job) {\n    // Stop the task cooperatively\n    job.handler-\u003edestroy();\n}\n```\n\nCheck the runnable examples under `examples/`:\n- `examples/basic_worker` – spawns workers, waits for completion, prints diagnostics.\n- `examples/psram_stack` – uses `spawnExt` to place heavy stacks in PSRAM.\n\n## Gotchas\n- Always call `worker.init()` once before spawning tasks. Each ESPWorker instance controls its own limits.\n- Call `worker.deinit()` during shutdown/reset paths. It is safe before `init()` and safe to call repeatedly.\n- `spawn` creates persistent FreeRTOS tasks; remember to end the lambda (return) or `destroy()` the handler to reclaim slots.\n- Errors such as `MaxWorkersReached`, `TaskCreateFailed`, or `ExternalStackUnsupported` are reported in the returned `WorkerResult` _and_ via the error callback.\n- PSRAM stack requests fail fast with `ExternalStackUnsupported` when caps-based task allocation is unavailable, PSRAM is missing, or external stacks are disabled.\n\n## API Reference\n- `void init(const ESPWorker::Config\u0026 config)` – sets defaults (max workers, default stack-bytes/priority/core, PSRAM allowance).\n- `void deinit()` / `bool isInitialized() const` – explicit teardown and lifecycle state checks; `deinit()` is idempotent and safe pre-init.\n- `WorkerResult spawn(TaskCallback cb, const WorkerConfig\u0026 config = {})` – create a worker. The returned handler provides `wait()` and `destroy()` helpers plus per-job diagnostics.\n- `WorkerResult spawnExt(...)` – identical to `spawn` but forces PSRAM stacks using `xTaskCreatePinnedToCoreWithCaps(...)`.\n- `size_t activeWorkers() const` / `void cleanupFinished()` – query or prune finished tasks.\n- `WorkerDiag getDiag() const` – aggregated counts and runtime stats across the pool.\n- `void onEvent(EventCallback cb)` / `void onError(ErrorCallback cb)` – receive lifecycle signals (`Created → Started → Completed/Destroyed`) and fatal issues.\n- `const char* eventToString(...)` / `errorToString(...)` – convert enums to printable text for logging.\n\n`WorkerConfig` (per job) and `ESPWorker::Config` (global defaults) expose priority, stack size bytes, core affinity, external stack usage, and an optional name that shows up in diagnostics and watchdog dumps.\nStack sizes are expressed in bytes.\n\n## Restrictions\n- Intended for ESP32-class boards where FreeRTOS and PSRAM are available; other architectures are untested.\n- Requires C++17 support (`-std=gnu++17`) and should not be called from ISR context.\n- Each worker consumes RAM proportional to its stack; keep `maxWorkers` and per-job stacks aligned with your heap budget.\n\n## Tests\nA native host test suite is still being assembled. For now rely on the `examples/` sketches (build with PlatformIO or Arduino IDE) to verify integration, and consider adding regression tests when contributing changes.\n\n## License\nESPWorker is released under the [MIT License](LICENSE.md).\n\n## ESPToolKit\n- Check out other libraries: \u003chttps://github.com/orgs/ESPToolKit/repositories\u003e\n- Hang out on Discord: \u003chttps://discord.gg/WG8sSqAy\u003e\n- Support the project: \u003chttps://ko-fi.com/esptoolkit\u003e\n- Visit the website: \u003chttps://www.esptoolkit.hu/\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesptoolkit%2Fesp-worker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesptoolkit%2Fesp-worker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesptoolkit%2Fesp-worker/lists"}