-
Notifications
You must be signed in to change notification settings - Fork 0
/
nbr_discovery.c
372 lines (316 loc) · 12 KB
/
nbr_discovery.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#include "contiki.h"
#include "dev/leds.h"
#include "board.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "core/net/rime/rime.h"
#include "dev/serial-line.h"
#include "dev/uart1.h"
#include "node-id.h"
#include "defs_and_types.h"
#include "net/netstack.h"
#include "random.h"
#include "lib/memb.h"
#include "sys/etimer.h"
#ifdef TMOTE_SKY
#include "powertrace.h"
#endif
// For temp sensing
#include "platform/native/dev/temperature-sensor.h"
#include "dev/watchdog.h"
#include "board-peripherals.h"
#include "rf-core/rf-ble.h"
#include "ti-lib.h"
#include "tmp-007-sensor.h"
/*---------------------------------------------------------------------------*/
#define TOTAL_SLOTS 25
#define SLOT_TIME (RTIMER_SECOND/64)
#define PROBE_SLOTS (TOTAL_SLOTS/2)
#define MAX_ITEMS 20 // for hashtable
#define SIZE 20 // for hashtable
#define INDOOR_RSSI_THRESHOLD -63 // for indoor setting
#define OUTDOOR_RSSI_THRESHOLD -70 // for outdoor setting
#define ACTIVE_RSSI_THRESHOLD INDOOR_RSSI_THRESHOLD // for entry into 3m radius
#define MAINTENANCE_FREQ 3 // maintenance per number of anchor slots
#define TEMP_THRESHOLD 27 // for entry into 3m radius
/*---------------------------------------------------------------------------*/
// duty cycle = WAKE_TIME / (WAKE_TIME + SLEEP_SLOT * SLEEP_CYCLE)
/*---------------------------------------------------------------------------*/
// sender timer
static struct rtimer rt;
static struct pt pt;
/*---------------------------------------------------------------------------*/
static data_packet_struct received_packet;
static data_packet_struct data_packet;
static int active_rssi_threshold;
unsigned long curr_timestamp;
/*---------------------------------------------------------------------------*/
static int curr_slot_index = 1;
static int permutation_arr_index = 0;
static int permutation_arr[PROBE_SLOTS];
static int debug = 0;
static int maintenance_flag = 0;
/*---------------------------------------------------------------------------*/
// Get a random permutation for the active probing slots
void populate_permuation_arr();
/*---------------------------------------------------------------------------*/
PROCESS(temperature_sensing_process, "temperature sensing process");
PROCESS(cc2650_nbr_discovery_process, "cc2650 neighbour discovery process");
AUTOSTART_PROCESSES(&temperature_sensing_process, &cc2650_nbr_discovery_process);
/*---------------------------------------------------------------------------*/
/* HELPER HASHTABLE IMPLEMENTATION */
// represents an encountered node
struct TrackedNode {
int node_id;
unsigned long first_seen; // first seen timestamp
unsigned long last_seen; // last seen timestamp
int exposed; // 1 if exposed for >30s, 0 otherwise
};
struct TrackedNode* hashArray[SIZE]; // hashtable
struct TrackedNode* dummyItem; // for empty slots in hashtable
// generate simple hashcode per node_id as minimal clashes expected
int hashCode(int key) {
return key % SIZE;
}
// search for a node_id in the hashtable
struct TrackedNode *search(int node_id) {
int hashIndex = hashCode(node_id);
// search the hashArray
while(hashArray[hashIndex] != NULL) {
if(hashArray[hashIndex]->node_id == node_id) {
return hashArray[hashIndex]; // found!
}
++hashIndex; // search the next position
hashIndex %= SIZE; // wraparound
}
return NULL;
}
// insert a <node_id, TrackedNode> pair into the hashtable
void insert(int node_id, uint16_t first_seen) {
MEMB(dummy_mem, struct TrackedNode, MAX_ITEMS);
struct TrackedNode *item;
item = memb_alloc(&dummy_mem);
item->node_id = node_id;
item->first_seen = first_seen;
item->last_seen = first_seen;
item->exposed = 0;
// get a hash index for this node_id
int hashIndex = hashCode(node_id);
// find an available position for this entry
while(hashArray[hashIndex] != NULL && hashArray[hashIndex]->node_id != -1) {
++hashIndex;
hashIndex %= SIZE; // wraparound
}
hashArray[hashIndex] = item;
if (debug) printf("Successfully added node with node ID: %d\n", node_id);
}
// delete an item from the hashtable
struct TrackedNode* delete(struct TrackedNode* item) {
int node_id = item->node_id;
int hashIndex = hashCode(node_id);
while(hashArray[hashIndex] != NULL) {
if(hashArray[hashIndex]->node_id == node_id) {
struct TrackedNode* temp = hashArray[hashIndex];
// dummify this position in the hashArray
dummyItem->node_id = -1;
hashArray[hashIndex] = dummyItem;
return temp;
}
++hashIndex;
hashIndex %= SIZE; // wraparound
}
return NULL;
}
// display the hashmap for debugging purposes
void display() {
int i = 0;
for(i = 0; i<SIZE; i++) {
if(hashArray[i] != NULL)
printf(" (%d,%d,%d)",hashArray[i]->node_id,hashArray[i]->first_seen,hashArray[i]->last_seen);
else
printf(" ~~ ");
}
printf("\n");
}
/*---------------------------------------------------------------------------*/
static void
broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from)
{
memcpy(&received_packet, packetbuf_dataptr(), sizeof(data_packet_struct));
int RSSI_reading = packetbuf_attr(PACKETBUF_ATTR_RSSI);
if (debug) printf("Rcv pkt RSSI: %d\n", (signed short) RSSI_reading);
// check if RSSI reading exceeds threshold
if ((signed short) RSSI_reading > active_rssi_threshold) {
if (debug) printf("%3lu.%03lu DETECT %lu with RSSI: %d\n", curr_timestamp / CLOCK_SECOND, ((curr_timestamp % CLOCK_SECOND)*1000) / CLOCK_SECOND, received_packet.src_id, (signed short)RSSI_reading);
unsigned long node_encounter_time = curr_timestamp / CLOCK_SECOND;
// insert or update node in hashtable
struct TrackedNode* this_tracked_node = search(received_packet.src_id);
if (this_tracked_node == NULL) {
printf("%3lu.%03lu DETECT %lu\n", curr_timestamp / CLOCK_SECOND, ((curr_timestamp % CLOCK_SECOND)*1000) / CLOCK_SECOND, received_packet.src_id);
// insert into hashtable
insert(received_packet.src_id, node_encounter_time);
} else {
// update node stats
this_tracked_node->last_seen = node_encounter_time;
// check if the 30s window is exceeded
if ((node_encounter_time - this_tracked_node->first_seen >= 30) &&
(this_tracked_node->exposed == 0)) {
printf("%3lu.%03lu !! CLOSE PROXIMITY FOR 30s !! NODE: %d\n",
curr_timestamp / CLOCK_SECOND,
((curr_timestamp % CLOCK_SECOND)*1000) / CLOCK_SECOND,
this_tracked_node->node_id);
// set node as exposed for 30s
this_tracked_node->exposed = 1;
}
}
}
}
static const struct broadcast_callbacks broadcast_call = {broadcast_recv};
static struct broadcast_conn broadcast;
/*---------------------------------------------------------------------------*/
char sender_scheduler(struct rtimer *t, void *ptr) {
static uint16_t i = 0;
static int NumSleep=0;
PT_BEGIN(&pt);
if (debug) {
curr_timestamp = clock_time();
printf("Start clock %lu ticks, timestamp %3lu.%03lu\n", curr_timestamp, curr_timestamp / CLOCK_SECOND, ((curr_timestamp % CLOCK_SECOND)*1000) / CLOCK_SECOND);
}
while(1){
// radio on
NETSTACK_RADIO.on();
for(i = 0; i < NUM_SEND; i++){
data_packet.seq++;
curr_timestamp = clock_time();
data_packet.timestamp = curr_timestamp;
if (debug) {
printf("Send seq# %lu @ %8lu ticks %3lu.%03lu\n", data_packet.seq, curr_timestamp, curr_timestamp / CLOCK_SECOND, ((curr_timestamp % CLOCK_SECOND)*1000) / CLOCK_SECOND);
}
packetbuf_copyfrom(&data_packet, (int)sizeof(data_packet_struct));
broadcast_send(&broadcast);
if(i != (NUM_SEND - 1)){
rtimer_set(t, RTIMER_TIME(t) + SLOT_TIME, 1, (rtimer_callback_t)sender_scheduler, ptr);
PT_YIELD(&pt);
}
}
// radio off
NETSTACK_RADIO.off();
int nxt_slot_index;
// the node is awake either during the anchor slot or the active probing slot,
if (curr_slot_index != 1) {
nxt_slot_index = 1;
} else {
// run maintenance based on MAINTENANCE_FREQ
int i = 0;
maintenance_flag += 1;
if (maintenance_flag % MAINTENANCE_FREQ == 0) {
for (i=0; i<SIZE; i++) {
if (hashArray[i] != NULL && hashArray[i]->node_id != -1) {
if ((curr_timestamp/CLOCK_SECOND) - hashArray[i]->last_seen >= 30) {
printf("%3lu.%03lu LEAVE %d\n", (curr_timestamp / CLOCK_SECOND)-30, ((curr_timestamp % CLOCK_SECOND)*1000) / CLOCK_SECOND, hashArray[i]->node_id);
printf("NODE: %d CONTACT TIME: %lu s\n", hashArray[i]->node_id, (hashArray[i]->last_seen)-(hashArray[i]->first_seen));
delete(hashArray[i]);
}
}
}
}
// display(); // for debugging
nxt_slot_index = permutation_arr[permutation_arr_index];
permutation_arr_index = (permutation_arr_index + 1) % (PROBE_SLOTS);
}
int slot_diff = nxt_slot_index - curr_slot_index - 1;
NumSleep = (slot_diff >= 0) ? slot_diff : (TOTAL_SLOTS + slot_diff);
if (debug) {
printf(" Sleep for %d slots \n", NumSleep);
}
curr_slot_index = nxt_slot_index;
// NumSleep should be a constant or static int
for(i = 0; i < NumSleep; i++){
rtimer_set(t, RTIMER_TIME(t) + SLOT_TIME, 1, (rtimer_callback_t)sender_scheduler, ptr);
PT_YIELD(&pt);
}
}
PT_END(&pt);
}
/*---------------------------------------------------------------------------*/
// this process runs at the start to determine RSSI threshold based on temperature
PROCESS_THREAD(temperature_sensing_process, ev, data)
{
static struct etimer etimer;
PROCESS_BEGIN();
SENSORS_ACTIVATE(hdc_1000_sensor);
while(1) {
etimer_set(&etimer, CLOCK_SECOND);
PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
int temp;
temp = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP);
if(temp == CC26XX_SENSOR_READING_ERROR) {
continue; // sensor still warming up, or error
}
// set the appropriate RSSI threshold
if (temp/100 > TEMP_THRESHOLD) {
active_rssi_threshold = OUTDOOR_RSSI_THRESHOLD;
printf("Temp: %d.%02d C, Outdoor RSSI threshold of %d will be used\n",
temp/100,
temp%100,
OUTDOOR_RSSI_THRESHOLD);
} else {
active_rssi_threshold = INDOOR_RSSI_THRESHOLD;
printf("Temp: %d.%02d C, Indoor RSSI threshold of %d will be used\n",
temp/100,
temp%100,
INDOOR_RSSI_THRESHOLD);
}
break;
}
SENSORS_DEACTIVATE(hdc_1000_sensor);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc2650_nbr_discovery_process, ev, data)
{
PROCESS_EXITHANDLER(broadcast_close(&broadcast);)
PROCESS_BEGIN();
random_init(54222 + node_id);
// get probing permuation
populate_permuation_arr();
#ifdef TMOTE_SKY
powertrace_start(CLOCK_SECOND * 5);
#endif
broadcast_open(&broadcast, 129, &broadcast_call);
// for serial port
#if !WITH_UIP && !WITH_UIP6
uart1_set_input(serial_line_input_byte);
serial_line_init();
#endif
printf("CC2650 neighbour discovery\n");
printf("Node %d will be sending packet of size %d Bytes\n", node_id, (int)sizeof(data_packet_struct));
// radio off
NETSTACK_RADIO.off();
// initialize data packet
data_packet.src_id = node_id;
data_packet.seq = 0;
// start sender in one millisecond.
rtimer_set(&rt, RTIMER_NOW() + (RTIMER_SECOND / 1000), 1, (rtimer_callback_t)sender_scheduler, NULL);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
void populate_permuation_arr() {
int random_index, i;
for (i = 2; i <= PROBE_SLOTS + 1; i++) {
do {
random_index = random_rand() % PROBE_SLOTS;
} while (permutation_arr[random_index] != 0);
permutation_arr[random_index] = i;
}
if (debug) {
// print out the active probe permutation
printf("Permutation is");
for (i = 0; i < PROBE_SLOTS; i++) {
printf(" %d", permutation_arr[i]);
}
printf("\n");
}
}
/*---------------------------------------------------------------------------*/