Difference between revisions of "Declarative programming with MansOS"
(5 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | = Quick Start = | ||
+ | |||
+ | Go to ''mansos/apps/sadlang/Blink'' and type | ||
+ | make <architecture> | ||
+ | in command line. | ||
+ | |||
+ | If you haven't used MansOS before, the [[MansOS_tutorial | tutorial]] will be helpful. | ||
+ | |||
+ | ''mansos/apps/sadlang/'' contains Blink and other SeAdScript example applications. The file ''main.sl'' in every subfolder contains SeAdScript source code for the particular application. | ||
+ | |||
= Overview = | = Overview = | ||
Line 10: | Line 20: | ||
* statements describing sensors (<code>read</code>), such as temperature, voltage or light sensors | * statements describing sensors (<code>read</code>), such as temperature, voltage or light sensors | ||
* <code>when</code> statements - code block that start with a conditional expressions and in turn can contain blocks of other statements | * <code>when</code> 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 (<code> | + | * statements describing where the output of the system should go (<code>output</code>), such as serial port, radio, or network protocols |
− | Each of the <code>use</code>, <code>read</code>, and <code> | + | Each of the <code>use</code>, <code>read</code>, and <code>output</code> statements has the following syntax: |
− | <statement> <name>, <parameterN> [<parameter1 value>], <parameter2> [<parameter2 value>], ..., < | + | <statement> <name>, <parameterN> [<parameter1 value>], |
+ | <parameter2> [<parameter2 value>], ..., <parameterN> [<parameterN value>]; | ||
− | For <code> | + | For <code>output</code> 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. | SeAdScript supports C-style comments. Comments start with double slash ("//") and last until the end of the line. | ||
Line 55: | Line 70: | ||
= Outputs = | = Outputs = | ||
− | Specified with the <code> | + | Specified with the <code>output</code> keyword. |
Examples: | Examples: | ||
Line 71: | Line 86: | ||
The following syntax is supported: | 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. | ||
+ | |||
+ | = Constants (NOT SUPPORTED YET!) = | ||
+ | |||
+ | 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. | ||
+ | |||
+ | |||
+ | = States (NOT SUPPORTED YET!) = | ||
− | In | + | 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; | ||
= Conditions (NOT SUPPORTED YET!) = | = Conditions (NOT SUPPORTED YET!) = | ||
Line 83: | Line 125: | ||
statement1; | statement1; | ||
statement2; | statement2; | ||
− | + | else when <condition>: | |
statement1; | statement1; | ||
statement2; | statement2; | ||
end | end | ||
− | + | Conditions: | |
* System.time - time elapsed | * System.time - time elapsed | ||
* System.RTC - clock time, requires real time clock present on the mote | * 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 | * 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 | * 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 <code>and</code>, and <code>or</code>. If multiple are specified, <code>and</code> has higher priority. Unary <code>not </code> can also be used to invert a value of an condtion. | ||
+ | |||
+ | when <condition1> and not <condition>2: | ||
+ | statement1; | ||
+ | |||
+ | = Code inclusion (NOT SUPPORTED YET!) = | ||
+ | |||
+ | Both C code and configuration file fragments can be included in a SeAdScript program. | ||
+ | |||
+ | ... | ||
= Code examples = | = Code examples = | ||
Blink with some extras: | Blink with some extras: | ||
− | use RedLed, period 1s, | + | use RedLed, period 1s, on_time 1500ms, off_time 4500ms; |
Conditional blink of all three leds: | Conditional blink of all three leds: | ||
Line 108: | Line 175: | ||
use GreenLed, period 1000ms; | use GreenLed, period 1000ms; | ||
// turn on blue led once the program has started | // turn on blue led once the program has started | ||
− | use BlueLed, | + | use BlueLed, on_time 2000ms; |
Light sensor reading: | Light sensor reading: | ||
read Light, period 2s; | read Light, period 2s; | ||
− | + | output Serial, baudrate 38400; | |
Examples for syntactic sugar for conditions. Base case syntax: | Examples for syntactic sugar for conditions. Base case syntax: | ||
Line 185: | Line 252: | ||
// send data to serial | // send data to serial | ||
− | + | output Serial; | |
// also send data to radio | // also send data to radio | ||
− | + | output Radio; | |
</pre> | </pre> | ||
Line 201: | Line 268: | ||
// turn green led on once the program has started | // turn green led on once the program has started | ||
− | use GreenLed, | + | use GreenLed, on_time 2000ms; |
// blink blue led; faster at the start | // blink blue led; faster at the start | ||
Line 222: | Line 289: | ||
// by default, output all data read to serial port; the baudrate is 38400 by default, but specify it explicitly | // 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) | // 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 | // 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 | // 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 | // 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; | |
</pre> | </pre> |
Latest revision as of 14:42, 5 December 2011
Contents
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 main.sl in every subfolder contains SeAdScript source code for the particular application.
Overview
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.
Actuators
Specified with the use
keyword.
Examples:
- Led
- RedLed
- GreenLed
- BlueLed
- Print (NOT SUPPORTED YET!)
Parameters:
- 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
Sensors
Specified with the read
keyword.
Examples:
- Light
- Humidity
- Temperature (NOT SUPPORTED YET!)
- InternalVoltage (NOT SUPPORTED YET!)
- InternalTemperature (NOT SUPPORTED YET!)
- ADC channels (NOT SUPPORTED YET!)
Parameters:
- period - read period
Outputs
Specified with the output
keyword.
Examples:
- Serial port (USB)
- Radio
- MAC protocol
- Network socket
Parameters:
- 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.
Constants (NOT SUPPORTED YET!)
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.
States (NOT SUPPORTED YET!)
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;
Conditions (NOT SUPPORTED YET!)
Syntax:
when <condition>: statement1; statement2; else when <condition>: statement1; statement2; end
Conditions:
- 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: statement1;
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; else: 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; end
One-liner:
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; else: use BlueLed, period 2000ms; use RedLed, period 3000ms; end
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; else: use BlueLed, period 1000; end // 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; end // 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; else: use BlueLed, period 1000ms; end // 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;