Skip to content

Device Modeling Language - A DSL for modeling IoT devices with automated source code generation for RaspberryPi and RiotOS

License

Notifications You must be signed in to change notification settings

robotics-4-all/demol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

image

Built with the tools and technologies:

Redis MQTT RabbitMQ
textX Python FastAPI Docker


DeMoL - A DSL for modeling IoT Devices

πŸ“œ Table of Contents

πŸ“– Overview

Device Modeling Language (DeMoL) - A DSL for modeling IoT devices.

Enables automated source code generation currently for RaspberryPi and RiotOS.

...

πŸ‘Ύ Features

Feature Summary
βš™οΈ Protocol-Agnostic
  • Protocol/Transport-level abstraction
  • Currently supports Redis, AMQP and MQTT
πŸ“„ Documentation
  • Rich documentation in various formats (YAML, TOML, Markdown)
  • Includes detailed installation commands for different package managers
  • Utilizes MkDocs for generating documentation
🧩 Modularity
  • Well-structured codebase with clear separation of concerns
  • Encourages code reusability and maintainability
πŸ“¦ Dependencies
  • Manages dependencies with Poetry and dependency lock files
  • Includes a variety of libraries for different functionalities
  • Dependency management with conda for environment setup
  • Dynamic imports of underlying transport libraries

πŸš€ Getting Started

πŸ”– Prerequisites

This project requires the following dependencies:

  • Programming Language: Python 3.7+
  • Packages: textX, jinja2
  • Package Manager: Pip

πŸ› οΈ Installation

Download this repository and either use the CLI and the API of the DSL directly from source, or in docker container.

Install from source

  1. Pull this repository locally
git clone https://github.com/lianoumaria/demol.git
  1. Create a Virtual environment (Optional Step)
python -m venv venv && source ./venv/bin/activate
  1. Install the DSL package in develop mode
python setup.py develop

πŸ“š Language Reference

The DeMoL DSL is built using the textX framework and provides a declarative approach to modeling IoT devices.

Grammar Structure

The grammar is modular and split into 5 interconnected files located in demol/grammar/:

File Purpose Key Concepts
device.tx Main device model definition DeviceModel, Connection, Settings
component.tx Board & peripheral hardware specs Board, Sensor, Actuator, Pins
communication.tx Message broker configurations AMQPBroker, MQTTBroker, RedisBroker
common.tx Common utilities FQN, Import, Comments
utils.tx Additional utilities FQN handling, Keywords

Core Concepts

The language is built around these fundamental concepts:

  • Device - Complete IoT device definition with metadata and configuration
  • Board - Microcontroller/SBC hardware (ESP32, Raspberry Pi, etc.)
  • Peripheral - External sensors and actuators (BME680, SRF04, etc.)
  • Connection - Defines how peripherals connect to boards (power + IO)
  • MessageBroker - Communication infrastructure (MQTT, AMQP, Redis)
  • Network - WiFi configuration

File Extensions:

  • .dev - Device models (complete IoT device definitions)
  • .hwd - Hardware component models (boards and peripherals)

Device Model Structure

Every .dev file follows this structure:

Metadata
    name: "DeviceName"
    description: "Device description"
    author: "author_name"
    os: Raspbian  // or RiotOS
end

Network
    ssid: "WiFi_SSID"
    passwd: "password"
    address: 192.168.1.100  // optional
    channel: "6"  // optional
end

Broker<MQTT> BrokerName
    host: "mqtt.example.com"
    port: 1883
    ssl: False
    auth:
        username: "user"
        password: "pass"
end

Components
    board: BoardModelName
    peripherals:
        - PeripheralModel(InstanceName1)
        - PeripheralModel(InstanceName2)
end

Connection
    peripheral: InstanceName1
    powerConnections:
        - board_pin -- peripheral_pin
    ioConnections:
        - type: gpio
          pin: board_pin -- peripheral_pin
    endpoint:
        topic: "device/sensor/topic"
        type: Publisher
    settings:
        - setting_name: type = value
end

Metadata Block

Describes the device and target platform:

Metadata
    name: "SmartSensor"
    description: "Environmental monitoring sensor"
    author: "developer_name"
    os: Raspbian  // Raspbian or RiotOS
end

Target Operating Systems:

  • Raspbian - For Raspberry Pi devices
  • RiotOS - For embedded systems (ESP32, ESP8266, etc.)

Network Configuration

WiFi network settings:

Network
    ssid: "IoT_Network"
    passwd: "secure_password"
    address: 192.168.1.50  // optional static IP
    channel: "11"  // optional WiFi channel
end

Components

Specifies the hardware composition:

