Wireless Sensor Network Programming by yrs83496

VIEWS: 761 PAGES: 113

									Wireless Sensor Network
       Rong Zheng
       Spring, 2007
• Overview of wireless sensor networks
• TinyOS
  – Primer
  – Installing TinyOS on Knoppix 5.1
• Basics of NesC programming
• Network programming examples
• TinyOS http://www.tinyos.net
• TinyOS 2.x tutorial http://www.tinyos.net/tinyos-
• nesC manual
• TinyOS programming
• Moteiv Tmote Sky
                Wireless Sensor Networks
                             • A network of RF transceivers,
                               sensors, actuators, micro-
                               controllers, and user interface
 Seismic Structure             devices communicating by means
                               of wireless transmissions
Interaction between ground
motion and structure &
foundation response

Emergency Medical

                                                Develop in situ observation of
                                                species and ecosystem
             Wireless Sensor Hardware

 Mica                                      Tmote                                  Imote 2
• Atmel Atmega128L 8MHz      •8MHz Texas Instruments             • PXA271 XScale® Processor at 13–
8-bit                        MSP430 microcontroller (10k         416MHz
•128kB flash memory, 4 Kb    RAM, 48k Flash)                     •Wireless MMX DSP Coprocessor
SRAM                         •250kbps 2.4GHz IEEE 802.15.4       •256kB SRAM, 32MB FLASH, 32MB
•433 or 868/916 MHz Multi-   Chipcon Wireless Transceiver        SDRAM
Channel Radio Transceiver    •Interoperability with other IEEE   •Integrated 802.15.4 Radio
38.4 kbps Data Rate Radio    802.15.4 devices                    •Multi-color Status Indicator LED
                             •Integrated ADC, DAC, Supply        •Integrated 2.4GHz Antenna, Optional
                             Voltage Supervisor, and DMA         External SMA Connector
                             Controller                          •USB Client With On-board mini-B
                             •Integrated onboard antenna with    •Rich set of Standard I/O: 3xUART,
                             50m range indoors / 125m range      2xSPI, I2C, SDIO, GPIOs
                             outdoors                            •Application Specific I/O: I2S, AC97,
                             •Optional Integrated Humidity,      Camera Chip Interface, JTAG
                             Temperature, and Light sensors
                             • 30 available in lab, 10 extra
       Wireless Sensor Hardware
           Platforms (Cont’d)


                         •Indoor localization
Cyclops: a CMOS imager   – 10.5m range
                         • Distance accuracy:
                         – 1 cm (< 3.5m dist)
                         – 2cm (>3.5m dist)
                         • Mote finds distance, PC finds location
                         • A Mica2 mote with ultrasound Rx/Tx
                         • http://cricket.csail.mit.edu/
                          4 available
• Tmote Connect Gateway Appliance
   – Linksys NSLU2 device with Moteiv's
     Tmote Connect firmware
• Support for up to 2 Tmote Sky wireless
  modules per Tmote Connect gateway
• Bi-directional connectivity to Tmote
  modules over TCP/IP using the Serial
  Forwarder wireless sensor network
  framing protocol
• Programs Tmote Sky modules remotely
  using standard Texas Instruments
  MSP430 BSL in-system programming
• 1 available
Canonical Structure of a Wireless Sensor Node
Canonical Structure of a
Wireless Sensor Node
• Micro-controller
   – “brain” of the node: control of the sensors and execution of
     communication protocols & signal processing algorithms on
     gathered data
   – Amtel’s AVR, Intel StrongArm, TI MSPxx
• Radio
• Sensor
   – Sensor transducers translate physical phenomena to
     electrical signals and can be classified as either analog or
     digital devices depending on the type of output they produce.
• Passive elements: seismic, acoustic, infrared, strain,
  barometer, humidity, temperature, etc.
• Passive Arrays: imagers (visible, IR), biochemical
• Active sensors: radar, sonar
   – High energy consumption, in contrast to passive elements
Closer Look at Tmote Sky
Look at Tmote Sky (Cont’d)
      Wireless Sensor Networks
• Each node as an embedded system
   – In-network processing possible
   – Manage per node resource
   – Programmable!
• Generally a multi-hop wireless network
   – Data gathered at sensors are relayed through radio towards the
   – Manage network resource
          TinyOS Installation
