Declarative programming with MansOS

From DiLab
Jump to: navigation, search

Quick Start

Go to mansos/apps/sadlang/Blink and type

make <architecture>

in command line.

If you haven't used MansOS before, the tutorial will be helpful.

mansos/apps/sadlang/ contains Blink and other SeAdScript example applications. The file in every subfolder contains SeAdScript source code for the particular application.


SeAdScript (Sensor Application Development Script) is a declarative application specification language.

SeAdScript code is stored in files with the extension .sl.

Source file can contain the following kind of statements:

  • statements describing systems parameters (parameter), such as the routing protocol used or system's energy budget
  • statements describing actuators and other active agents (use), such as LEDs or debug output agents (use Print)
  • statements describing sensors (read), such as temperature, voltage or light sensors
  • when statements - code block that start with a conditional expressions and in turn can contain blocks of other statements
  • statements describing where the output of the system should go (output), such as serial port, radio, or network protocols

Each of the use, read, and output statements has the following syntax:

<statement> <name>, <parameterN> [<parameter1 value>],
       <parameter2> [<parameter2 value>], ..., <parameterN> [<parameterN value>];

For output statements, a list of packet fields can also be specified. This list can contain:

  • <fieldName> -- a field which correspond to a sensor in the system;
  • <fieldName> <number> -- the same, but included in the packet not once, but a number of times;
  • const<FieldName> <value> - fields with constant values (for example, some ID of the mote). The names of these fields must start with "const", and they shouldn't correspond to any sensor names;

If the list is omitted, all active sensors are included in the packet.

SeAdScript supports C-style comments. Comments start with double slash ("//") and last until the end of the line.

The language at the moment is case partially-sensitive - i.e. all keywords must be in small case, while identifiers are not case sensitive.


Specified with the use keyword.


  • Led
  • RedLed
  • GreenLed
  • BlueLed


  • period - toggle period
  • on_time - time when turned on, seconds after system's start
  • off_time - time when turned off, seconds after system's start
  • blink, blinkTwice, blinkTimes <n> - for LEDs


Specified with the read keyword.


  • Light
  • Humidity
  • Temperature (NOT SUPPORTED YET!)
  • InternalVoltage (NOT SUPPORTED YET!)
  • InternalTemperature (NOT SUPPORTED YET!)
  • ADC channels (NOT SUPPORTED YET!)


  • period - read period


Specified with the output keyword.


  • Serial port (USB)
  • Radio
  • MAC protocol
  • Network socket


  • aggregate - whether to send all in one packet or each value individually
  • baudrate - serial port baudrate, by default 38400
  • crc - whether to add checksum for packets, by default on for radio

Specifying individual fields

The following syntax is supported:

output <name> {field1, field2, ..., fieldN  <timesToInclude>, ... , constField1 value1, constaField2 value2, ...},
   <parameter1> [<parameter1 value>], ..., <parameterN> [<parameterN value>];

The field list is optional, but if present, it must be non-empty.


A boolean or integer constant can be declared by using this syntax:

const <name> <value>;

Afterwards, it can be used everywhere when and scalar value is required.


The language is not fully declarative, it has some statements with side effects. In particular, finite-state machine abstractions are built in the language.

A state of the system can be specified by state keyword. The syntax is:

state <name> [<initial value>];

States can take boolean or integer values, including symbolic constants.

Once declared, the state can be

Code example:

state temperatureCritical false;
when Sensors.Temperature > 50:
    set temperatureCritical true;
when Sensors.Temperature < 40:
    set temperatureCritical false;
when temperatureCritical:
    use RedLed, period 100ms;



when <condition>:
else when <condition>:


  • System.time - time elapsed
  • System.RTC - clock time, requires real time clock present on the mote
  • System.isDaytime - whether the current time is in day, real time clock present on the mote
  • MAC.isBaseStationNearby - whether as base station is reachable via radio

Using sensors in conditions

Each sensor present in the system can also be used in a condition:

when Voltage.value < 1234:
     use RedLed, turn_on;

