Skip to content

ESPToolKit/esp-reboot-manager

Repository files navigation

ESPRebootManager

ESPRebootManager is a centralized reboot coordinator for ESP32 projects. Any module can request a reboot, registered guard callbacks vote whether reboot is safe, and registered evaluation callbacks report the final decision.

CI / Release / License

CI Release License: MIT

Features

  • Multi-guard callback API: onRebootRequest(...).
  • Multi-evaluation event API: onEvaluation(...).
  • Deferred guard votes: any guard can defer and force evaluation restart from guard #1.
  • Async request handling on a dedicated FreeRTOS task.
  • Single active request policy with deterministic Busy responses.
  • Polling support for missed events via isRebootRequested(), rebootStatus(), and lastEvaluation().
  • Bounded reason/detail buffers for deterministic memory usage.

Installation

  • PlatformIO: add https://github.com/ESPToolKit/esp-reboot-manager.git to lib_deps.
  • Arduino IDE: install as ZIP from this repository.

Single Include

#include <ESPRebootManager.h>
#include <cstdio>

Quick Start

#include <ESPRebootManager.h>

ESPRebootManager rebootManager;

void setup() {
    ESPRebootManagerConfig config;
    config.taskName = "reboot-manager";
    config.taskStackSizeBytes = 6 * 1024;
    config.taskPriority = 1;
    config.taskCoreId = tskNO_AFFINITY;
    config.callbackTimeoutMs = 1000;
    rebootManager.init(config);

    rebootManager.onRebootRequest([](const RebootRequestContext& ctx) {
        RebootVote vote;
        if (ctx.reason[0] == '\0') {
            vote.allow = false;
            std::snprintf(vote.detail, sizeof(vote.detail), "empty reason is not allowed");
        }
        return vote;
    });

    rebootManager.onEvaluation([](const RebootEvaluation& evaluation) {
        if (evaluation.accepted) {
            Serial.printf("reboot accepted: id=%lu reason=%s\n",
                          static_cast<unsigned long>(evaluation.requestId),
                          evaluation.reason);
        } else {
            Serial.printf("reboot rejected: code=%u blocker=%s detail=%s\n",
                          static_cast<unsigned>(evaluation.code),
                          evaluation.blockerName,
                          evaluation.detail);
        }
    });

    (void)rebootManager.requestReboot("firmware-update", 1500);
}

Examples

  • basic_reboot_request: minimal accepted request flow with guard + evaluation callbacks.
  • busy_and_retry: demonstrates Busy submit status and retrying once the manager returns to Idle.
  • guard_blocking: shows a guard rejecting reboot until a maintenance window opens.
  • callback_timeout: demonstrates CallbackTimeout behavior when a guard runs longer than callbackTimeoutMs.

API Summary

  • bool init(const ESPRebootManagerConfig& config = {})
  • void deinit()
  • bool isInitialized() const
  • RebootCallbackId onRebootRequest(GuardCallback cb)
  • RebootCallbackId onEvaluation(EvaluationCallback cb)
  • bool offRebootRequest(RebootCallbackId id)
  • bool offEvaluation(RebootCallbackId id)
  • RebootSubmitResult requestReboot(const char* reason, uint32_t delayMs = 0)
  • bool isRebootRequested() const
  • RebootRequestStatus rebootStatus() const
  • RebootEvaluation lastEvaluation() const

Status Flow

Accepted path: Idle -> Requested -> Evaluating -> Delaying -> Rebooting -> Idle

Deferred path: Idle -> Requested -> Evaluating -> Deferred -> Evaluating -> ...

If any guard rejects (or times out), the flow is: Idle -> Requested -> Evaluating -> Idle

Guard Vote Semantics

  • allow=true: guard accepts current pass.
  • allow=false: request is blocked immediately and reboot does not proceed.
  • defer=true: request is deferred immediately, remaining guards are skipped for the current pass, and evaluation restarts from the first guard after deferTimeoutMs (minimum 1ms when omitted/0).

Formatting Baseline

This repository follows the firmware formatting baseline from esptoolkit-template:

  • .clang-format is the source of truth for C/C++/INO layout.
  • .editorconfig enforces tabs (tab_width = 4), LF endings, and final newline.
  • Format all tracked firmware sources with bash scripts/format_cpp.sh.

License

MIT - see LICENSE.md.

About

A centralized reboot coordinator for ESP32

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

 
 
 

Contributors