• TinyOS 1.x, Boomerang
• TinyOS 2.0 beta
  – Follow the instruction handout
       TinyOS Directory Structure
              The Make System
• From within the application’s directory:
• make (re)install.<node id> <platform>
   – <node id> is an integer between 0 and 255
   – <platform> may be tmote, mica2, mica2dot, or all
• make telosb reinstall bsl,3 # Windows example
   – Use motelist to find out which comm (-1!)
• make telosb reinstall bsl,/dev/ttyUSB2 # Linux
• make clean
• make platform docs
   – Generates documentation in <tos>/doc/nesdoc/platform
• make pc
   – Generates an executable that can be run a pc for simulation
  Compile, Install An Application
1. Program written in nesC language
  – Components and configurations
2. Use nesC compile to convert to C
3. Use native compiler for individual platforms
  •   PC, mica, telos, telosb, tmote
• Blink Application
• “is an open-source operating system designed for wireless
  embedded sensor networks”
• Why do we need an OS for sensor networks?
• What kind of OS is needed?
      Convention OS                                  TinyOS
• Process management                  •   Task, interrupts
   – Sharing CPU resource                  – Task runs to completion, FIFO
     among multiple processes              – Interrupts can preempt current
       • Scheduling                          tasks
• Memory management                   •   Harvard architecture
   – Caching, memory                       – Separate storage and signal
     allocation/protection, virtual          pathway for instruction and data
     memory                           •   No dynamic memory allocation
                                      •   No kernel, user boundary
• Disk and file system                • 
• Hardware (I/O) abstractions:        • 
                                           –   Hardware presentation layer (HPL)
  drivers                                  –   Hardware adaptation layer (HAL)
   – Interrupt handling                    –   Hardware interface layer (HIL)

• Networking                          • 
• An operating system
  – A programming environment
• A language and model (nesC)
  – A set of services
• Main design philosophy
     • Sleep as often as possible to save power
  – High concurrency, interrupt driven
TinyOS Structure
      Three-layer Hardware Abstraction
   • Hardware Interface Layer (HIL)                                   application
       – Convert the platform-specific HAL abstractions
         into hardware-independent interfaces
   • Hardware Adaptation Layer (HAL)                                     HIL
       – Uses the raw interfaces provided by the HPL to
         build useful abstractions
       – Exposes the “best” possible abstraction for the
         given hardware without compromising efficiency                 HAL
         for convenience
   • Hardware Presentation Layer (HPL)
       – Interfaces fully determined by the HW module                   HPL
         capabilities, but have a common structure
       – Stateless, does not provide substantial
         abstraction over the hardware, but hides the most
                                                                     HW platform
         hardware-dependent code

Recall Linux device abstraction?
                              More info: see TEP 2: Hardware Abstraction Architecture
               Data Memory Model
    • STATIC memory allocation!
       – No heap (malloc)
       – No function pointers
    • Global variables
       – Ex: TOS_NODE_ID
    • Local variables
       – Saved on the stack
       – Declared within a method

How is it different from Linux kernel?
       TinyOS Program Model
A graph of components
• Separation of construction and composition
• Programs are built out of components
• Each component is specified by an interface
  – Provides “hooks” for wiring components together
• Components are statically wired together
  based on their interfaces
  – Increases runtime efficiency (?)
TinyOS is a graph of components
            TinyOS Thread Model
• Tasks:
   –   Time flexible
   –   Longer background processing jobs
   –   Atomic with respect to other tasks (single threaded)
   –   Preemptable by hardware interrupt
• Events:
   –   Time critical
   –   Shorter duration (hand off to task if need be)
   –   Interrupts task
   –   Last-in first-out semantics (no priority among events)
           TinyOS Scheduling
•   Two level scheduling: events and tasks
•   Scheduler is simple FIFO
•   A task cannot preempt another task
•   Events preempt tasks (higher priority)
isr for interrrupt service
handler routine
nesC Programming
• Basic type
  – uint8_t, uint16_t, uint32_t
  – int8_t, int16_t, int32_t
  – bool
• struct, enum
• nx_struct
  – Network byte ordering
  – Alignment on byte boundaries
              An In-depth Look at Blink
