Mappls InTouch

InTouch C / C++ device SDK

The C99 core builds into a static library for firmware, RTOS tasks and native Linux processes. A C++11 caller includes the same header with C linkage. The core maintains one mutable burst in caller-owned memory, serializes typed fields directly into that buffer, and hands sealed bytes to your storage hook. It uses standard C formatting and libm. The POSIX example supplies disk persistence and HTTP delivery with libcurl and json-c.

Build and run

Install a C99 compiler, C++11 compiler, make, pkg-config, libcurl development files and json-c development files. Only the example host program needs libcurl/json-c. Linux Debian packages are build-essential pkg-config libcurl4-openssl-dev libjson-c-dev.

make all check
./build/edge-host diagnostics
./build/edge-host sample temperature celsius 4.8
./build/edge-host motion 14 0 0
./build/edge-host sync

Set EDGE_TOKEN in the process environment to the local edge-lab credential. Load it from the ignored repository .env in a trusted shell or secret manager. Set INTOUCH_ORIGIN for another HTTPS service. The default is http://127.0.0.1:8917. The sender accepts plain HTTP only on loopback. Use INTOUCH_SPOOL to select a persistent directory (default .edge-spool, owned by this user with mode 0700). Dedicate one directory per tenant/device/service and preserve it across upgrades. diagnostics reads actual OS CPU count, memory page size and monotonic uptime. sample and motion take caller-provided values. sync drains previously committed batches after a reconnect. Each command exits nonzero if delivery fails and leaves committed files for a later invocation.

# From sdk/c, with the local Docker API running:
python3 tests/roundtrip.py
# Build the standalone Linux sender and run C, C++ and board-adapter checks inside Linux:
docker build -t mappls-intouch-edge:local .
python3 tests/linux_smoke.py

The integration check creates a separate private spool, forces two unsuccessful sends to a closed loopback port, launches a fresh process to drain both files, and verifies each original timestamp, value, trigger and batch ID through the viewer API.

Firmware integration

  1. Include include/intouch.h and compile src/intouch.c with C99 support, floating-point snprintf and libm. Use the C numeric locale. Reserve a caller-owned arena of 260 bytes to 512 KiB. An 8 KiB arena suits small batches. Give one task exclusive access to each batch/rule instance.
  2. Supply it_hooks.new_id using a reboot-safe sequence plus device-unique prefix or cryptographic randomness. IDs use at most 96 ASCII letters, digits, periods, hyphens or underscores. Use a durable sequence to avoid reuse after power loss.
  3. Supply it_hooks.store to append a complete record to a flash journal (CRC plus commit marker) or deliver it to an acknowledged transport. Return success only after durable acceptance. The SDK clears its arena only on success. Retrying a sealed batch preserves byte-identical payload, trigger and ID. Retain the board's unresolved sealed arena until storage is available. An uncommitted RAM burst may be lost on power failure.
  4. Convert driver measurements to named typed fields, then call it_add with event epoch milliseconds. Preserve monotonic timing separately in a value when absolute time is uncertain. Use numbers, booleans or printable ASCII strings; keys and stream names use the ID character set. Each sample accepts up to 32 fields and 4 KiB of encoded data. Large media belongs in the media API.
  5. On IT_FULL commit the preceding burst with IT_SIZE, then retry that reading. A sample that cannot fit an empty buffer needs a larger buffer or a smaller schema. Call it_commit with IT_TIMER, IT_CONTROL, IT_MANUAL or IT_INCIDENT to flush on a scheduler deadline, an authenticated flush command, a manual request or a detected incident. A burst has at most 256 readings.
  6. Feed linear acceleration (gravity removed, m/s²) and monotonic milliseconds to it_detect_motion. A threshold crossing above the configured magnitude that clears the cooldown produces a local event; sustained high acceleration can retrigger after each cooldown. The board example records the motion and incident before sealing. Connect BLE, I²C, SPI, CAN, Modbus or a vendor SDK by mapping its readings to it_field. See examples/rtos_adapter.c for the compile-checked MCU-side adapter and board functions to implement.
it_field fix[] = {{"lat", IT_NUMBER, 28.61, NULL},
                  {"lon", IT_NUMBER, 77.21, NULL},
                  {"accuracyM", IT_NUMBER, 6, NULL}};
enum it_status status = it_add(&batch, "location", capture_unix_ms, fix, 3);

The POSIX host writes a private temporary file, syncs it, renames it and syncs its directory before releasing the RAM burst. A process-level filesystem lock makes file delivery single-writer. Up to 256 committed files, each at most 32 KiB, bound its spool. On restart, sync sends them in filename order. Successful delivery requires a 2xx receipt with the matching ID and sample count. A crash following server commit can replay a file; server-side idempotency prevents duplicate samples. Provision a supervisor or RTOS timer for jittered retries and heartbeat scheduling. The host example is a one-shot batch sender. Remote configuration polling, device authentication refresh, camera drivers, flash wear levelling and OTA require product-specific integration. The embedded adapter has been compile-tested; physical flash, radios, power-loss recovery and battery draw require target-board measurements.