alec 1.3.1

Adaptive Lazy Evolving Compression - Smart codec for IoT sensor data with 90% compression ratio
Documentation

ALEC — Adaptive Lazy Evolving Compression


Why ALEC?

In many environments, every bit counts:

  • 🛰️ Satellite communications at a few kbps
  • 🌿 Battery-powered IoT sensors lasting years
  • 🌍 Rural areas with limited satellite connectivity
  • 🌊 Underwater acoustic links
  • 🏭 Industrial networks with restricted bandwidth

ALEC addresses these challenges with an innovative approach: transmit only what has value.


Features

🦥 Lazy Compression

ALEC doesn't transmit all data — it first sends the decision, then details only if needed.

Without ALEC:  [Complete data] ──────────────────────▶ 1000 bytes
With ALEC:     [Alert: anomaly detected] ────────────▶ 12 bytes
               [Details on demand] ──────────────────▶ 500 bytes (if requested)

🔄 Evolving Context

Encoder and decoder build a shared dictionary that improves over time.

Week 1:  "temperature=22.3°C" ──────────────────────▶ 20 bytes
Week 4:  [code_7][+0.3] ───────────────────────────▶ 3 bytes

⚖️ Smart Asymmetry

Computational effort is placed where resources exist.

Mode Encoder Decoder Use Case
Standard Light Heavy IoT sensors, drones
Reversed Heavy Light Broadcast distribution

📊 Priority Classification

Each data point receives a priority that determines its handling:

Priority Behavior Example
P1 CRITICAL Immediate send + acknowledgment Fire alert
P2 IMPORTANT Immediate send Anomaly detected
P3 NORMAL Standard send Periodic measurement
P4 DEFERRED On demand only Detailed history
P5 DISPOSABLE Never sent Debug logs

Use Cases

🚜 Connected Agriculture

Field sensors monitor moisture, temperature, and nutrients. With ALEC, they run 10 years on battery by transmitting only alerts and anomalies.

🏥 Rural Telemedicine

A portable ultrasound in a remote area first sends "suspected cardiac anomaly" in 50 bytes. The remote doctor decides if they need the full image.

🚛 Vehicle Fleets

500 trucks report their position. After a few weeks, the system knows the usual routes and only transmits deviations.

🛰️ Space Observation

A satellite photographs Earth. It only sends significant changes compared to previous images.

➡️ See all detailed use cases


Ecosystem

ALEC consists of multiple crates:

Crate Description Features
alec Core compression codec Encoder, Decoder, Context
alec-ffi C/C++ bindings FFI interface, embedded targets
alec-gateway Multi-sensor orchestration Channel management, Frame aggregation
alec-gateway[metrics] Entropy observability TC, H_joint, Resilience R
alec-complexity Anomaly detection Baseline, Z-scores, Events

Quick Install

# Core codec only
[dependencies]
alec = "1.2"

# C FFI (std)
[dependencies]
alec-ffi = "1.2"

# C FFI for embedded (bare-metal, no RTOS)
[dependencies]
alec-ffi = { version = "1.2", default-features = false, features = ["bare-metal"] }

# C FFI for Zephyr RTOS
[dependencies]
alec-ffi = { version = "1.2", default-features = false, features = ["zephyr"] }

Quick Start

Prerequisites

  • Rust 1.70+ (encoder and decoder)
  • Or: C compiler (embedded encoder only via alec-ffi)

Installation

git clone https://github.com/zeekmartin/alec-codec.git
cd alec-codec
cargo build --release
cargo test

First Example

use alec::{Encoder, Decoder, Context, RawData};

fn main() {
    let mut ctx_emitter = Context::new();
    let mut ctx_receiver = Context::new();

    let encoder = Encoder::new();
    let decoder = Decoder::new();

    for i in 0..100 {
        let data = RawData::new(20.0 + (i as f64 * 0.1), i);

        // Encode
        let message = encoder.encode(&data, &ctx_emitter);
        ctx_emitter.observe(&data);

        // Decode
        let decoded = decoder.decode(&message, &ctx_receiver).unwrap();
        ctx_receiver.observe(&decoded);

        println!("Original: {:.1}, Size: {} bytes", data.value, message.len());
    }
}

