Skip to main content

hxtp-micro

Embedded SDK for ESP32/ESP8266 — Arduino/PlatformIO compatible with zero dynamic memory allocation.

Installation​

PlatformIO​

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
hxtp-micro@^1.0.3
knolleary/PubSubClient@^2.8
build_flags =
-DHXTP_RELEASE=1

Arduino Library Manager​

Search for "hxtp-micro" in Arduino Library Manager.

Quick Start​

#include <Hxtp.h>

hxtp::Client client;

void setup() {
hxtp::Config config;
config.api_base_url = "https://api.hestialabs.in/v1";
config.device_uuid = "permanent-hw-id";
config.api_key = "YOUR_PORTAL_API_KEY";
config.verify_server = true;

client.begin(config);

// Register capability
client.registerCapability(1, "toggle_led",
[](const char* params, uint32_t len, void* ctx) {
int64_t value = 0;
if (!hxtp::json_get_int64(params, len, "value", &value)) {
return hxtp::CapabilityResult{false, 0};
}
digitalWrite(LED_BUILTIN, value ? HIGH : LOW);
return hxtp::CapabilityResult{true, 0};
}
);

client.connect();
}

void loop() {
client.loop(); // Handles identity generation, claiming, and handshakes
}

Configuration​

struct Config {
const char* api_base_url; // Hestia Cloud Endpoint
const char* device_uuid; // Permanent hardware identifier
const char* api_key; // Portal bootstrap key
bool verify_server; // TLS verification (recommended)
const char* wifi_ssid; // Optional: pre-configured WiFi
const char* wifi_password; // Optional: pre-configured WiFi
};

Build Profiles​

ProfileDescriptionUse Case
HXTP_RELEASEFull features, optimizedProduction
HXTP_DEBUGVerbose errorsDevelopment
HXTP_LITEReduced memoryESP32 constrained
HXTP_CONSTRAINEDMinimalESP8266

State Machine​

Capabilities​

Register Capability​

client.registerCapability(
id, // Capability ID (1-255)
name, // Name (e.g., "toggle_led")
handler, // Callback function
);

Handler Signature​

CapabilityResult handler(
const char* params, // JSON params
uint32_t len, // Params length
void* ctx // User context
);

Return Value​

struct CapabilityResult {
bool success; // true = handled
int16_t error; // Error code or 0
};

Zero-Allocation JSON​

The SDK includes a zero-allocation JSON parser:

// Get string
char buffer[64];
size_t len;
if (hxtp::json_get_string(json, json_len, "key", buffer, sizeof(buffer), &len)) {
// Use buffer
}

// Get int64
int64_t value;
if (hxtp::json_get_int64(json, json_len, "key", &value)) {
// Use value
}

// Get bool
bool flag;
if (hxtp::json_get_bool(json, json_len, "key", &flag)) {
// Use flag
}

// Get raw (nested object)
if (hxtp::json_get_raw(json, json_len, "key", out, out_cap, &len)) {
// Use raw JSON
}

Validation Pipeline​

The SDK runs a hardened 7-step validation on every incoming message:

StepCheckDetails
1VersionMust be "HxTP/3.1"
2TimestampFreshness window (Âą30s)
3Payload SizeSize enforcement
4NonceReplay protection (ring buffer)
5SequenceMonotonic counter check
6Payload HashSHA-256 integrity
7SignatureEd25519 verification (Cloud Root)

Supported Boards​

BoardPlatformCryptoRAMFlash
ESP32-S3espressif32mbedTLS13.8%29.6%
ESP32espressif32mbedTLS13.9%51.7%
NodeMCUespressif8266BearSSL39.5%39.6%
Wemos D1espressif8266BearSSL39.5%39.6%

MQTT Topics​

Pattern: hxtp/{tenant_id}/device/{device_id}/{channel}

ChannelDirectionPurpose
cmdInboundRPC Commands
cmd_ackOutboundCommand Acknowledgments
stateOutboundState Reporting
helloOutboundHandshake Handlers

Memory Configuration​

// Config.h overrides
#define HXTP_NONCE_CACHE_SIZE 64 // Entries (16 for CONSTRAINED)
#define HXTP_FRAME_BUFFER_SIZE 4096 // Bytes (1536 for CONSTRAINED)
#define HXTP_MAX_PAYLOAD_SIZE 16384 // Max payload
#define HXTP_MAX_NONCE_LEN 32 // Max nonce length

FROZEN Canonical Framing​

The HxTP/3.1 pipe-separated framing is FROZEN. The order of fields is immutable:

version|device_id|tenant_id|client_id|message_id|request_id|sequence_number|timestamp|nonce|message_type|payload_hash

Any change to this sequence or content format will invalidate signatures globally.