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 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;