A condition can also be made on sensor failing or working correctly:

when Light.failed:
     use RedLed, turn_on;
when not Light.failed:
     use GreenLed, period 1s;

Combining conditions

Two or more conditions can be combined together with logical connectives and, and or. If multiple are specified, and has higher priority. Unary not can also be used to invert a value of an condtion.

when <condition1> and not <condition>2:

Code inclusion (NOT SUPPORTED YET!)

Both C code and configuration file fragments can be included in a SeAdScript program.


Code examples

Blink with some extras:

use RedLed, period 1s, on_time 1500ms, off_time 4500ms;

Conditional blink of all three leds:

// blink red led periodically
use RedLed, period 1000ms;
// blink green led; faster at the start
when System.time < 5s:
    use GreenLed, period 100ms;
    use GreenLed, period 1000ms;
// turn on blue led once the program has started
use BlueLed, on_time 2000ms;

Light sensor reading:

read Light, period 2s;

output Serial, baudrate 38400;

Examples for syntactic sugar for conditions. Base case syntax:

when System.time < 5s:
    use BlueLed, period 100ms;


when System.time < 5s: use BlueLed, period 100ms;

Another one-liner:

use BlueLed, period 100ms, when System.time < 5s;

Else-when syntax:

when System.time < 2s:
    use BlueLed, period 100ms;
    use RedLed, period 200ms;
elsewhen System.time < 6s:
    use BlueLed, period 500ms;
    use RedLed, period 1000ms;
    use BlueLed, period 2000ms;
    use RedLed, period 3000ms;

Just turn on a led when a constant condition is true:

when 1 < 2 use BlueLed, turn_on;

A larger example:

 // do nothing, just declare that red LED will be used in the program
 use RedLed;
 // red led is on when system starts
 use RedLed, turn_on;
 // red led is turned off when a condition is fullfilled
 // (conditions are checked in the main loop at least once per minute)
 use RedLed, turn_off, when 1 < 2;
 // blue led is always on in daytime
 when System.isDaytime: use BlueLed, turn_on;
 // blue led blinks periodically in night
 when System.isDaytime = false: use BlueLed, period 1000;
 // alternatively:
 when System.isDaytime:
      use BlueLed, turn_on;
      use BlueLed, period 1000;
 // compilation error
 // when System.isDaytime = false use BlueLed, period 2000;
 // blink one time on radio rx
 use GreenLed, blinkOnce, when System.radioRx;
 // blink two times on radio rx error
 use GreenLed, blinkTwice, when System.radioRxError;

 // blink three times on radio tx
 use GreenLed, blinkTimes 3, when System.radioTx;
 // during daytime also read sensors
 when System.isDaytime
      read Light, period 2s;
      read Humidity, period 2s;
 // send data to serial
 output Serial;
 // also send data to radio
 output Radio;

Another larger example:

// define system parameters
parameter battery 2700mAh;
parameter routingProtocol GPSR;

// blink red led periodically
use RedLed, period 1000ms;

// turn green led on once the program has started
use GreenLed, on_time 2000ms;

// blink blue led; faster at the start
when System.time < 5s:
     use BlueLed, period 100ms;
     use BlueLed, period 1000ms;

// read onboard light sensor once every 10 seconds
read Light, period 10s;

// read a specific sensor once every 10 seconds
read APDS9300, period 10s;

// define a constant time value
const PERIOD 10s;

read Humidity, period PERIOD;

// by default, output all data read to serial port; the baudrate is 38400 by default, but specify it explicitly
output Serial, baudrate 38400;

// also output to radio (aggregate=yes means put all data in one packet; by default on for radio, off for serial port)
output Radio, aggregate yes;

// also output to MAC protocol, but only when a base station is detected nearby
output Network, protocol CSMA_MAC, when MAC.baseStationIsReachable;

// also output to higher level network-stack
output Network, protocol Socket, port 100;

// save light sensor values (but not humidity sensor!) to flash in case battery voltage is above 2.7V
output Flash {Light, APDS9300}, when System.voltage > 2.7V;