Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Phase

Phase is an async application lifecycle orchestration library for ESP32.

Phase helps you boot and shut down larger Arduino ESP32 applications in a predictable order. It is designed for projects with multiple modules that depend on each other and focuses on dependency-ordered lifecycle steps, readiness gates, cooperative pause/resume, rollback, and result-based errors.

CIReleaseLicense: MIT

Why use Phase?

  • Async boot - start() wakes the Phase task and returns immediately.
  • Dependency order - steps and groups declare what must be ready first.
  • Two-layer lifecycle - simple modules use init/deinit, advanced modules add start/stop.
  • Readiness groups - wait for virtual gates such as network link or internet access.
  • Production-minded - thread-safe internals, no exceptions, rollback, diagnostics, and progress callbacks.

Install

PlatformIO

[env:esp32dev]platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/ZekStack/phase.git
build_flags =
-std=gnu++20
build_unflags =
-std=gnu++11

Arduino IDE

Phase is not published to Arduino Library Manager yet.

Install it by downloading the repository ZIP or cloning it into your Arduino libraries folder.

Arduino/libraries/Phase

Quick start

#include<Arduino.h>
#include<Phase.h>
Phase phase;
voidsetup() {
Serial.begin(115200);
PhaseResult initResult = phase.init();
if (!initResult) {
Serial.println(initResult.message);
return;
}
phase.add("storage", []() {
Serial.println("storage init");
});
phase.add("network", []() {
Serial.println("network init");
}).start([]() {
Serial.println("network start");
});
phase.onReady([]() {
Serial.println("app ready");
});
phase.start();
Serial.println("setup continues while Phase boots");
}
voidloop() {
delay(1000);
}

Important notes

Important

Phase callbacks are cooperative. Lifecycle callbacks run inside the Phase task, so a callback that never returns cannot be interrupted by Phase.

  • pause() is async and takes effect before the next lifecycle action or group-condition poll.
  • Callback timeout checks happen after the callback returns.
  • Group condition polling timeouts are enforced by the Phase task.
  • Registration closes after a successful start() request.
  • stop(), pause(), and resume() may be called from Phase callbacks. end() must be called from another task and returns Busy when called from the Phase task.
  • The destructor waits for the Phase task to stop using its internal state. Destruction from a Phase callback is deferred safely until the worker exits.
  • Registration and graph preparation use std::vector, std::string, and std::function. Node storage, dependency indexes, and lifecycle order are preallocated before the worker starts; lifecycle execution does not allocate.
  • PhaseChange string pointers are valid for the complete callback invocation. Event messages and pause reasons are copied into bounded internal snapshots and may be truncated to 191 characters.
  • Stop/deinit failures are best-effort and are reported through onChange() while remaining cleanup continues.
  • Phase does not depend on other ZekStack libraries.

Examples

ExampleDescription
BasicMinimal async boot with init/deinit and ready callback.
DependenciesDependency order, start/stop, and shutdown order.
GroupsVirtual readiness groups with condition polling.
PauseResumePause before boot and resume from loop().
OptionalNodesOptional node failure and skipped dependent behavior.
BindableCallbacksBind private class methods with lambdas.
ManualShutdownRequest reverse stop/deinit from loop().

Start with:

examples/Basic

Documentation

Detailed documentation is available in the docs/ folder.

DocumentDescription
docs/getting-started.mdStep-by-step setup and first lifecycle flow.
docs/configuration.mdTask, timeout, limit, and polling options.
docs/api.mdPublic classes, methods, callbacks, and result types.
docs/examples.mdExplanation of all included examples.
docs/troubleshooting.mdCommon issues and behavior notes.

API overview

Phase phase;
phase.init();
phase.add("storage", initStorage, deinitStorage);
phase.add("network", initNetwork, deinitNetwork).start(startNetwork, stopNetwork);
phase.addGroup("internet").depends("network").condition(hasInternet, 30000);
phase.onReady([]() {});
phase.onFailed([](PhaseResult result) {});
phase.start();

For the full API, see docs/api.md.

Compatibility

ItemSupport
FrameworkArduino ESP32
Platformespressif32
LanguageC++20
Filesystemnone
PSRAMOptional for task stacks when ESP-IDF support is available
Dependenciesnone
ExceptionsNot used
Status0.1.0 release candidate

Configuration

PhaseConfig config;
config.stackSizeBytes = 4096;
config.priority = 1;
config.coreId = tskNO_AFFINITY;
config.stackType = PhaseStackType::Auto;
config.defaultInitTimeoutMs = 30000;
config.conditionPollIntervalMs = 100;
PhaseResult result = phase.init(config);

For all options, see docs/configuration.md.

Error handling

Phase reports operation status through PhaseResult.

PhaseResult result = phase.start();
if (!result) {
Serial.println(result.message);
return;
}

For all error codes, see docs/api.md.

License

MIT - see LICENSE.md.

ZekStack

Part of the ZekStack ESP32 library stack.

About

Phase is an async application lifecycle orchestration library for ESP32.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages