29
Techniques for Protocol Programming 2013 Họ và tên sinh viên: Trịnh Phi Hùng Nguyễn Chí Nhân Nguyễn Đăng Khoa Final : Techniques for Protocol Programming (Các kĩ thuật của giao thức lập trình) Mạng cảm biến không dây thường được dùng trong các ứng dụng trong đo đạc, phát hiện, dự báo như : đo nhiệt độ, đo độ ẩm, cảm nhận độ rung … Hầu hết các nút cảm biến thường được dùng như một cơ sở dữ liệu hoặc phát hiện sự kiện trong tự nhiên, truyền thông đóng vai trò quan trọng trong việc xác định thời gian sống của các nút cảm biến, tốc độ định tuyến và bản chất của dữ liệu truyền đi trong mạng. Do đó mà chúng ta cần quan tâm tới các tính năng, các giao thức được sử dụng trong lớp phân rã IP , đó là lớp MAC. S-MAC là giao thức điều khiển truy nhập trung bình trong mạng cảm biến, nó được phát triển từ mạng 802.11

final.docx

Embed Size (px)

Citation preview

Techniques for Protocol Programming 2013

Họ và tên sinh viên:

Trịnh Phi Hùng

Nguyễn Chí Nhân

Nguyễn Đăng Khoa

Final : Techniques for Protocol Programming

(Các kĩ thuật của giao thức lập trình)

Mạng cảm biến không dây thường được dùng trong các ứng dụng trong đo

đạc, phát hiện, dự báo như : đo nhiệt độ, đo độ ẩm, cảm nhận độ rung … Hầu hết

các nút cảm biến thường được dùng như một cơ sở dữ liệu hoặc phát hiện sự kiện

trong tự nhiên, truyền thông đóng vai trò quan trọng trong việc xác định thời gian

sống của các nút cảm biến, tốc độ định tuyến và bản chất của dữ liệu truyền đi

trong mạng. Do đó mà chúng ta cần quan tâm tới các tính năng, các giao thức được

sử dụng trong lớp phân rã IP , đó là lớp MAC.

S-MAC là giao thức điều khiển truy nhập trung bình trong mạng cảm biến,

nó được phát triển từ mạng 802.11 truyền thống có ưu điểm là giảm năng lượng

tiêu thụ và khả năng tự cấu hình cho mạng. Trong sự phát triển người ta đã xác

định được 2 trong 3 nguồn tiêu tốn năng lượng và đã cải thiện nó nhằm khắc phục.

Hai trong ba nguồn tiêu thụ năng lượng được đề cấp đến dưới đây:

- Cộng tuyến : khi 2 hay nhiều nút cùng gửi một gói tin về nút trung tâm, sự

va chạm có thể xảy ra làm sai hỏng các gói tin. Vì thế phải tiêu tốn năng

lượng vô ích để truyền lại các gói tin bị hỏng.

Techniques for Protocol Programming 2013

- Nghe lỏm : trong trường hợp các nút nghe nhiều hơn những gói tin không

dùng cho mình thì nó phải tiêu tốn năng lượng hơn. Với việc sử dụng giao

thức S-MAC thì các nút sẽ ở trạng thái ngủ theo lịch trình vì thế sẽ giảm

năng lượng do nghe lỏm đi.

I. THE MEDIATION DEVICE PROTOCOL( các thiết bị trung gian)

Bây giờ ta sẽ xem xét một giao thức nổi tiếng là thiết bị hòa giải trung gian,

trong giao thức này nút A muốn truyền tải một gói tin tới nút B.

1. Nút A thông báo cho thiết bị trung gian biết bằng định kì gửi một gói tin

RTS (request-to-send), các thiết bị trung gian sẽ bắt các gói tin này. Nút A

gửi gói RTS của nó thay vì cảnh báo truy vấn nó

2. Nút A sau đó ở chế độ nhận (lắng nghe )

3. Các thiết bị trung gian phải chờ nút B truy vấn nó và sẽ gửi lại một gói tin

trả lời truy vấn nó, cho biết địa chỉ của nút A và khoảng thời gian bù đắp cho

thời gian truyền

4. Nút B bây giờ sẽ bít B sẽ nghe một lần nữa và gửi một CTS tới nút A (Bây

giờ, nút B cũng biết thời gian của nút A, và do đó biết ở thời điểm t nút A là

chế độ truyền sẽ xảy ra một lần nữa.)