A nesC application
consists of one or
more components,
wired together to
form a runnable
                     configuration Blink {
                     implementation {
                       components MainC, BlinkM, LedsC;
                         components new TimerMilliC() as Timer0;
                         components new TimerMilliC() as Timer1;
                         components new TimerMilliC() as Timer2;

                         BlinkC.Timer0 -> Timer0;
                         BlinkC.Timer1 -> Timer1;   Every nesC application has
                         BlinkC.Timer2 -> Timer2;   a single top-level
                         BlinkC.Leds -> LedsC;      configuration that specifies
                     }                              the set of components in the
                                                    application and how they
                                                    connect one another.

• a single box is a module and
• a double box is a configuration.
• dashed border lines denote that a component is a
  generic component
• ovals denote interfaces that a component provides or

                   BlinkM Implementation
                          module BlinkC
                            uses interface Timer<TMilli>   as Timer0;   A module is a nesC
                            uses interface Timer<TMilli>   as Timer1;   component consisting
                            uses interface Timer<TMilli>   as Timer2;   of application code in a
                            uses interface Leds;
                            uses interface Boot;                        C-like syntax.
                            event void Boot.booted()
                              call Timer0.startPeriodic(   250 );
                              call Timer1.startPeriodic(   500 );
                              call Timer2.startPeriodic(   1000 );
A module can                }
•Can provide command
(called by others)            event void Timer0.fired()
•Call other components’               call Leds.led0Toggle();
command                       }
•Handle events
                              event void Timer1.fired()
                                      call Leds.led1Toggle();

                              event void Timer2.fired()
                                      call Leds.led2Toggle();
          tos/interfaces/timer.nc Interface
    interface Timer {
      command void startPeriodic(uint32_t dt);
      event void fired();
    An interface is used to provide an abstract definition of the
      interaction of two components (the user and the provider).
      Similar to languages such as Java, an interface contains no
      actual code or wiring; it simply declares a set of functions:

    the provider must implement all commands and signal all events

    the user must implement all events (handler)

Socket API? Network Layering
  interface Leds {

      async   command   void   led0On();
      async   command   void   led0Off();
      async   command   void   led0Toggle();
      async   command   void   led1On();
      async   command   void   led1Off();
      async   command   void   led1Toggle();
      async   command   void   led2On();
      async   command   void   led2Off();
      async   command   void   led2Toggle();

      async command uint8_t get();
      async command void set(uint8_t val);


 Exercise: Revisit Blink Example
• Use of a single timer
  – Hint: use “call Leds.set(counter)” command
• the nesC model:
   – interfaces: (signature)              Application
       • uses                                                     D
       • provides                                                    Component
   – components:                                                        A

       • modules
       • configurations                       C

• application:= graph of                                             Component
  components                                                            B


                                                      E               configuration
          nesC Name Convention

File Name         File Type

Foo.nc            Interface

Foo.h             Header File

FooC.nc           Public Module

FooP.nc           Private Module

              Command and Events
• Event
   –   Signal keyword triggers an event
   –   Flows upward to wired component(s)
   –   Issued to higher level: provides callback
   –   A C callback function
   –   Control returns to signaling component
• Command
   –   Call keyword executes a command
   –   Flows down the configuration hierarchy
   –   Issued to lower level: uses library code
   –   Just a C function call -parameters on stack
   –   Control returns to caller
• Implemented under the keyword “command”
• Invoked/called by “call” syntax
  – call InterfaceName.CommandName(params)
• Initiated by a “signal.”
• Handled with an Event Handler

  event void Timer0.fired()
         call Leds.led0Toggle();
• Declared before they are invoked
• No parameters (use Frame variables)
• Typical used for operations that run for a long
   ...                         task void TskName {
     post TskName();           ...
   ...                         }
                 Naming Scope
• nesC components use a purely local
  – Declaration of functions it implements
  – Declaration of function it calls, may have different
     names from the actual implementation
  [similar to public methods in Java]
  Component A                Component C
  …                          …
  call B                     command result_t D

           A.B                       C.D
• “Binds” the User to the Provider’s component
  via an Interface:

  “User”.interface -> “Provider”.interface

  – myApp.Timer -> FastClocker.Timer
• Or
  – myApp.Timer -> FastClocker

                                 “Timer” interface implied
        Configuration (cont’d)
• connected elements must be compatible
• 3 wiring statements in nesC:
  – endpoint1 = endpoint2 (export interfaces of
    components within the configuration out to the
    configuration’s name space)
  – endpoint1 -> endpoint2 (user -> provider)
  – endpoint1 <- endpoint2 (equivalent: endpoint2 ->
                                Wiring Example                                            provides

configuration SerialActiveMessageC {
  provides {
    interface SplitControl;
    interface AMSend[am_id_t id];
    interface Receive[am_id_t id];
    interface Packet;
    interface AMPacket;                                                                  SerialActive
    interface PacketAcknowledgements;                                                    MessageP
  uses interface Leds;
implementation {
  components new SerialActiveMessageP() as AM, SerialDispatcherC;
  components SerialPacketInfoActiveMessageP as Info, MainC;                            SerialPacketInfo
 MainC.SoftwareInit -> SerialDispatcherC;
 Leds = SerialDispatcherC;
 SplitControl = SerialDispatcherC;

 AMSend = AM;
 Receive = AM;                                                                     SerialDispatcherC
 Packet = AM;
 AMPacket = AM;
 PacketAcknowledgements = AM;

 AM.SubSend ->                                                                              MainC
 AM.SubReceive ->

   SerialDispatcherC.SerialPacketInfo[TOS_SERIAL_ACTIVE_MESSAGE_                             Leds
   ID] -> Info;
•   Component is wired to multiple destinations
•   Commands and Events will flow between all connected components
•   Order is not guaranteed
    configuration BaseStationC {

    implementation {
              components MainC, BaseStationP, LedsC;
              BaseStationP.RadioControl -> Radio;
              BaseStationP.SerialControl -> Serial;

            configuration BaseStationP {
              uses {
                      interface SplitControl as SerialControl;
                      interface SplitControl as RadioControl;
Split Phase Operations
               Split Phase Use
•   Variable Duration processes
    – Hardware I/O Operations
      •   ADC Start Conversion –> Data Ready
    – Slow devices
      •   Flash Memory –Write Buffer –> Done

•   Asynchronous or Complex Processes
    – Send a Message to Communications Stack and
      continue with operations until .sendDone
     Split Phase Example: Client Side
event void Timer0.fired() {
    if (!busy) {
      BlinkToRadioMsg* btrpkt =                                   Phase 1: start
       (BlinkToRadioMsg*)(call Packet.getPayload(&pkt, NULL));   “send” operation
      btrpkt->nodeid = TOS_NODE_ID;
      btrpkt->counter = counter;
      if (call AMSend.send(AM_BROADCAST_ADDR,&pkt, sizeof(BlinkToRadioMsg))
        busy = TRUE;
 event void AMSend.sendDone(message_t* msg, error_t err) {
    if (&pkt == msg) {
      busy = FALSE;
  }                                                        Phase 2: “send”
          Split Phase Example: Server Side
command error_t Send.send( message_t* p_msg, uint8_t len ) {

      cc2420_header_t* header = getHeader( p_msg );
      cc2420_metadata_t* metadata = getMetadata( p_msg );


      call CC2420Transmit.sendCCA( m_msg );

      return SUCCESS;

async event void CC2420Transmit.sendDone( message_t* p_msg, error_t err)
    atomic sendErr = err;
    post sendDone_task();

    task void sendDone_task() {
      error_t packetErr;
      atomic packetErr = sendErr;
      m_state = S_STARTED;
      signal Send.sendDone( m_msg, packetErr );
              Parameterized Interfaces
     • Multiple users of a component
         – One Timer component but many users with
           different event time requirements
         – When a Timer “fires” which component should be

     • How does TinyOS handle this ?
         – Parameterized interface
             • Multiple instantiations of a component’s Interface
             • Parameter specifies the specific Instance
         – Generic component

Supplement Reading: P Levis, “TinyOS Programming”, Chap 6
      Parameterized Interfaces
• A parameterized interface allows a
  component to provide multiple instances of
  an interface
• Parameterization (index) is set by a compile-
  time value
configuration HilTImerMilliC {
  provides interface Timer<TMilli>[uint8_t id];

• Total number of instances permitted may be
  limited by Implementation

     Wiring of Parameterized Interface
configuration ActiveMessageC {
  provides {
         interface AMSend[uint8_t id];
         interface Receive[uint8_t id];

configuration TestAMAppC {}
implementation {
  components MainC, TestAMC as App, LedsC;
  components ActiveMessageC;
  components new TimerMilliC();

    App.Boot -> MainC.Boot;

    App.Receive -> ActiveMessageC.Receive[240];
    App.AMSend -> ActiveMessageC.AMSend[240];
    App.SplitControl -> ActiveMessageC;
    App.Leds -> LedsC;
    App.MilliTimer -> TimerMilliC;
}                                                 Similar to the idea of protocol id
                Unique Instances
• How to make sure your instance Parameter is not
  used by some one else?
• unique(“a string”)
   – generates a unique 8-bit identifier from the string given as an
   – Multiple Components using
   –    are each guaranteed to get a signal associated with their
       specific timer settings.
• All Components must use the same “string”
                  Unique Instances
generic configuration TimerMilliC() {
  provides interface Timer<TMilli>;
implementation {
  components TimerMilliP;

  // The key to unique is based off of TimerMilliC because
  // is just a pass-through to the underlying HIL component
  Timer = TimerMilliP.TimerMilli[unique(UQ_TIMER_MILLI)];
• async Code
  – Code that can be run preemptively
  – Code that is reachable from at least one Interrupt
• sync Code
  – Command, events, or tasks only reachable from
• Any update to shared state (memory) that is
  reachable from async is a potential data race.
• By defaults, functions are sync
               async Syntax
• async attribute used to indicate command or
  event is part of an asynchronous flow
• async processes are “decoupled” by posting
  a task
  – A task is always synchronous

  async event result_t A.B() {
         post HandleTask();
         return SUCCESS;

                                   The post task “decouples”
                                   the async event
                   TOS Rules
• Hardware event handler commands and
  events must be declared with the async
  – Indicates that this code may execute
    asynchronously to Tasks and other processes.
  – nesC will check & warn if states (variables) could
    be affected (races)
• Races are avoided by
  – accessing shared data exclusively within Tasks
     • Because Tasks can’t interrupt each other
  – Use atomic statement to access shared variables
Updates to shared state are allowed:
• Atomic block
   //code is atomic –can not be interrupted
       ApplicationState= NewState;
• “atomic”is a macro that disables all interrupts
  for duration of the block {}
   – Be careful: “atomic”may impact Node performance
   Exercise: Write BlinkToRadio
Ref: http://www.tinyos.net/tinyos-

• A counter is incremented and a radio
  message is sent whenever a timer fires.
• Whenever a radio message is received, the
  three least significant bits of the counter in the
  message payload are displayed on the LEDs.
    General Steps to develop a new
1. Identify the interfaces (and components)
2. Update the module block in the xxx.nc by adding uses
   statements for the interfaces we need
3. Declare any new variables and add any needed initialization
4. Add any program logic and calls to the used interfaces we
   need for our application.
5. Implement any (non-initialization) events specified in the
   interfaces we plan on using.
6. Update the implementation block of the application
   configuration file by adding a components statement for
   each component used that provides one of the interfaces
   chosen earlier.
7. Wire the the interfaces used by the application to the
   components which provide those interfaces.
8. Test your application!
            TinyOS 2.0 Message Buffer
         #define TOSH_DATA_LENGTH 28
         typedef nx_struct message_t {
                 nx_uint8_t header[sizeof(message_header_t)];
                 nx_uint8_t data[TOSH_DATA_LENGTH];
                 nx_uint8_t footer[sizeof(message_header_t)];
                 nx_uint8_t metadata[sizeof(message_metadata_t)];
         } message_t;

More info see: http://www.tinyos.net/tinyos-2.x/doc/html/tep111.html
   TinyOS 2.0 Message Buffer
• Header   typedef struct cc2420_header_t {
                      uint8_t length;
                      uint16_t fcf;
                      uint8_t dsn;
                      uint16_t destpan;
                      uint16_t dest;
                      uint16_t src;
                      uint8_t type;
           } cc2420_header_t;

• Metadata
Exercise: Write BlinkToRadio (cont’d)

Step 1: modify Blink to use a single timer
  – Hint: use Leds.set(parameter) command
Exercise: Write BlinkToRadio (cont’d)
Step 2: Add Radio transmit
  – Create a transmit message data structure
        typedef nx_struct BlinkToRadioMsg {
                nx_uint16_t nodeid;
                nx_uint16_t counter;
        } BlinkToRadioMsg;

  – Active messsage interfaces
     • AMSend, AMPacket [TOS_NODE_ID]
  – SplitControl
  – Decide which components to wire to
     • ActiveMessageC vs. AMSenderC
     • Make sure to handle the events its generate
  – Test with BaseStation
  • Check if the RF transmission is working
     – Put a node as a base node
         • apps/BaseStationCC2420
     – Run the listener tool
         • java net.tinyos.tools.Listen -comm serial@COM1:telos

Step 3: Add Radio receive
  – Add interface Receive
  – Add logic to process received event
  – Wiring
• Program two motes with this application. As
  long as they are both within range of each
  other, the LEDs on both will keep changing.
  If the LEDs on one (or both) of the nodes
  stops changing and hold steady, then that
  node is no longer receiving any messages
  from the other node.
• Interface to use for radio communication
  –   AMSend
  –   AMPacket
  –   AMReceive
  –   SplitControl
• Components to wire to
  – ActiveMessageC or AMSendC
• Parse of messages
  – message_t
       • Dest, src addr, meta data
  – Payload: define your own struct & cast
          Serial Communication
• Very similar to radio communication

• PC-mote communicaiton
   – java net.tinyos.tools.Listen -comm serial@COM1:telos
   – java net.tinyos.tools.SerialForwarder –port XX –comm xx
             Special Topics
• Data dissemination/collection
• Sensing
• Actuation
  Data Dissemination/Collection
• Equivalence of socket programming
  – What kind of socket interfaces are supported in
• One-to-many communication for data
  – Query
  – Flood of command
  – Software update
• Many-to-one communication
  – Collection of sensing data
  – Collection of state information
• http://www.tinyos.net/tinyos-2.x/doc/html/tutorial/lesson12.html
• http://www.tinyos.net/tinyos-2.x/doc/html/tep118.html
• http://www.tinyos.net/tinyos-2.x/doc/html/tep119.html
        • Goal: reliably deliver a piece of data to every
          node in the network
        • Underlying idea*
              – A node broadcast a summary to local neighbors
              – A node remains quiet if it hears an identical
              – A node broadcast an update if it hears an older

*Philip Levis, Neil Patel, David Culler, and Scott Shenker. "Trickle: A Self-Regulating Algorithm for Code
Maintenance and Propagation in Wireless Sensor Networks." In Proceedings of the First USENIX/ACM
Symposium on Networked Systems Design and Implementation (NSDI 2004).
interface DisseminationUpdate<t> {   interface DisseminationValue<t> {
  command void change(t* newVal);      command const t* get();
}                                      event void changed();

   • DisseminationUpdate is used by producers
       – The command DisseminationUpdate.change() should be
         called each time the producer wants to disseminate a new
         value, passing this new value as a parameter.
   • DisseminationValue is for consumers
       – The event DisseminationValue.changed() is signalled each
         time the disseminated value is changed (the producer has
         called change), and the command get allows to obtain this
         new value.
          Disseminator Component
generic configuration DisseminatorC(typedef t, uint16_t key) {
       provides interface DisseminationValue<t>;
       provides interface DisseminationUpdate<t>;

  • Key should be unique for each “value” to be
      – Hand coded
      – Unique
      – May still have key collision problem!
EasyDisseminationAppC.nc Example

• Goal:
  – A base node with ID 0 has timer, upon expiration
    of the timer, it increments its counter value and
    disseminate this information to others

 CFLAGS += -I$(TOSDIR)/lib/net

 include $(MAKERULES)
• Use a BaseStationCC2420 node to sniff the
  communication from disseminator nodes
• Goal: provides a best-effort, multihop delivery of
  packets to one of a network's tree roots
   – Forwarding of packets follows a sink tree
   – Requirement for underlying tree building and data
      • Loop detection: detecting when a node selects one of its
        descendants as a new parent.
      • Duplicate suppression: detecting and dealing with when lost
        acknowledgments are causing packets to replicate in the
        network, wasting bandwidth.
      • Link estimation: evaluating the link quality to single-hop
      • Self-interference: preventing forwarding packets along the route
        from introducing interference for subsequent packets.
• interface Send[uint8_t id] interface:
  Producer interface for generating data to be
  send to the root
• interface Receive[collection_id_t id]:
  consumer interface for root nodes that
  receive data from the network
• interface Receive as
  Snoop[collection_id_t] for sniffer
• interface Intercept[collection_id_t id] to
  receive and update a packet for in-network
            Interface (cont’d)
• interface RootControl
   interface RootControl { command error_t setRoot();
     command error_t unsetRoot();
     command bool isRoot();
• tos.lib.net.ctp.CollectionC
  configuration CollectionC {
    provides {
          interface StdControl;
          interface Send[uint8_t client];
          interface Receive[collection_id_t id];
          interface Receive as Snoop[collection_id_t];
          interface Intercept[collection_id_t id];

           interface Packet;
           interface CollectionPacket;
           interface CtpPacket;

           interface CtpInfo;
           interface CtpCongestion;
           interface RootControl;
      uses {
            interface CollectionDebug;
            interface CollectionID[uint8_t];

generic configuration CollectionSenderC(collection_id_t collectid) {
 provides {
   interface Send;
   interface Packet;
     EasyCollection Application
• Goal:
   – Each node periodically send a 0xAABB to the sink

Hint: modify the BlinkToRadio application

  CFLAGS += -I$(TOSDIR)/lib/net \
  -I$(TOSDIR)/lib/net/le \
  include $(MAKERULES)
  Packet Protocol – a.k.a why are
there so many interfaces and which
           ones to use?
    Decipher a message from serial
                src       grp

00 00 01 00 08 0A 00 17 00 00 00 00 00 08 77 07 AA BB
   typedef nx_uint8_t nx_ctp_options_t;
   typedef uint8_t ctp_options_t;
   typedef nx_struct {
     nx_ctp_options_t    options;
     nx_uint8_t          thl;
     nx_uint16_t         etx;
     nx_am_addr_t        origin;
     nx_uint8_t          originSeqNo;
     nx_collection_id_t type;
     nx_uint8_t          data[0];
   } ctp_data_header_t;

           Communication Interfaces
     • Interface Packet
        – Access to the payload
        – In designing a new protocol, you should provide
          these interfaces
interface Packet {
       command void clear(message_t* msg);
       command uint8_t payloadLength(message_t* msg);
       command void setPayLoadLength(message_t* msg, uint8_t len);
       command uint8_t maxPayloadLength();
       command void* getPayload(message_t* msg, uint8_t* len);
                   An example
                            sq    payload            Upper layer

                   header        payload             Lower layer

generic module SequenceNumber {
  provides interface Packet;
  uses interface Packet as SubPacket;
implementation {
  typedef nx_struct seq_header {
     nx_uint16_t seqNo;
  } seq_header_t;
  enum { SEQNO_OFFSET = sizeof(seq_header_t), };
  command uint8_t Packet.payloadLength(message_t* msg) {
         return SubPacket.payloadLength(msg) - SEQNO_OFFSET;
  command Packet.getPayload(message_t* msg, uint8_t* len) {
    uint8_t* payload = call SubPacket.getPayload(msg, len);
    if (len != NULL) { *len -= SEQNO_OFFSET; }
    return payload + SEQNO_OFFSET; }
       Addition Packet interfaces
• XPacket provides access to the protocol
  header/footer information
   interface CtpPacket {
     // Sets the given options bit.
     command void          setOption(message_t* msg, ctp_options_t option);

    // Clears the given options bit.
    command void          clearOption(message_t* msg, ctp_options_t option);

    // Returns TRUE iff all of the given options bits are set.
    command bool          option(message_t* msg, ctp_options_t opt);

    command uint8_t       getThl(message_t* msg);
    command void         setThl(message_t* msg, uint8_t thl);

    command uint16_t      getEtx(message_t* msg);
    command void         setEtx(message_t* msg, uint16_t etx);

     command am_addr_t getOrigin(message_t* msg);
     command void    setOrigin(message_t* msg, am_addr_t addr);
               Sending interfaces
 • Address-free send (e.g., used in CollectionC)
interface Send {
  command error_t send(message_t* msg, uint8_t len);
  command error_t cancel(message_t* msg);
  event void sendDone(message_t* msg, error_t error);
  command uint8_t maxPayloadLength();
  command void* getPayload(message_t* msg);
 • Address-specific interface
interface AMSend {
  command error_t send(am_addr_t addr, message_t* msg, uint8_t len);
  command error_t cancel(message_t* msg);
  event void sendDone(message_t* msg, error_t error);
  command uint8_t maxPayloadLength();
  command void* getPayload(message_t* msg);
     Sending interfaces (cont’d)
• Return value of send()
   – SUCCESS if the request was accepted and will issue a
     sendDone event,
   – EBUSY if the component cannot accept the request now but
     will be able to later,
   – FAIL if the stack is in a state that cannot accept requests
     (e.g., it's off).
   – ESIZE if the message is too long (??)
• event void sendDone(message_t *msg, error_t error)
   – Signaled in response to an accepted send request. msg is
     the sent buffer, and error indicates whether the send was
     successful, and if not, the cause of the failure.
                 Receive interface
interface Receive {
  event message_t* receive(message_t* msg, void* payload, uint8_t len);
  command void* getPayload(message_t* msg, uint8_t* len);
  command uint8_t payloadLength(message_t* msg);

Buffer-swap policy:
•    The handler of the event MUST return a pointer to a valid
     message buffer for the signaler to use.
•    The pointer passed as a parameter to receive MUST NOT be
     touched, used, or stored after the signaling of receive
Basic options upon a receive event:
•    Return msg without touching it.
•    Copy some data out of payload and return msg.
•    Store msg in its local frame and return a different message_t*
     for the lower layer to use.
PC-mote Communication
       Write to Serial on Mote
• Serial comm is very similar to RF comm
        Serial Message Format

• Frame byte “0x7e”
• 0x7d -> 0x7d5d; 0x7e  0x7d5e
• CRC from S – P
7e 45 00 ff ff 00 00 04 00 06 00 01 00 53 f4 9f 7e
                   PC tools
• Raw listen
  – java net.tinyos.tools.Listen -comm
  – raw_listen.c
• Serial forwarder
  – java net.tinyos.sf.SerialForwarder
Write to Mote from PC
     An Example: BlinkToURT
• Write an application that changes a 1-byte
  counter periodically and write to URT
Hint: modify your BlinkToRadio code
             More exercise
• Modify your Collection program and write the
  collected data to the URT
Write to Serial from PC
    Message Interface Generator (MIG)

   • Mig can generate Java, Python, C interface to
     message structure
 BUILD_EXTRA_DEPS += SensorToRadioMsg.class
 CLEAN_EXTRA = *.class SensorToRadioMsg.java

 SensorToRadioMsg.class: SensorToRadioMsg.java
         javac *.java

         mig java -target=null -java-classname=SensorToRadioMsg
 SensorToRadio.h S
 ensorToRadioMsg -o SensorToRadioMsg.java

 include $(MAKERULES)

Name your AM type correctly! e.g. AM_SENSORTORADIOMSG
        Parse & Display Data
• java net.tinyos.tools.MsgReader
• Hardware Abstraction Architecture
  – Hardware Presentation Layer (HPL): register level
  – Hardware Adaptation Layer (HAL): platform
  – Hardware Interface Layer (HIL): platform
    independent abstraction
• Sensors are clearly different:
  – e.g., # of bits per sample, unit of data etc.
        Platform independent sensing
Split-Phase Small Scalar I/O
interface Read<val_t> {
        command error_t read();
        event void readDone( error_t result, val_t val );
interface Write<val_t> {
        command error_t write( val_t val );
        event void writeDone( error_t result );
Split-Phase Large Scalar I/O

interface ReadRef<val_t> {
command error_t read( val_t* val );
event void readDone( error_t result, val_t* val );
interface WriteRef<val_t> {
command error_t write( val_t* val );
event void writeDone( error_t result, val_t* val );
 Who provides these interfaces?
• All sensor components should

interface Read<uint16_t>
interface ReadNow<uint16_t>
interface ReadStream<uint16_t>
interface Resource
generic configuration SensirionSht11C() {
  provides interface Read<uint16_t> as Temperature;
  provides interface Read<uint16_t> as Humidity;
implementation {
  components new SensirionSht11ReaderP();

 Temperature = SensirionSht11ReaderP.Temperature;
 Humidity = SensirionSht11ReaderP.Humidity;

 components HalSensirionSht11C;

 enum { TEMP_KEY = unique("Sht11.Resource") };
 enum { HUM_KEY = unique("Sht11.Resource") };
• Modify the BlinkToRadio example
  – Instead of incrementing the counter, read from the
    sensor and transmit over the radio

To top