Components
    board: RaspberryPi_4B_4GB
    peripherals:
        - BME680(EnvSensor)
        - SonarSRF04(DistanceSensor)
        - WS2812(StatusLED)
end

Features:

  • Board references are resolved from the global repository in demol/builtin_models/boards/
  • Peripheral models are loaded from demol/builtin_models/peripherals/
  • Supports multi-file imports using FQN (Fully Qualified Names)
  • Named peripheral instances for easy reference in connections

Hardware Components

Board Models

Boards are defined in .hwd files and describe microcontroller/SBC specifications using the Board[Type] name syntax:

Board[RPI] RaspberryPi_4B_4GB
    operational
        vcc: 5V
        memory:
            flash: 16 gb
            ram: 4 gb
        cpu:
            cpu_family: PiArmCortex
            max_freq: 1500 mhz
            fpu: true
        wifi:
            name: wifi_0
            freq: 2.4 ghz
        bluetooth: BT5
        ioVcc: 3V3
    end
    pins
        PPIN power_5v[5V] @ 2;
        PPIN gnd_1[GND] @ 6;
        DPIN p_21[gpio,sda-1] @ 40;
        DPIN p_22[gpio,scl-1] @ 38;
    end
end

Board Types: RPI (Raspberry Pi), ESP (ESP32/ESP8266), ARDUINO

Pin Syntax:

  • PPIN - Power pins (VCC, GND)
  • DPIN - Digital/IO pins with functions

Pin Functions: gpio, adc, dac, pwm-<channel>, sda-<bus>, scl-<bus>, mosi-<bus>, miso-<bus>, sck-<bus>, cs-<bus>, tx-<bus>, rx-<bus>

Power Types: GND, 3V3, 5V, 12V

Peripheral Models (Sensors)

Sensors use the Sensor[Type] name syntax where Type indicates the sensor category and its message schema:

Sensor[Env] BME680
    operational
        vcc: 5V
        ioVcc: 3V3
        powerConsumption: 3 mW
        piTpl: "bme680"  // optional - RaspberryPi template
        riotTpl: "bme680"  // optional - RiotOS template
    end
    pins
        PPIN vcc[5V] @ 1;
        PPIN gnd[GND] @ 5;
        DPIN sda[sda-0] @ 2;
        DPIN scl[scl-0] @ 3;
    end
    attributes
        ATTR poll_period[int] = 10;
        ATTR humidity_oversample[int] = 2;
        ATTR temperature_oversample[int] = 8;
    end
end

Available Sensor Types: Distance, Temperature, Humidity, Gas, Pressure, Env, AirQuality, Light, UV, Sound, Acceleration, Gyroscope, Magnetometer, IMU, Tracker, Proximity, Motion, Presence, ADC, Current, Voltage, Power, Flow, Level, Weight, Force, Vibration, Camera, RFID, Fingerprint, GPS, Color

For complete sensor type documentation and message schemas, see SENSORS_ACTUATORS.md.

Peripheral Models (Actuators)

Actuators use the Actuator[Type] name syntax:

Actuator[ServoController] PCA9685
    operational
        vcc: 5V
        ioVcc: 5V
    end
    pins
        PPIN GND_1[GND] @ 1;
        DPIN SCL_1[scl-0] @ 2;
        DPIN SDA_1[sda-0] @ 3;
        PPIN VCC_1[5V] @ 4;
    end
    attributes
        ATTR num_servos[int] = 16;
        ATTR frequency[int] = 50;
    end
end

Available Actuator Types: MotorController, ServoController, Relay, Switch, Led, LedArray, NeoPixel, Display, LCD, OLED, Buzzer, Speaker, Stepper, DCMotor, Pump, Valve, Heater, Cooler, Fan

For complete actuator type documentation and command schemas, see SENSORS_ACTUATORS.md.

Units:

  • Memory: b, kb, mb, gb
  • Frequency: hz, khz, mhz, ghz
  • Distance: mm, cm, m
  • Power: uW, mW, W

Connections

Connections define how peripherals connect to the board through power and IO pins:

GPIO Connection

Connection
    peripheral: DistanceSensor
    powerConnections:
        - gnd_1 -- gnd
        - power_5v -- vcc
    ioConnections:
        - type: gpio
          name: trigger  // optional
          pin: p_13 -- trigger
          input: False  // optional mode
          output: True
          pullup: False
          pulldown: False
          open_drain: False
        - type: gpio
          name: echo
          pin: p_14 -- echo
    endpoint:
        topic: "sensors/distance"
        type: Publisher
end

I2C Connection

Connection
    peripheral: EnvSensor
    powerConnections:
        - gnd_1 -- GND
        - power_5v -- VCC
    ioConnections:
        - type: i2c
          name: env_i2c  // optional
          slave_address: 0x76
          pins:
              sda: p_21 -- sda
              scl: p_22 -- scl
    endpoint:
        topic: "sensors/environment"
        type: Publisher
    settings:
        - poll_period: int = 5
        - enable_gas: bool = True
