• No se han encontrado resultados

Programa de mejora genética para prolificidad de la Rasa Aragonesa

typedef nx_struct serial_header {

nx_uint16_t dest; /* packet destination */ nx_uint16_t src; /* packet sender */

nx_uint8_t length; /* payload length, in bytes */

nx_uint8_t group; /* identifies a specific sensor network */ nx_uint8_t type; /* AM type */

} serial_header_t;

typedef nx_struct serial_packet {

serial_header_t header; nx_uint8_t data[]; } serial_packet_t;

Listing 7.1: Serial AM Packet layout

The type field is used to dispatch the payload (data[]). Serial AM packets have no footer. The dest (destination) and src (sender) fields are not directly relevant to packets exchanged over a serial connection, as the sender and destination are normally implicit. Similarly, group is not relevant: it is used to distinguish different motes participating in separate applications but sharing a physical connection. These fields are included for consistency with AM packets sent over a radio, and are used in some base station mote applications and ignored by others. For instance, in the BaseStation application that forwards radio AM packets to/from a PC (as serial AM packets):

• From BaseStation to the PC: src, dest and group are as in the received radio AM packet.

• From the PC to BaseStation: the transmitted radio AM packet has its destination set to dest, but sets its sender and group to those of the BaseStation mote.

With these choices, a PC with a BaseStation mote behaves much like a PC with a directly-attached mote radio.

Conversely, the TestSerial application (part of the standard TinyOS distribution) ignores these three fields. TestSerial is a application designed to test serial connectivity: the mote and the PC simply send each other messages containing consecutive numbers. The mote displays the low-order three bits of these numbers on its LEDs, while the PC simply prints these numbers. TestSerial uses the following simple external type to specify its message layout:

typedef nx_struct test_serial_msg {

nx_uint16_t counter; } test_serial_msg_t;

Listing 7.2: TestSerial packet layout

Serial AM packets containing a test serial msg t message are identified by an AM type field of 9. Figure 7.1 shows the resulting connection between serial packet t and test serial msg t external types (the figure does not show the lowest, packet-exchange layer as it is not specified using external types).

7.2

Using mig

The mig tool generates a class that represents a value of a given nesC nx struct M 1. This class provides methods to read, write and report properties of the fields of M . Given a mig-generated class for M , the

1

It is also possible to use mig with regular C structures, but the resulting code is mote-specific, as different motes have different endianness and different rules for laying out C structures.

101 7.2. Using mig

counter

test_serial_msg

data[]

dest src length group type=9

serial_packet_t

header

Figure 7.1: TestSerial packet layout

ff 00 02 02 42 09 00 ff x->header FF FF 00 02 02 42 09 00 03 serial_packet_t *x; x->header.dest = 0xffff; x->header.src = 2; ... ff 00 02 02 42 09 ff baseOffset = 0 dataLength = 7 data[] = 00 03 serial AM packet received on the PC 03

nesC code writing to serial_header_t header field of a serial_packet_t bytes on serial connection from mote to PC mig-generated class for serial_header_t x

Figure 7.2: Mig and External Types

net.tinyos.message package provides classes and methods that allow you to send and receive serial AM packets whose payload is a value of type M .

Mig-generated classes represent structure values using a backing array, a byte array that stores the structure value in the same representation as it has on the mote, and hence the same representation as in TinyOS packets. Figure 7.2 shows a typical situation, with a mote sending a serial AM packet to a PC. On the mote, the packet is represented by x, a pointer to a serial packet t. The representation of x is the same as the representation of the packet on the serial connection to the PC. On the PC itself, a mig-generated class uses a backing array containing the same bytes to represent a serial header t (the external type for serial AM packet headers) value.

Mig-generated classes supports all features of C structures, including bitfields, arrays, unions, and nested structures. They allow you to perform all the operations (and more) that you can do on structures in nesC programs:

• Create a new (all fields initialised to zero) structure value.

7.2. Using mig 102

• Read and write any field.

