Windows
PlatformIO SDK · MIT · v1.0.0
OXRecorder-1.0.0.zipDownload the OXRecorder SDK as a PlatformIO library and reuse it in your own project
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).
PlatformIO SDK · MIT · v1.0.0
OXRecorder-1.0.0.zipsame contents, gzipped tarball
OXRecorder-1.0.0.tar.gz
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):
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 |
In VS Code: Extensions panel → search “PlatformIO IDE” → Install → reload. A new alien-head icon appears in the sidebar.
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.
Extract OXRecorder-1.0.0.zip somewhere, then point
lib_deps at the folder (next section). PlatformIO copies it
into .pio/libdeps/ on the next build — no manual file
juggling.
Use the bottom PlatformIO toolbar: ✓ build, → upload, plug icon for the
serial monitor (115200 baud to see OXLog output).
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's SdFs/FsFile
(FAT + exFAT) API. That API only exists with -D SDFAT_FILE_TYPE=3,
so the SD build_flags below 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
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:
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.
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().
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).
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.
libArchive: false so that glue is always linked — call
begin() with no device argument. If your toolchain links the
SDK as a static archive with dead-stripping, call
OXRecorder::init() once before the first begin()
as a guarantee (idempotent; no backend classes needed in your code).
OXLog/OXSecurity include
<Arduino.h>, so device builds target the Arduino
framework. For a bare native host build use the bundled shim
(above) and the SDK classes compile and run with no hardware.
-std=gnu++17 in the consuming
project's build_flags; the SDK classes use inline-static members
and other C++17 features.