A textX-based DSL for declarative IoT device modeling with hardware-aware semantic validation and reproducible code generation for Raspberry Pi (Python) and RIOT (C).
Research and prototyping workflows for IoT devices share a common set of bottlenecks.
Device code is rewritten per platform with no shared source of truth. The same sensor logic takes different forms on Raspberry Pi, ESP32, and Arduino. Those implementations drift apart over time, and porting a design to a new target means starting from scratch or copying untested fragments from a sibling project. The absence of a single, authoritative device description makes it impossible to verify that two implementations for different platforms are functionally equivalent.
Pin assignments and protocol constraints are checked by hand, or not at all. An I2C address collision, a voltage mismatch between board and peripheral, or a GPIO shared across two outputs is typically caught at hardware bring-up, not during design. The cost of a late-stage fix ranges from a board respin to a damaged component. Manual inspection does not scale beyond a few peripherals.
Models are embedded in code spread across files. A hardware change -- swapping a sensor, rewiring a bus, changing the power source -- means editing multiple source files instead of updating a single declarative specification. There is no single artifact that describes the device as a whole. The wiring logic, protocol configuration, and pin assignments are scattered across initialization routines, header files, and configuration dictionaries.
There is no formal grounding for what constitutes a valid IoT device. The language of device design is informal, ad hoc, and varies across teams and projects. Reproducibility suffers because the design lives only in the implementer's head. Peer review of a device configuration is impossible without a shared, parseable representation that captures both structure and constraints.
DeMoL is a textX-based DSL that captures an IoT device as a single .dev model and
compiles it to validated, reproducible code for Raspberry Pi (Python) and RIOT (C).
The .dev model serves as the authoritative specification: it describes the board,
its peripherals, the electrical connections, the communication brokers, the sampling
policies, the user-defined constraints, and the alert triggers. All generators read
this single file and produce platform-specific artifacts from it.
DeMoL follows a three-stage pipeline.
-
Model -- A designer writes a
.devfile describing the board, peripherals, connections, communication brokers, sampling policies, constraints, and alerts. The syntax mirrors the hardware structure: boards, sensors, actuators, pins, protocols, and buses are all first-class citizens in the grammar. The file is self-contained and serves as the single source of truth for the device. -
Validate -- The semantic engine checks 21 hardware-aware rules: voltage compatibility, pin conflict detection, I2C address uniqueness, protocol frequency constraints, power budget limits, user-defined CONSTRAINT expressions, and ALERT trigger consistency. Validation errors are collected with precise line and column information and rendered with actionable hints. No code is generated for an invalid model. The validation pass is deterministic and reproducible.
-
Generate -- The validated model feeds platform-specific code generators. The RPi Python generator produces a commlib-based node with sensor initialization, MQTT publishing, and configurable sampling loops. The RIOT C generator produces bare-metal firmware with the same logical structure and the same connectivity pattern. Additional generators produce wiring diagrams (SVG), pin-mapping reports (MD + JSON), JSON model representations, and hardware construction guides.
DEVICE MixedConnectionDevice WITH
description="Device mixing manual CONNECT and SMARTCONNECT",
os=raspbian;
USE RaspberryPi_5_8GB;
USE BME680[EnvSensor], HCSR04[DistanceSensor];
BROKER[MQTT] Broker WITH host="localhost", port=1883;
// Manual wiring -- full control over pin assignments
CONNECT EnvSensor WITH
POWER gnd -- GND_1, vcc -- power_5v_a
DATA i2c[slave_address=0x76] sda -- GPIO2, scl -- GPIO3
@ "sensors/env";
A device model is a single text file. The full example adds a
SMARTCONNECT DistanceSensor block and lives at
examples/rpi/rpi_mixed_connect.dev.
The DSL syntax distinguishes between manual CONNECT blocks for precise wiring
control and SMARTCONNECT blocks for automatic pin assignment. The model also
supports SAMPLING blocks for data acquisition configuration, CONSTRAINT blocks
for user-defined invariants, and ALERT blocks for threshold-based triggers. Every
keyword in the language corresponds to a first-class concept in the metamodel.
Running demol generate rpi examples/rpi/rpi_mixed_connect.dev --output-dir ./output
produces envsensor_node.py (69 lines). The class shell shows the generator's
structure: commlib imports, sensor initialization, and MQTT publisher wiring.
from commlib.node import Node
from commlib.utils import get_timestamp_ns, Rate
from commlib.transports.mqtt import ConnectionParameters
from .msg import EnvMessage
from .bme680_envsensor import BME680_EnvSensor
class BME680Node:
_FREQUENCY = 10.0
_SAMPLING_MODE = "continuous"
def __init__(self):
self.sensor = BME680_EnvSensor()
self.node = Node(node_name='sensors.env.envsensor',
connection_params=ConnectionParameters(
host="localhost", port=1883))The RIOT C generator produces a structurally equivalent firmware in C with the same
pin configuration, protocol setup, and topic subscription logic. Both generators
derive their output from the same validated .dev model, guaranteeing that the RPi
Python prototype and the RIOT C deployment share the same hardware configuration.
The same model produces a wiring diagram and a pinmap report via
demol generate svg and demol generate pinmap.
A full list of all generator targets, their output formats, and usage examples is
in docs/code-generation.md.
Formal semantics -- A 1,800-line mathematical specification in
docs/semantics.md defines the device model,
voltage/pin/protocol constraints, and the validation engine using inference rules and
proof obligations. The specification covers the abstract syntax, static semantics,
type system, and dynamic semantics of every language construct, including SAMPLING
blocks, CONSTRAINT expressions, and ALERT triggers. This formal grounding supports
verification of model properties and opens a path toward theorem-prover integration
and model checking.
Reproducible code generation -- The same .dev model produces byte-identical RPi
Python and RIOT C outputs across runs and machines. The generators in
demol/transformations/m2t_rpi.py and
demol/transformations/m2t_riot.py are
deterministic and tested against golden-file snapshots in the test suite at
tests/. A model round-trip through validate and generate always produces
the same artifact set, which supports CI verification of generated code.
21 semantic validation rules -- The validator suite in
demol/lang/semantics/validators/ covers power
compatibility, pin conflicts, protocol frequency constraints, I2C address uniqueness,
user-defined CONSTRAINT expressions, ALERT trigger correctness, sampling policy
consistency, and multi-broker VIA routing. Running demol validate on a model
reports every applicable rule and its outcome with precise source locations. The
validator architecture is class-based and extensible: new rules inherit from
BaseValidator and register themselves automatically.
Open hardware library -- A library of 12 boards (Raspberry Pi, ESP32, ESP8266,
Arduino) and 32 sensors / 13 actuators / 2 power sources lives in
demol/builtin_models/. Each entry is a validated .hwd
component model that the DSL resolves at parse time via the component metamodel. The
full catalog is documented in
docs/sensors-actuators.md, with interface type, bus
protocol, voltage range, and code-generation support status for each component.
The full hardware library (boards, sensors, actuators, power sources) is in
docs/sensors-actuators.md. Each entry is a validated
.hwd component model loaded at parse time.
| Approach | Declarative model | Semantic validation | Multi-target codegen |
|---|---|---|---|
| Raw Python (per platform) | no | none | one platform per codebase |
| Arduino sketch | partial (.ino + comments) |
manual pin checks | one board per sketch |
| PlatformIO | partial (platformio.ini) |
library-level only | C++/Arduino, MicroPython |
Other tools (Zephyr / Devicetree, raw textX) cover adjacent niches; this comparison focuses on the most common prototyping path. DeMoL's combination of a formal semantic specification, a declarative model format, and multi-target code generation is distinctive among DSLs for IoT device design.
pip install demol
demol validate examples/rpi/rpi_mixed_connect.dev
demol generate rpi examples/rpi/rpi_mixed_connect.dev --output-dir ./output
demol generate svg examples/rpi/rpi_mixed_connect.dev --output-dir ./outputGenerated code and reports land in the directory passed to --output-dir. See
docs/code-generation.md for all codegen options
including RPi Python, RIOT C, SVG wiring diagrams, pin-mapping reports (MD + JSON),
JSON output, and SMAuto automation models.
The CLI also supports demol analyze power for battery runtime estimation,
demol fix for auto-correcting common validation errors, and demol diff for
semantic comparison of two model files.
A formal citation will be added here once a published artifact is available; in the meantime, please cite the GitHub release at https://github.com/robotics-4-all/demol/releases.
DeMoL's design is grounded in a formal semantic specification covering the device
model, voltage/pin/protocol constraints, and the validation engine. The full 1,800-line
mathematical specification is in docs/semantics.md, with
inference rules and proof obligations for the 21 validation checks. The semantics
document uses mathematical notation for voltage domains, pin functions, protocol
constraints, power budgets, sampling configurations, and alert trigger conditions.
| Document | Description |
|---|---|
| Language Reference | Grammar, syntax, hardware components, connections, brokers |
| Semantic Validation | Validation rules, safety checks, error examples |
| Code Generation & CLI | Generators, CLI usage, deployment artifacts, diagrams |
| Formal Semantics | Mathematical specification of the language |
| Sensors & Actuators | Hardware library reference |
| Testing | Test suite structure and coverage |
DeMoL is released under the MIT License. Copyright (c) 2023 robotics-4-all. Maintainer: Konstantinos Panayiotou (klpanagi@gmail.com). Issues and pull requests are tracked on GitHub.