• Obtain information on a field: its offset, size, signedness, etc. • Obtain the byte array representing a particular structure value.

The classes generated by mig are subclasses of net.tinyos.message.Message, to simplify writing generic code that can handle multiple message layouts. The main public function of the Message class is to provide access to the backing array of a mig-generated class. The backing array is a slice of a Java byte[] array, specified by an offset and length. This array, offset and length are returned by the following three methods:

public byte[] dataGet(); public int baseOffset(); public int dataLength();

Listing 7.3: Backing array methods

For instance, in Figure 7.2, the mig-generated class for serial header t takes a 7-byte slice starting at offset 0 of the 9-byte array representing the whole serial AM packet. The use of a slice of a byte[] array allows a mig-generated class to represent a value stored within another mig-generated class, supporting the “casting” of part of one structure to another.

For test serial msg t, the basic constructor and methods of the mig-generated TestSerialMsg class are:2 • TestSerialMsg(): create a new (fields initialised to zero) test serial msg t value.

• static int offset counter(): Return the offset (in bytes) of the counter field in a test serial msg t structure.

• get counter(): Return the value of the counter field.

• set counter(int value): Modify the value of the counter field.

7.2.1 Sending and receiving mig-generated packets

The net.tinyos.message package provides a class MoteIF (for “mote interface”) that makes it simple to transmit and receive messages specified by a mig-generated class.

Before using MoteIF, you need to open a connection to your base station mote. This is done by calling the net.tinyos.packet.BuildSource.makePhoenix method, which takes as argument a packet source name. This packet source name specifies how you reach the base station mote (e.g., through a serial port) and all the relevant parameters (e.g., device name, baud rate, etc). In the rest of this section, we will use"serial@COM1:telosb"as our packet source, which denotes serial communication over serial port

COM1: at the normal Telos mote baud rate (115200 baud). Most Java programs that use MoteIF take a command-line argument that specifies the actual packet source. Chapter 7.4 discusses packet sources, and their motivation, in more detail.

Using MoteIF and mig, the code to transmit test serial msg t messages is quite simple, as this simplified excerpt from theTestSerial.java file shows. Transmission of consecutive packets is performed using MoteIF’s send method, which takes an object of a mig-generated class as argument:

public class TestSerial ... {

103 7.2. Using mig

private MoteIF moteIF; ...

public void sendPackets() {

int counter = 0;

// Create uninitialized TestSerialMsg

TestSerialMsg payload = new TestSerialMsg(); try {

while (true) {

System.out.println("Sending packet " + counter); payload.set_counter(counter);

moteIF.send(0, payload); // send payload to mote counter++;

try {Thread.sleep(1000);}

catch (InterruptedException exception) {} }

}

catch (IOException exception) {

System.err.println("Exception thrown when sending packets. Exiting."); System.err.println(exception);

} }

public static void main(String[] args) throws Exception { /* Open connection to the mote, and start sending packets */

PhoenixSource phoenix = BuildSource.makePhoenix("serial@COM1:telosb", null); MoteIF mif = new MoteIF(phoenix);

TestSerial serial = new TestSerial(mif); serial.sendPackets();

} }

Listing 7.4: Sending packets with mig and MoteIF

Received packets are handled following the AM “dispatch to a per-message handler” model. The registerListener method takes an object O of a mig-generated class and a handler as arguments. The object O specifies the AM type and layout, the handler must implement the net.tinyos.messages.MessageListener interface:

public interface MessageListener {

public void messageReceived(int to, Message m); }

Listing 7.5: Interface for handling received packets

When the handler is called, to is the destination address from the received packet, and m is a clone of O containing the payload of the received packet.

The resulting additions to TestSerial.javaare simply to declare a messageReceived method, and register it as the handler for test serial msg t in TestSerial’s constructor:

public class TestSerial implements MessageListener { public TestSerial(MoteIF moteIF) {

this.moteIF = moteIF;

// Register this class as a handler for test_serial_msg_t AM packets this.moteIF.registerListener(new TestSerialMsg(), this);