➡️ Complete getting started guide


Embedded / no_std

ALEC supports embedded targets from version 1.2.0. The alec-ffi crate provides C bindings with three feature tiers:

Feature comparison

Feature Allocator Panic handler Target
std (default) System System Linux, macOS, Windows
no_std User-provided User-provided Any embedded
bare-metal embedded-alloc (8KB heap) loop {} Bare-metal (no RTOS)
zephyr Zephyr k_malloc/k_free loop {} Zephyr RTOS

Bare-metal (no RTOS)

alec-ffi = { version = "1.2", default-features = false, features = ["bare-metal"] }
rustup target add thumbv8m.main-none-eabihf
cargo build --release --target thumbv8m.main-none-eabihf --no-default-features --features bare-metal

Zephyr RTOS

alec-ffi = { version = "1.2", default-features = false, features = ["zephyr"] }
rustup target add thumbv8m.main-none-eabi
cargo build --release --target thumbv8m.main-none-eabi --no-default-features --features zephyr

Note on target selection for Zephyr: Use thumbv8m.main-none-eabi (not eabihf). Zephyr's nRF91 toolchain compiles in nofp mode — using the hf variant causes an ABI mismatch at link time.

CMakeLists.txt integration (Zephyr)

add_library(alec_ffi STATIC IMPORTED GLOBAL)
set_target_properties(alec_ffi PROPERTIES
    IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libalec_ffi.a
)
target_include_directories(alec_ffi INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)
# Do NOT use --whole-archive — causes premature static initialisation before Zephyr heap is ready

Add a critical_section.c to your Zephyr app:

#include <zephyr/kernel.h>

static unsigned int cs_irq_key;

void _critical_section_1_0_acquire(void) { cs_irq_key = irq_lock(); }
void _critical_section_1_0_release(void) { irq_unlock(cs_irq_key); }

Validated embedded platforms

Platform SoC Feature Status
Nordic nRF9151 SMA-DK Cortex-M33 zephyr ✅ Validated
Generic Cortex-M33 thumbv8m bare-metal ✅ Builds

➡️ See the full NB-IoT demo


Documentation

Core Documentation

Document Description
Architecture System design and ADRs
Getting Started Getting started guide
Protocol Reference Protocol specification
Security Security considerations
FAQ Frequently asked questions

Module Documentation

Document Description
Gateway Guide Multi-sensor orchestration
Metrics Guide Entropy and resilience computation
Complexity Guide Baseline learning and anomaly detection
Configuration Complete configuration reference
Integration Integration patterns

Performance

Results on reference dataset (temperature sensor, 24h, 1 measurement/min):

Metric Without context After warm-up Target
Compression ratio 0.65 0.08 < 0.10 ✅
P1 Latency 45ms 42ms < 100ms ✅
Encoder RAM 12KB 28KB < 64KB ✅

Roadmap

  • v1.0 — Production ready ✅
  • v1.2.0 — no_std support ✅
  • v1.2.1 — bare-metal embedded (Cortex-M) ✅
  • v1.2.3 — Zephyr RTOS support ✅
  • v1.3 — RIOT OS support
  • v1.4 — FreeRTOS support

➡️ See the complete roadmap


Contributing

Contributions are welcome! See:


License

ALEC is dual-licensed:

Open Source (AGPL-3.0)

Free for open source projects, research, and personal use.

[dependencies]
alec = "1.2"

Commercial License

For proprietary use without open-source obligations. Starting at $500/year for startups.

👉 Get a Commercial License

See LICENSE for details.


Acknowledgments

ALEC draws inspiration from:

  • NASA error-correcting codes (turbo codes, LDPC)
  • Dictionary compression (LZ77, LZ78)
  • Efficient IoT protocols (CoAP, MQTT-SN)