OXRecorder SDK
Download the OXRecorder SDK as a PlatformIO library and reuse it in your own project
Download
The OXRecorder SDK bundles the firmware's ten core classes as a self-contained, redistributable PlatformIO library. Grab an archive and drop it into any PlatformIO project (see Install below).
Both archives contain an identical OXRecorder/ SDK tree — pick
the one for your OS (the .zip unpacks natively on Windows, the
.tar.gz on macOS/Linux). They are otherwise interchangeable.
The SDK's custom partition table is shipped separately so you can drop it into your project (see partition table below):
partitions.csvWhat's inside
The SDK classes keep every hardware peripheral behind an injected
interface (storage, radios, LED, I2S, cipher, GPIO), so the library is
board-agnostic. It also ships production ESP32/Arduino backends
for every seam and registers them as the managers' defaults at static-init
time — so on a real board a manager's begin() just works with
no wiring, while you can still inject your own backend (a different
board, or a fake for host tests). It builds against the
Arduino framework (OXLog and
OXSecurity use Arduino's
String/Print/Serial) and ships a host
shim so it also compiles in a bare native build for unit tests.
| Class | Responsibility | Bundled backend |
|---|---|---|
OXLog | Leveled, printf-style logging to an injectable sink | — (Arduino Serial) |
OXFileManager | Internal-flash + SD file I/O over an IStorageBackend | LittleFsBackend, SdFatBackend |
OXWirelessManager | Wi-Fi + BLE transport over IWifiDevice / IBluetoothDevice | EspWifiDevice, EspBluetoothDevice |
OXAPIManager | REST routing + BLE command dispatch + outbound HTTP client | EspHttpClient |
OXConfigManager | Key/value config and reset-button handling | (uses OXSwitchManager) |
OXLEDManager | Status-LED color + animation over an ILedDevice | Ws2812Device |
OXAudioManager | Audio capture over an injected I2S device | Esp32I2SDevice |
OXBatteryManager | ADC battery-voltage sampling with divider/curve mapping | EspAdcInput |
OXSecurity | AES-CBC over an injected cipher | MbedAesCbc |
OXSwitchManager | GPIO debounce + long-press over an IGpioInput | EspGpioInput |
├── library.json # PlatformIO manifest (libArchive:false)
├── LICENSE # MIT
├── README.md # usage + install
├── MANIFEST.md # exact list of exported files
├── examples/BlinkStatusLed/ # runnable sample sketch
├── extras/host-mock/Arduino.h # shim for native (host) test builds
└── src/ # managers (flat) + hardware backends (subfolders)
├── OXRecorder.{h,cpp} # SDK facade — optional init()
├── OXLog.{h,cpp} OXLEDManager.{h,cpp} … # 10 managers + shared headers, flat
└── led/ wifi/ bluetooth/ audio/ http/ gpio/ crypto/ backends/ # backends
Install in a PlatformIO project
-
1
Install the PlatformIO IDE extension
In VS Code: Extensions panel → search “PlatformIO IDE” → Install → reload. A new alien-head icon appears in the sidebar.
-
2
New project
PlatformIO icon → PIO Home → Open → + New Project. Set Board to Espressif ESP32-S3-DevKitC-1-N8 and Framework to Arduino, then Finish. This is the compatible PlatformIO profile with a 4 MB flash-size override for the no-PSRAM ESP32-S3 Super Mini used by OXRecorder.
-
3
Unpack the download & reference it
Extract
OXRecorder-1.0.0.zipsomewhere, then pointlib_depsat the folder (next section). PlatformIO copies it into.pio/libdeps/on the next build — no manual file juggling. -
4
Build · Upload · Monitor
Use the bottom PlatformIO toolbar: ✓ build, → upload, plug icon for the serial monitor (115200 baud to see
OXLogoutput).
platformio.ini
Reference the SDK with one of the three lib_deps
forms below. Two bundled backends link third-party libraries, so add those to
lib_deps as well:
-
greiman/SdFat@^2.2.2— required by the SD backend (SdFatBackend.cpp), which uses SdFat'sSdFs/FsFile(FAT + exFAT) API. That API only exists with-D SDFAT_FILE_TYPE=3, so the SDbuild_flagsbelow are required too. -
h2zero/NimBLE-Arduino@^1.4.2— required by the Bluetooth backend (EspBluetoothDevice.cpp), which provisions over a NimBLE NUS service.
You only need these if you use the SD-card or Bluetooth backends; drop the matching line (and SD flags) if you don't.
[env:esp32-s3-super-mini]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
board_build.partitions = partitions.csv ; enlarge the app partition (see below)
build_flags =
-std=gnu++17
-D ARDUINO_USB_MODE=1
-D ARDUINO_USB_CDC_ON_BOOT=1
; SdFat (for SdFatBackend): FAT16/FAT32 + exFAT API (SdFs/FsFile).
-D SDFAT_FILE_TYPE=3
-D DISABLE_FS_H_WARNING
-D USE_SD_CRC=1
lib_deps =
; --- third-party backends (add only the ones you use) ---
greiman/SdFat@^2.2.2 ; for SdFatBackend.cpp (SD card)
h2zero/NimBLE-Arduino@^1.4.2 ; for EspBluetoothDevice.cpp (BLE)
; --- the OXRecorder SDK itself — one of: ---
; (a) the unpacked download — simplest:
file:///path/to/OXRecorder
; (b) OR the archive directly (PlatformIO unpacks it):
; https://your-host.com/OXRecorder-1.0.0.zip
; (c) OR a git repo:
; https://gitlab.com/your/oxrecorder-lib.git
Partition table
The SDK is large enough that the default Arduino partition table can run the
app partition out of room. The standard 8 MB S3 table splits flash into
two ~3.2 MB app slots (for OTA). The bundled
partitions.csv drops the second OTA slot and folds that space
into a single 6 MB app partition, keeping an internal LittleFS partition
for config and a coredump region.
Download partitions.csv
(button at the top), drop it in your project root next to
platformio.ini, and point to it with:
board_build.partitions = partitions.csv
The table targets the 4 MB ESP32-S3 Super Mini with no OTA. Its layout:
otadata 8 KB # boot-slot selector (kept for Arduino-core compatibility)
app0 3 MB # firmware (was 1.28 MB in the default table)
spiffs 896 KB # internal LittleFS (config.json / device.cfg / health.json)
coredump 64 KB # crash dump region
0x400000 (4 MB). Recorded audio is meant for the SD card
(Storage::External), not internal flash, so the 896 KB
LittleFS partition is sized only for small config files.
Use it in src/main.cpp
Headers are included with angle brackets (<OXLog.h>) — the
library is on the include path. Everything lives in the
OXRecorder namespace. Because each manager's bundled backend
registers itself as the default, you just call begin() — no
device argument, no extra wiring.
#include <Arduino.h>
#include <time.h>
#include <OXRecorder.h>
#include <OXLog.h>
#include <OXLEDManager.h>
using namespace OXRecorder;
OXLEDManager led;
unsigned long diff = 0;
void setup() {
// optional; guarantees the bundled default devices
OXRecorder::init();
// initialize logging to the USB serial port at 115200 baud, with INFO level
OXLog::begin(115200);
// The bundled Ws2812Device drives the LED automatically. No device argument.
// To override it on a different board: led.setDevice(&myLedDevice);
led.begin();
led.setStatus(SystemStatus::BluetoothPairing);
}
void loop() {
// get current timestamp
unsigned long now = millis();
//set the led reference time to animate the led
led.animate(now);
// every one second, we output the timestamp
if (diff != now/1000) {
diff = now/1000;
OXLog::info("current time: %u", now/1000);
}
delay(5);
}
OXRecorder::init() is optional. Each
hardware backend registers itself as its manager's default at static-init
time, and this SDK ships with libArchive: false so PlatformIO
links that self-registering glue directly — begin() works on
its own. OXRecorder::init() is a belt-and-suspenders call for
toolchains that link the SDK as a static archive with aggressive
dead-stripping (which can discard glue nothing references directly): calling
it once before your first begin() forces every bundled default
device to link in. It is idempotent, needs no backend classes in your code,
and does not call any manager's begin().
Override a bundled backend
The bundled ESP32/Arduino backends cover the OXRecorder reference board. To
run on different hardware — or to inject a fake in host tests — you implement
the relevant interface and register it before begin(),
which overrides the default. Example for storage:
#include <OXFileManager.h>
using namespace OXRecorder;
// You provide a class implementing IStorageBackend (e.g. wrapping LittleFS).
class MyLittleFs : public IStorageBackend { /* mount(), readFile(), … */ };
OXFileManager files;
MyLittleFs flash;
void setup() {
files.setBackend(Storage::Internal, &flash); // override the bundled default
files.writeFile(Storage::Internal, "/hello.txt",
reinterpret_cast<const uint8_t*>("hi"), 2);
}
The same seam exists on every manager:
OXWirelessManager::setWifiDevice() /
setBluetoothDevice(), OXLEDManager::setDevice(),
OXSecurity's cipher, and OXSwitchManager's
IGpioInput. Each interface is documented on its class's
API reference page.
src/led/, src/wifi/,
src/bluetooth/, src/backends/, etc., and double as
reference implementations of these interfaces — the model to follow when
writing a backend for your own board. They link ESP-IDF / NimBLE / SdFat, so
exclude those folders on a bare native build (see below).
Host testing (native, no hardware)
OXLog and OXSecurity include
<Arduino.h>, which does not exist in a bare
native build. The download bundles a minimal Arduino shim at
extras/host-mock/Arduino.h; point a native test
env's include path at it (and nowhere else, so device builds still use the
real header). The hardware backends link ESP32 headers, so exclude their
folders — and OXRecorder.cpp, which references them — with
build_src_filter, and inject your own fakes instead:
[env:native]
platform = native
build_flags =
-std=gnu++17
-I .pio/libdeps/native/OXRecorder/extras/host-mock ; supplies <Arduino.h>
build_src_filter =
+<*>
-<OXRecorder.cpp>
-<audio> -<backends> -<bluetooth> -<crypto> -<gpio> -<http> -<led> -<wifi>
lib_deps = file:///path/to/OXRecorder
The shim provides just enough (Print, Serial,
millis()) for the managers to compile and run on the host;
inject your own fakes for the hardware seams (don't call
OXRecorder::init() here — it's excluded with the backends).
This is the same shim the OXRecorder firmware uses for its own
native unit tests.
Notes & caveats
-
Default devices auto-register. Each bundled backend
installs itself as its manager's default at static-init, and the SDK ships
libArchive: falseso that glue is always linked — callbegin()with no device argument. If your toolchain links the SDK as a static archive with dead-stripping, callOXRecorder::init()once before the firstbegin()as a guarantee (idempotent; no backend classes needed in your code). -
Arduino dependency, host-testable anyway.
OXLog/OXSecurityinclude<Arduino.h>, so device builds target the Arduino framework. For a barenativehost build use the bundled shim (above) and the SDK classes compile and run with no hardware. -
C++17. Keep
-std=gnu++17in the consuming project'sbuild_flags; the SDK classes use inline-static members and other C++17 features. - Re-download to update. The archive is generated output — grab a newer version here rather than editing the unpacked copy by hand.