5. Nút B đợi tại t’ để nhận dử liệu từ nút A.

6. Tại t” nút B sẽ gửi một gói tin báo xác nhận (nút B biết t” vì nó với nút A có

cùng chu kỳ )

7. Sau khi nút A và nút B đã truyền xong nó lại lặp lại quá trình phát đi các tín

hiệu truy vấn mới.

8. Nút B cũng khôi phục lại chu kì định kì và nó tách biệt với chu kì của nút A.

II. CONTENTION-BASED PROTOCOLS

Techniques for Protocol Programming 2013

Giao thức contention-based đề cập đến một lớp trong giao thức truyền thông,

khi đó một số quy tắc trong việc thu, phát sóng được đề xuất cho các nút cảm biến

trong mạng bắt buộc phải tuân thủ.

1. Carrier Sense Multiple Access Protocol (CSMA):

Trước khi có bất kì thông tin nào được truyền đi, nút truyền phải xác nhận

không hoạt động truyền đồng thời hay chia sẽ thông tin đang diễn ra

III. PROGRAMMING WITH LINK-LAYER PROTOCOLS( lập trình với

giao thức link-layer) :

Trong phần này chúng ta cùng xem xét các thách thức đặt ra trong việc lập trình

tại lớp liên kết dữ liệu, chúng ta sử dụng kĩ thuật ARQ (automatic repeat request –

Techniques for Protocol Programming 2013

tự động lặp lại yêu cầu). Giao thức này cố gắng gửi lại gói tin có độ tin cậy hơn

bằng cách sử dụng các báo nhận và gửi lại.

IV. AUTOMATIC REPEAT REQUEST (ARQ) PROTOCOL (giao thức

ARQ)

Ý tưởng cơ bản của giao thức ARQ có thể hiểu như sau :

Nút truyền dữ liệu sử dụng giao thức link-layer chấp nhận một gói dữ liệu, sẽ tạo

ra một gói tin mới bằng cách thêm vào một header và check sum và truyền gói tin

đã được đóng gói đó tới máy thu. Bên máy thu sẽ kiểm tra check sum có đúng

không, nếu đúng nó sẽ gửi một bản tin ACK(báo nhận) dương tới máy phát, còn

nếu kiểm tra bị sai thì máy thu sẽ gửi môt ACK âm tới máy phát. Máy phát nếu

nhận lại được một ACK dương thì nó biết là đã gửi được gói tin thành công còn

nếu nó nhận được một bản tin ACK âm thì nó sẽ gửi lại một gói tin mới cho máy

thu.

V. TRANSMITTER ROLE ( kịch bản của máy phát)

Lưu ý rằng thời gian để máy phát từ lúc gửi gói tin đến lúc thoát ra để vào chế

độ ngủ là nhất định và có giới hạn. Nếu máy phát không nhận được tín hiệu ACK

âm thì nó sẽ vẫn tiếp gửi những tin nhắn tới các nút khác trong mạng.

