Difference between revisions of "Declarative programming with MansOS"
| (One intermediate revision by the same user not shown) | |||
| Line 20: | 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>], |
<statement> <name>, <parameterN> [<parameter1 value>], |
||
<parameter2> [<parameter2 value>], ..., <parameterN> [<parameterN 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 66: | Line 70: | ||
= Outputs = |
= Outputs = |
||
Specified with the <code> |
Specified with the <code>output</code> keyword. |
||
Examples: |
Examples: |
||
| Line 82: | 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>]; |
<parameter1> [<parameter1 value>], ..., <parameterN> [<parameterN value>]; |
||
The field list is optional, but if present, it must be non-empty. |
|||
In this case, not all sensors in the system are included in the packet, but only the ones specified in the field list. Each name of non constant-valued field must correspond to a sensor active on the system. |
|||
= Constants (NOT SUPPORTED YET!) = |
|||
Also, if any fields with value are specified, then all packets are going to contain these fields and have them filled with the value specified. |
|||
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!) = |
= Conditions (NOT SUPPORTED YET!) = |
||
| Line 95: | Line 125: | ||
statement1; |
statement1; |
||
statement2; |
statement2; |
||
else when <condition>: |
|||
statement1; |
statement1; |
||
statement2; |
statement2; |
||
end |
end |
||
Conditions: |
|||
Condition: |
|||
* 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 = |
||
| Line 125: | Line 180: | ||
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 197: | 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 234: | 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 15: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 whenstatements - 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;