Arduino (ESP32)
Configure and run the Honch Arduino ESP32 wrapper.
The Arduino port is a C++ wrapper around the shared core for ESP32 boards using the Arduino framework. It ships to the PlatformIO registry as honch/Honch and vendors a byte-identical copy of the core so the library is self-contained.
Preview
0.3.0. ESP32-only. Use it for evaluation and controlled pilots until your product has passed hardware, TLS, offline-queue, flush, retry, and power-cycle validation.Before You Start
- Targets ESP32 with the Arduino-ESP32 core (
WiFi,HTTPClient, and friends). It is not a relay and does not handle OTA. - The default queue is RAM-only — events and identity are lost on reset or power loss unless you supply durable adapters.
- There is no background task. Call
tick()(or its aliasloop()) from a task or your sketch loop.
1. Add The Library
In platformio.ini:
lib_deps = honch/Honch@^0.3.02. Configure And Send A First Event
HonchConfig uses default member initializers, so construct it empty and assign fields — do not use designated-initializer syntax (it will not compile in C++).
#include <WiFi.h>
#include <time.h>
#include <Honch.h>
static uint8_t eventBuffer[8192];
void setup() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) delay(250);
// ESP32 has no battery-backed RTC: sync the clock before tracking, or every
// event is stamped near 1970 and falls outside the dashboard's time window.
configTime(0, 0, "pool.ntp.org");
while (time(nullptr) < 1577836800UL) delay(250);
HonchConfig config = {};
config.apiKey = "your-api-key";
config.host = "https://i.honch.io";
config.deviceModel = "demo-board";
config.firmwareVersion = "1.0.0";
config.rootCaPem = ROOT_CA_PEM; // required for HTTPS
config.eventBuffer = eventBuffer;
config.eventBufferSize = sizeof(eventBuffer);
if (!honch::defaultClient().begin(config)) {
Serial.printf("honch begin failed: %s\n", honch::defaultClient().lastError());
return;
}
honch::defaultClient().track("boot");
}
void loop() {
honch::defaultClient().tick();
delay(1000);
}Sync the clock before tracking — ESP32 has no RTC
The ESP32 has no battery-backed real-time clock, so its clock reads 1970 until you set it. Honch stamps each event with the on-device time, so tracking before the clock is set produces events that upload and ingest fine but are dated to ~1970 and fall outside the dashboard's time window — they look "missing." Call configTime(...) after Wi-Fi connects and wait for a real time before begin()/track(), as shown above. See Timestamps.
Methods return bool (true on success); read lastError() for the status string when one returns false. Calls are serialized on a per-instance mutex with a 10 ms timeout — under contention a call returns false with lastError() of "busy".
| Field | Default | Notes |
|---|---|---|
apiKey, host, deviceModel, firmwareVersion | — | Required. |
rootCaPem | — | PEM root CA for HTTPS. |
environment | "production" | |
eventBuffer / eventBufferSize | — | RAM queue backing; eventBufferSize also sets max_event_bytes. |
flushIntervalSeconds, flushMinIntervalMs, flushEventThreshold | shared defaults | flushEventThreshold also sets the batch size. |
transportTimeoutMs | 8000 | Capped at 10000. |
connectivityCallback | — | Return false when offline. |
enableErrorTracking | false | Detect an abnormal ESP32 reset at begin() and emit a $crash with the reset reason. This port captures the reset reason only — no coredump or symbolicated backtrace (those are ESP-IDF only). |
insecureSkipTlsVerify | false | Local testing only; logs a warning. |
stateStorageOps / eventQueueOps | — | Durable identity / durable queue. |
The wrapper hardcodes $sdk_platform to arduino-esp32 and caps the RAM queue at 1000 entries. The device ID defaults to esp32-<eFuse MAC>.
3. Track, Identify, And Sessions
const honch_property_t props[] = { honch_prop("mode", honch_str("record")) };
honch::defaultClient().track("mode_changed", props, 1);
honch::defaultClient().identify("user-123");
honch::defaultClient().sessionStart("recording");
honch::defaultClient().sessionEnd();
honch::defaultClient().flush();Transport And TLS
Uploads use HTTPClient over WiFiClientSecure to <host>/capture. Set rootCaPem for real HTTPS; insecureSkipTlsVerify = true disables verification for local testing only and logs a warning. Production must use a real root CA.
Durability
By default the queue is RAM-only and identity is not persisted, so both are lost on reset. For persistence, wire eventQueueOps to a durable queue (a tiered RAM + non-volatile queue is available; the HonchDurableQueue example shows a LittleFS cold tier) and stateStorageOps to non-volatile storage such as Preferences. If you call the tiered queue's persist function yourself, hold the same lock as track()/tick().
Examples And Build Check
The library's registered examples are HonchBasic and HonchOfflineQueue. The repository also includes a HonchDedicatedTask sketch and HonchDurableQueue reference helpers — a LittleFS cold tier for the tiered queue, shipped as .h/.cpp rather than a standalone sketch. Compile-check with arduino-cli:
arduino-cli compile --fqbn esp32:esp32:esp32 examples/HonchBasicDebugging Failures
lastError() returns a short status word ("transport error", "rejected"). For why a call failed, use the structured accessors:
if (!Honch.flush()) {
honch_error_detail_t detail;
Honch.lastErrorDetail(&detail);
Serial.println(Honch.lastErrorMessage());
// "rejected: HTTP 401 - API key invalid or revoked (reason=auth_invalid_key)"
if (detail.http_status == 401) { /* bad project key */ }
}lastErrorDetail(&out) fills status, reason, http_status, os_error, message, and component; lastErrorMessage() returns the formatted one-liner. The SDK also logs that same line once per distinct failure via log_w/log_e, so failures show up on the serial monitor automatically. See Error Context & Diagnostics.
Public API
honch::defaultClient() returns the singleton. Methods: begin(config), track(name, props, count), identify(id, traits, count), setProperty(key, value), sessionStart(name), sessionEnd(), flush(), tick() (alias loop()), reset(), shutdown(), deviceId(), queueStats(&stats), lastError(), lastErrorDetail(&detail), and lastErrorMessage().