{

//Let p be a data packet coming from the MAC layer.

frame = Header++data packet p++check sequence (FCS);

// Construct the link layer packet

repeat forever

{

transmit (frame, to receiver node j);

// Can be done using Receive.receive( ).

parallel

{

Techniques for Protocol Programming 2013

P1: {wait-for (ack);

if (ack == positive) exit repeat loop;

else

continue; // it is negative ack

// waited long enough.

P2: {if time-out() exit repeat loop; }

} // end of parallel

} // end of repeat;

sleep( ) until woken-up( );

}

{

Receiver

node

j

{

repeat for ever

{

// Can be done using Receive.receive ( ).

p = receive-packet( );

result = checksum-test (p);

if (result == success)

{send ("success"); exit repeat loop;}

else send ("failure");

} // end of repeat loop

sleep ( ) until woken-up( );

}

}

Nút nhận(máy thu) dữ liệu sẽ vào chế độ ngủ sau khi nó gửi một tín hiệu ACK

dương (nếu check sum đúng - dữ liệu đúng), còn nếu không nó sẽ gửi tín hiệu

ACK âm cho máy phát rồi đợi máy phát gửi lại gói tin.

{

TRANSMITTER(ARQ)

FSM Model

Transmitter:

s0: frame = getFrame ( );

transmit ( frame );

go to s1;

s1:

Techniques for Protocol Programming 2013

receive( );

if acktype = +ve then {frame = getFrame( );

transmit (frame)}

else

{ transmit (frame);}

upon ack go to s1;

// Use Receive.receive( ) for this.

----------------------

global: frame, acktype = +ve;

booted( ):

frame = getFrame( ); transmit (frame)

receive( ):

actype = extract ack type( );

if acktype = + ve then {frame = getFrame( );

transmit (frame)}

else

{ transmit (frame); }

}

{

RECEIVER

fired( ):

{NULL}

receive( ):

if checksum is valid then

send +ve ack else send -ve ack;

}

Nếu tín hiệu ACK âm bị mất và bên máy phát đã quá thời gian time out, vì vậy

bên máy thu sẽ phải chờ bên máy phát gửi lại gói tin bị hỏng nhưng bên máy phát

lại không có tín hiệu ACK âm. Để kết thúc sự chờ đợi mãi mãi như vậy thì bên

máy phát sẽ thực hiện lệnh receive-packet(). Kết quả là lãng phí thời gian chờ đợi

quá nhiều làm tiêu hao thời lượng pin.

VI. ALTERNATING-BIT-BASED ARQ PROTOCOLS

Một biến thể nhỏ của giao thức trên là giao thức alternating-bit-based. Trong giao

thức này máy phát sẽ sử dụng một bít gọi là bit điều khiển, được thiết lập luân

phiên là 0 hoặc 1, để truyền tải gói tin p1, máy phát sẽ thêm vào bit 0 rồi đến gói

Techniques for Protocol Programming 2013

tin P1 khi đó gói tin mới có dạng 0:P1 sau đó truyền tới cho máy thu, đặt thời gian

s và chờ đợi tín hiệu báo nhận ACK, nếu thời gian timeout xảy ra trước khi nhận

được tín hiệu ACK từ máy thu thì máy phát sẽ gửi lại gói tin 0:P1. Khi nhận được

tín hiệu ACK từ máy thu thì máy phát sẽ gửi gói tin tiếp theo p2, khi đó ta sẽ thêm

bit điều khiển 1 vào trước p2 khi đó p2 có dạng 1:P2. Nếu máy thu nhận được gói

tin p2 và báo nhận lại thì ta truyền tiếp gói tin p3 có dạng 0:P3. Như vậy giao thức

này có thể quản lý việc truyền dữ liệu ngay cả khi mất tín hiệu ACK.

{

Transmitter i Control bit b = 0;

REPEAT: repeat for ever

{

read-packet-to-send (p);

RESEND: transmit (b:p);

PARALLEL:

P1: { wait-for-ack( );

p = p+1 mod 2;}

// Receive.receive( );

no clock necessary .

P2: { time-out( );

goto RESEND;

}

}

{

Receiver j

Control bit b = 0;

repeat for ever

{

receive-packet (p);

// Receive.receive( );

is adequate to handle this situation.

b1 = extract-control-bit (p);

d = extract-data (p);

if (b1 = b) && checksum-valid (p) then

{send-ack( ); b = b+1 mod 2;};

// No -ve ack is sent.

// Go back and wait for the

// next transmission of the same data.

Techniques for Protocol Programming 2013

}

}

{

TRANSMITTER _ alternating bit

FSM Model

Transmitter

s0: bit =1; c bit = 1;

frame = getFrame( );

transmit (frame);

// c bit is control bit (sent by receiver)

go to s1;

s1: receive( );

if c bit == bit

{ bit = bit + 1 mod 2; frame = bit: packet };

transmit (frame); upon ack: goto s1;

--------------------------

Pseudo code for nesC:

global: bit = 1, c bit = 1;

booted( ):

frame = getFrame( ); transmit (frame)

receive( ):

actype = extract acktype( );

if acktype = + ve then

{frame = getFrame( ); transmit (frame)}

else { transmit (frame);}

}

{

Receiver _ alternating bit

s0: control bit = 0; goto s1;

s1: receive( );

b1 = extract-control-bit (p);

d = extract-data (p);

if (b1 = b) & checksum-valid (p) then

{send-ack( ); b = b+1 mod 2;};

// No -ve ack is sent.

}

1. A Generalized Version of the Previous Protocol:

Techniques for Protocol Programming 2013

Chúng ta có thể khái quát các giao thức trên được trình bày ở trên bằng cách quay

lại bước truyền n và bắt đầu truyền lại chúng. Chúng tôi sẽ minh họa điều này với

một ví dụ dưới đây.

2. Ví dụ:

Đặt N= e4, ta sẽ dùng một bộ đệm lưu lại các gói tin. Bắt đầu ta sẽ thêm vào bộ

đệm 8 gói tin, thêm vào mỗi gói tin một byte(8 bit) điều khiển, do đó ta có bộ đệm

có dạng buff = 0:p0,1:p1,2p2,3p3,4p3,5p4,6p5,7p6, bắt đầu gửi gói tin từ trái trở đi

0:p0,1:p1,2:p2, . . . . (cùng một thời điểm), đồng thời nhận tín hiệu ACK gửi về và

xử lí chúng, đặt b là byte điều khiển của gói tin đã gửi. Bên máy thu giả sử luôn

gửi một tín hiệu ACK dương ( các gói tin đã gửi thành công)

{

transmitter

A

{

// Let Nmax = 4.

repeat forever{

load buffer [0:7] = 0: packet0: 1: packet1:.. .: 7: packet7;

i = -1; // j is number of packets for which acks received.

go = 1;

PAR

P1: while (i < 7 )

{

shared:

if (go) i = i +1;

send (i: packet);

go = 1;

if (i ==7) wait( );

}

P2:

wait-for-ack( );

// Receive.receive( ); should solve this problem.

j = extract-control-digit (ack);

delete j: packet j from the buffer;

shared: { i = j +1; go = 0}

Techniques for Protocol Programming 2013

} // for ever;

{

receiver B

while (1) {

receive ( from node a, packet p); // Receive.receive( ).

contorl-digit j = extract-control-digit (from packet p);

send-ack (control-digit);

data = extract-data (from packet p);

process (data);

}

}

{

Transmitter _ GENERALIZED VERSION

Transmitter:

s0: c=0, k=0; goto s1;

s1: while (k < 7) { send a[ k ]; k ++; };

s2: receive( );

cbit = extract cbit( );

if (cbit == c) then (c=c+1 mod 8)

else k = c; go to s1;

nesC code

booted( )

c=0; k =0;

transmit( );

transmit( ):

while (k < 7) {send a [ k ]; k ++; };

receive( ):

cbit = extract cbit( );

if (cbit == c) then (c=c+1 mod 8) else k = c;

call transmit( );

}

{

Receiver _ GENERALIZED VERSION

s0: receive ( from node a, packet p);

contorl-digit j = extract-control-digit (from packet p);

send-ack (control-digit);

data = extract-data (from packet p);

process (data);

}

Techniques for Protocol Programming 2013

VII. SELECTIVE REPEAT/SELECTIVE REJECT (lựa chọn lặp lại/ lựa chọn

từ chối)

Phương pháp này đơn giản hơn các phương pháp đã nêu trên đó, trong cách truyền

dữ liệu này thì cả máy phát và máy thu đều sử dụng một bộ nhớ đệm dùng để lưu

các giá trị được gửi đến mà chưa kịp truyền đi, hay nhớ các báo nhận ACK gửi

đến… Các máy phát gửi liên tiếp các gói tin cho máy thu, máy thu kết thúc nhận

dữ liệu khi có tín hiệu +ACK (ACK dương) và nếu gói bị hỏng hoặc gửi thiếu nó

sẻ gửi cho máy phát một –ACK(ACK âm), từ đó máy phát sẽ so sánh và gửi lại cái

gói tin bị hỏng theo chỉ số của báo nhận ACK tương ứng. Phương pháp này có lợi

thế hơn các phương pháp kia vì có bộ đệm nên khi có bị mất gói tin và cần gửi lại

thì máy phát sẽ lấy như bộ đệm, song do có bộ đệm nên sẽ tiêu tốn nhiều không

gian bộ nhớ hơn trong mạng, từ đó sẽ dẫn đến chi phí hạ tầng mạng tăng cao.

Transmitter A

{

bufer1 [0 .. 7 ] = 0: p0 ++ 1: p1 ++ 2:

p2 ++ ... ++ 7: p7;

send-now [ 0 .. 7 ] = 0, 1 ,.., 7;

send-next [ 0 .. 7 ] = non empty junk;

j = -1; end =0;

// initially start sending from buffer1 [ ].

while (send-next [ ] != empty)

{

PARALLEL:

{

PAR1:{

Techniques for Protocol Programming 2013

for ( i = 0, i < size; i ++)

{

i1 = send-now[i];

send (to node B, buffer1 [i1]); }

end = 1;

}

PAR2:{

while (end != 1)

{

wait-for (ack, from node B);

packet-id pid =

extract-control-byte (ack);

ack-type = extract-ack-type (ack);

if (ack-type = negative)

{ send-next [++ j] = pid; }

} // end while

send-now [ ] = send-next [ ];

size = size of send-next [ ];

} // end PAR2

} // end PARALLEL.

} // end while.

}

{

receiver B

buffer [ 0 .. 7 ] = empty;

Techniques for Protocol Programming 2013

i = 0;

while (i < 7)

{

receive (packet p, from node A);

packet-id = get-packet-id (packet p);

data = get-data (packet p);

if (packet-id == i)

{ buffer [ i ] = data; i = i + 1; send (+ve ack)}

else

send (-ve ack, i);

}

}

{

Transmitter-Selective

Repeat/Selective Reject

s0: k = 0;

s1: while (k < 7) send (a [k]); goto s2;

s2: receive( );

c = control bit( );

if ack-for (c) is -ve then send a [c];

}

{

Receiver-Selective Repeat/Selective Reject

s0: i =0;

while (i < 7)

Techniques for Protocol Programming 2013

{

receive (packet p, from node A);

packet-id = get-packet-id (packet p);

data = get-data (packet p);

if (packet-id == i)

{

buffer [i] = data;

i = i +1;

send (+ve ack)

}

else

send (-ve ack, i);

}

nesC code:

booted( ):

i = 0;

receive( ):

}

Trong một số ứng dụng thực tế, phương pháp này tỏ ra có lợi hơn

VIII. NAMING AND ADDRESSING

Trong môi trường bên ngoài thì các nút trong mạng cảm biến có thể hư hỏng bất cứ

khi nào. Vì vậy trong một WSN thì các nút phân bố trong mạng phải được gán

một địa chỉ duy nhất, việc này để dể dàng trong việc quản lí các nút trong khi phát

sinh các trường hợp mới. Ví dụ một nút trong mạng làm cầu nối(nút trung gian)

giữa hai mạng con, và nút này vì một lý do nào đó mà nó không hoạt động, khi đó

Techniques for Protocol Programming 2013

thì cả hai mạng con này sẽ bị mất kết nối, việc đó khiến cho các nút trong mạng sẽ

không hoạt động được. Trong khi để quản lí địa chỉ là một vấn đề khó khăn. Chúng

ta sẽ tìm hiểu một số kĩ thuật trong lập trình cách đặt tên và gán địa chỉ cho các nút

trong mạng.

IX. DISTRIBUTED ASSIGNMENT OF NETWORKWIDE ADDRESSES

(phân cấp và gán địa chỉ cho mạng rộng )

Đây là kĩ thuật đơn giản gán mỗi địa chỉ cho mỗi nút, tuy nhiên chi phí cho kĩ thuật

này là rất khó. Trong kĩ thuật này mỗi nút tạo ra một địa chỉ ngẫu nhiên, sau đó đặt

địa chỉ đó như là địa chỉ riêng của mình, sau đó nó sẽ phát tín hiệu để kiểm tra các

nút kế cận xem có bị trùng lặp với địa chỉ riêng không. Nếu có sự trùng lặp với địa

chỉ của nút bên cạnh thì nó sẽ cố gắng chọn một địa chỉ ngẫu nhiên rồi tiếp tục

kiểm tra với các nút bên cạnh một lần nữa. Công việc này được lặp lại cho đến khi

không còn có sự trùng lặp địa chỉ với nút bên cạnh.

module algorithm2C

{

uses interface Boot;

uses interface Random;

uses interface Leds;

uses interface AMPacket;

uses interface Packet;

uses interface AMSend;

uses interface ActiveMessageAddress as AMA;

uses interface PacketAcknowledgements;

uses interface Receive;

uses interface SplitControl as RadioCont rol;

uses interface Timer <TMilli> as Timer0;

}

implementation

{

void generateAddress( );

void broadcastAddress( );

am group t my group = 1;

Techniques for Protocol Programming 2013

am addrt myaddress;

bool conflict;

event void Boot.booted( )

{

call RadioControl.start( );

}

/**************************************************

Compute global addresss for each specific node and

test if the address is in use

**************************************************/

event void RadioCont rol.startDone (error t err)

{

// First we generate the address of the mote

generateAddress( );

// The initial address broadcast

call Timer0.startOneShot (6000);

// At this point, we can set the generated address

call AMA. setAddress (my group, my address);

}

event void AMSend.sendDone (message t* msg, error t err)

{

if (err == FAIL)

{

call Leds.led0On( );

}

}

event void Timer0.fired()

{

message t msg;

am addr t* temp;

temp = (am addr t*) call AMSend.getPayload (&msg);

temp = &my address;

call AMSend.send (0 x ffff, &msg, sizeof (am addr t));

}

/****************************************************

A simple function that randomly generates an address

for a mote

Techniques for Protocol Programming 2013

****************************************************/

void generateAddress( )

{

call Leds.set (0);

my address = (31071334523 % (call Random.rand16( )));

}

void broadcastAddress( )

{

message t msg;

am addr t* temp;

temp = (am addr t*) (call AMSend.getPayload (&msg));

*temp = call AMA.amAddress( );

call AMSend. send (0 x ffff,&msg, sizeof (am addr t));

}

async event void AMA.changed( )

{

}

event void RadioControl.stopDone (error t err)

{

}

event message t* Receive.receive (message t *msg,

void* payload,... uint8 t len)

{

am addr t broadcasted addr;

broadcasted addr = (am addr t*) payload;

Techniques for Protocol Programming 2013

call Leds.set (0); // Clear debug leds

if (*broadcasted addr ==

(call AMA.amAddress( ))) // Generate a new

// addr

{

call Leds.led0On( );

// A collision has occured

generateAddress( );

call AMA.setAddress

(my group, my address);

broadcastAddress( );

// Only broadcast new address

// after a collision

}

else

{

call Leds.led1On( ); // No collison yet

}

return msg;

}

}

Các công việc để triển khai giao thức này, một bộ giao diện sẻ được khởi động các

thành phần như: đưa ra các hệ số ngẫu nhiên, việc gửi nhận các thông tin cho các

nút kế cận, tự động hẹn giờ để phát sóng ra cho các nút lân cận, tạo ra một địa chỉ

ngẫu nhiên…

#define MOTE AM ID 10

configuration algorithm2AppC { }

implementation

{

components MainC;

Techniques for Protocol Programming 2013

components RandomC;

components LedsC;

components new AMSenderC(MOTE AM ID);

components new AMReceiverC(MOTE AM ID);

components ActiveMessageAddressC;

components algorithm2C;

components ActiveMessageC;

components new TimerMilliC( );

algorithm2C.Boot->MainC. Boot;

algorithm2C.Random->RandomC;

algorithm2C.Leds->LedsC;

algorithm2C.AMPacket->AMSenderC;

algorithm2C.Packet->AMSenderC;

algorithm2C.AMSend->AMSenderC;

algorithm2C.AMA->ActiveMessageAddressC;

algorithm2C.PacketAcknowledgements->AMSenderC;

algorithm2C.Receive->AMReceiverC;

algorithm2C.RadioControl->ActiveMessageC;

algorithm2C.Timer0->TimerMilliC;

}

void generateAddress( )

{

call Leds.set (0);

my address = (31071334523 % (c a l l Random. rand16( )));

}

Techniques for Protocol Programming 2013

void broadcastAddress( )

{

message t msg;

am addr t* temp;

temp = (am addr t*) (call AMSend. getPayload (&msg));

*temp = call AMA. amAddress( );

call AMSend. send (0 x ffff,&msg, sizeof (am addr t));

}

Ngoài ra để kiểm soát và các sự kiến xảy ra trong quá trình giao tiếp trong mạng,

khi đó ta có thể dùng nhiều hơn hai địa điểm để tạo ra các địa chỉ ngẫu nhiên và

phát sóng các địa chỉ ra các nút lân cận.

event void Boot.booted( )

{

call RadioCont rol.start( );

}

event void RadioCont rol.startDone (error t err)

{

// puts the address in my address.

generateAddress( );

// The initial address broadcast

call Timer0.startOneShot (6000);

// Check once if any one else has my address.

// If not, at this point, we can set the

generated address

call AMA.setAddress (my group, my address);

}

Địa chỉ của tôi là một biến số toàn cục trong các địa chỉ ngẫu nhiên được lưu trữ,

sau đó được phát ra cho các nút lân cận.

Ngay sau khi các thành phần được nêu trên được bật bởi lệnh RadioControl.start()

thì chúng ta sẽ thực hiện các nhiệm vụ sau đây. Đầu tiên sẽ tạo ra một địa chỉ ngẫu

Techniques for Protocol Programming 2013

nhiên và đặt vào trong biến toàn cục của tôi. Chúng ta sẽ kiểm tra tất cả các nút có

cùng địa chỉ với mình (các địa chỉ trùng lặp), các trùng lặp được bắt đầu bằng một

one-shot (monoshot) xảy ra sẻ gây ra các chậm trể (6000ms) trong chương trình

của tôi. Nếu không có sự trùng lặp thì ta thiết lập được địa chỉ riêng cho mỗi nút

trong mạng. Nhiệm vụ còn lại là chờ đợi và trả lời các truy vấn nếu có sự trùng lặp

địa chỉ.

event void Timer0.fired( )

{

message t msg;

am addr t *temp;

temp = (am addr t *) call AMSend. getPayload (&msg);

// storing the address of my address in temp.

*temp = my address;

call AMSend.send (0 x ffff, &msg, sizeof (am addr t));

}

event void AMSend. sendDone (message t *msg, error t err)

{

if(err == FAIL)

{

// If send fails, switch on red led

call Leds.led0On( );

}

}

event message t *Receive.receive(message t* msg, void*

payload, uint8 t len)

{

am addr t* broadcasted addr;

broadcasted addr = (am addr t*)payload;

call Leds.set (0); // Clear debug leds

if(*broadcasted addr == (call AMA.amAddress( )))

// Generate a new addr

{

call Leds.led0On( ); // A collision has occured

generateAddress( );

call AMA.setAddress (my group, my address);

broadcastAddress( ); // Only broadcast

Techniques for Protocol Programming 2013

new address after// a collision

}

else

{

call Leds.led1On( ); // No collison yet

}

return msg;

}

Các xung đột monoshot gây nên sự kiên fired() nơi mà chúng ta gửi gói tin tới nút

lân cận, ta thiết lập một trọng tải và lưu trữ địa chỉ của tôi như một phần của các

gói tin, sau đó gửi các gói tin đi. Sau khi gửi các gói tin nếu có bất kì báo cáo về lỗi

gửi thì chúng ta sẽ bật một đèn LED, sau này ta sẽ không cố gắng gửi lại gói tin

nữa mà nếu nhận được mốt gói tin bất kì thì ta sẽ tách lấy địa chỉ của người gửi rồi

so sánh với địa chỉ của mình để xem có bị trùng lặp không. Nếu không có trùng lặp

ta sẽ tự thiết lập và nhớ địa chỉ của mình và đánh dấu bằng cách đặt một cờ báo( từ

giờ trở đi sẽ không trả lời tin nhắn từ các nút khác gửi đến và cũng không thay đổi

địa chỉ của mình nữa. Điều này đạt được bằng thiết lập cờ báo TRUE). Tuy nhiên

nếu ta nhận thấy địa chỉ bị trùng lặp thì ta sẽ tạo ra một địa chỉ và gán đó là địa chỉ

của mình, sau đó phát đi báo cho các nút lân cận và chờ các nút đó trả lời. Ta cứ

tiếp tục như thế cho đến khi tìm thấy địa chỉ của mình. Trước khi làm xong công

việc ta cần thêm vào một số chi tiết dưới đây.

void generateAddress( )

{

call Leds. set (0);

my address = (31071334523 \% (call Random. rand16( )));

}

async event void AMA.changed( ) { }

event void RadioControl.stopDone (error t err) { }

Techniques for Protocol Programming 2013

X. IMPROVED ALGORITHMS

Bây giờ ta sẽ nói về các giải pháp để giải quyết các vấn đề được đề cập ở trên.

1. Perkin’s Solution (giải pháp Perkin’s)