end

SPI Connection

Connection
    peripheral: DisplayModule
    powerConnections:
        - gnd_1 -- GND
        - power_3v3 -- VCC
    ioConnections:
        - type: spi
          name: display_spi  // optional
          pins:
              mosi: p_23 -- mosi
              miso: p_19 -- miso
              sck: p_18 -- sck
              cs: p_5 -- cs
    endpoint:
        type: Subscriber
end

UART Connection

Connection
    peripheral: GPSModule
    powerConnections:
        - gnd_1 -- GND
        - power_5v -- VCC
    ioConnections:
        - type: uart
          name: gps_uart  // optional
          pins:
              tx: p_1 -- tx
              rx: p_3 -- rx
              baudrate: 115200
    endpoint:
        topic: "sensors/gps"
        type: Publisher
end

Endpoint Types

endpoint:
    topic: "device/sensor/data"  // optional, auto-generated if omitted
    type: Publisher  // Publisher, Subscriber, RPC, Action

Auto-generated Topics: If topic is omitted, it's generated as <device_name>.<peripheral_type>.<peripheral_msg>.<instance_name> (e.g., mydevice.sensor.env.mysensor)

Connection Settings

Define peripheral-specific runtime configurations:

settings:
    - poll_rate: int = 10
    - threshold: float = 25.5
    - sensor_name: str = "BME680"
    - enable_filter: bool = True
    - thresholds: list = [10, 20, 30, 40]
    - config: dict = {
        timeout: int = 5000,
        retry: bool = True,
        max_attempts: int = 3
      }
end

Setting Types: int, float, str, bool, list, dict

Message Brokers

DeMoL supports three message broker types:

MQTT Broker

Broker<MQTT> MyMqttBroker
    host: "mqtt.example.com"
    port: 1883
    ssl: False
    basePath: "/mqtt"  // optional
    webPath: "/ws"  // optional
    webPort: 8080  // optional
    auth:
        username: "sensor_client"
        password: "secure_pass"
end

AMQP Broker

Broker<AMQP> MyAmqpBroker
    host: "rabbitmq.example.com"
    port: 5672
    vhost: "/"  // optional
    topicExchange: "amq.topic"  // optional
    rpcExchange: "amq.rpc"  // optional
    ssl: False
    auth:
        username: "guest"
        password: "guest"
end

Redis Broker

Broker<Redis> MyRedisBroker
    host: "redis.example.com"
    port: 6379
    db: 0  // optional
    ssl: False
    auth:
        username: "default"
        password: "redis_pass"
end

Authentication Methods:

  • Username/Password: auth: username: "user" password: "pass"
  • API Key: auth: key: "api_key_value"
  • Certificate: auth: cert: "cert_string" or certPath: "/path/to/cert"

Complete Example

Here's a complete device model demonstrating all features:

Metadata
    name: "SmartEnvironmentMonitor"
    description: "Multi-sensor environmental monitoring device"
    author: "john_doe"
    os: Raspbian
end

Network
    ssid: "IoT_Network"
    passwd: "secure_password"
end

Broker<MQTT> SmartHomeBroker
    host: "mqtt.smarthome.local"
    port: 1883
    ssl: True
    auth:
        username: "sensor_node"
        password: "node_pass"
end

Components
    board: RaspberryPi_4B_4GB
    peripherals:
        - BME680(EnvSensor)
        - SonarSRF04(DistanceSensor)
        - WS2812(StatusLED)
end

Connection
    peripheral: EnvSensor
    powerConnections:
        - gnd_1 -- GND
        - power_5v -- VCC
    ioConnections:
        - type: i2c
          slave_address: 0x76
          pins:
              sda: p_21 -- sda
              scl: p_22 -- scl
    endpoint:
        topic: "home/environment/living_room"
        type: Publisher
    settings:
        - poll_period: int = 5
        - humidity_oversample: int = 2
        - pressure_oversample: int = 4
        - temperature_oversample: int = 8
end

Connection
    peripheral: DistanceSensor
    powerConnections:
        - gnd_2 -- gnd
        - power_5v -- vcc
    ioConnections:
        - type: gpio
          name: trigger
          pin: p_23 -- trigger
        - type: gpio
          name: echo
          pin: p_24 -- echo
    endpoint:
        topic: "home/distance/entrance"
        type: Publisher
end

Connection
    peripheral: StatusLED
    powerConnections:
        - gnd_3 -- GND
        - power_5v -- VCC
    ioConnections:
        - type: gpio
          name: LedControl
          pin: GPIO10 -- DIN
    endpoint:
        type: Subscriber
    settings:
        - colors: list = ['0xFF0000', '0x00FF00', '0x0000FF']
        - brightness: int = 128
        - num_leds: int = 12
end


## πŸ”Œ Supported Sensors & Actuators

DeMoL supports **35 sensor types** and **23 actuator types** covering a wide range of IoT applications:

### Sensor Categories

- **Environmental**: Temperature, Humidity, Pressure, Gas, Env, AirQuality, Light, UV, Sound
- **Motion & Position**: Distance, Proximity, Motion, Presence, Acceleration, Gyroscope, Magnetometer, IMU, Tracker
- **Specialized**: ADC, Current, Voltage, Power, Flow, Level, Weight, Force, Vibration
- **Smart**: Camera, RFID, Fingerprint, GPS, Color

### Actuator Categories

- **Basic**: MotorController, ServoController, Relay, Switch
- **Display & Light**: Led, LedArray, NeoPixel, Display, LCD, OLED
- **Sound**: Buzzer, Speaker
- **Advanced**: Stepper, DCMotor, Pump, Valve, Heater, Cooler, Fan

### Message Schemas

Each sensor and actuator type has a defined message schema for standardized communication:

**Example Sensor Message (Environmental):**
```json
{
  "temperature": 23.5,
  "humidity": 65.2,
  "pressure": 1013.25,
  "gas": 450.0,
  "timestamp": 1638360000000
}

Example Actuator Command (NeoPixel):

{
  "leds": [
    {"index": 0, "r": 255, "g": 0, "b": 0},
    {"index": 1, "r": 0, "g": 255, "b": 0}
  ],
  "brightness": 128,
  "mode": "static",
  "timestamp": 1638360000000
}

For complete documentation of all sensor and actuator types with their message schemas, see SENSORS_ACTUATORS.md.

πŸ“ Formal Semantics

For a complete formal specification of the DeMoL language, see SEMANTICS.md, which provides:

  • Abstract Syntax: Mathematical representation of DeMoL constructs using syntactic domains and abstract syntax trees
  • Formal Grammar: Complete EBNF specification of the concrete syntax
  • Static Semantics: Well-formedness rules, type checking, and validation using inference rules
  • Operational Semantics: Runtime behavior defined via small-step transition systems covering device initialization, broker connections, GPIO/I2C/SPI/UART operations, and message passing
  • Axiomatic Semantics: Hoare logic specifications with pre/post conditions and invariants for device operations
  • Type System: Complete type judgments, typing rules, and subtyping relations
  • Verification Conditions: Safety properties (no short-circuits, voltage limits), liveness properties (message delivery, sensor readings), and correctness conditions

This formal foundation enables rigorous reasoning about device models, verified code generation, and static analysis tools.

πŸ”§ Usage

The DSL provides a command-line interface (CLI) for operating on models.

venv [I] ➜ demol --help
Usage: demol [OPTIONS] COMMAND [ARGS]...

  An example CLI for interfacing with a document

Options:
  --help  Show this message and exit.

Commands:
  gen
  validate

The gen command provides means of executing M2T transformations and provides subcommands, while the validate is used to validate input models.

To validate a device model, for example the ./examples/raspi_iot_device.dev, head to the examples directory and execute:

demol validate raspi_iot_device.dev

You should see an output similar to the below, in case of successful validation of the model.

[*] Running validation for model rpi_iot_device.dev
PowerPinConnection:
  gnd_1 -> gnd
PowerPinConnection:
  power_5v -> vcc
I2C-Connection:
  SDA: p_21 -> sda
  SCL: p_22 -> scl
[*] Validation passed!

Otherwise, the parser will raise an error:

textx.exceptions.TextXSemanticError: rpi_iot_device.dev:29:17: Unknown object "MyBME2" of class "PeripheralDef"

Development & Validation Scripts

The repository includes several utility scripts in the scripts/ directory for validation and code generation testing:

Validate Builtin Models

Validates all builtin board and peripheral models (.hwd files) to ensure they comply with the DeMoL grammar and semantics.

python scripts/validate_builtin_models.py

Generate RPI Examples

Generates Raspberry Pi code for all example models in examples/, validating the code generation pipeline.

python scripts/generate_rpi_examples.py

Validate Examples

Validates all example models in examples/ against the grammar.

python scripts/validate_examples.py

REST API

TODO...

πŸ“œ License

Commlib-py is protected under the MIT License. For more details, refer to the MIT LICENSE uri.


🎩 Acknowledgments

TODO ...

🌟 Star History

Star History Chart


About

Device Modeling Language - A DSL for modeling IoT devices with automated source code generation for RaspberryPi and RiotOS

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages