Contiki 2.5
broadcast-announcement.c
Go to the documentation of this file.
1 /**
2  * \addtogroup rimeexamples
3  * @{
4  */
5 
6 /*
7  * Copyright (c) 2006, Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the Institute nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * This file is part of the Contiki operating system.
35  *
36  * $Id: broadcast-announcement.c,v 1.7 2010/10/11 23:43:01 adamdunkels Exp $
37  */
38 
39 /**
40  * \file
41  * An example announcement back-end, based on the broadcast primitive
42  * \author
43  * Adam Dunkels <adam@sics.se>
44  */
45 
46 #include "contiki.h"
47 
48 #include "net/rime.h"
49 #include "net/rime/announcement.h"
50 #include "net/rime/broadcast.h"
51 #include "lib/random.h"
52 #include "lib/list.h"
53 
54 #if NETSIM
55 #include "ether.h"
56 #endif
57 
58 #include <string.h>
59 #include <stdio.h>
60 #include <stddef.h>
61 
62 struct announcement_data {
63  uint16_t id;
64  uint16_t value;
65 };
66 
67 #ifdef BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
68 #define NUM_DUPS BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS
69 #else /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
70 #define NUM_DUPS 5
71 #endif /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */
72 
73 #define ANNOUNCEMENT_MSG_HEADERLEN 2
74 struct announcement_msg {
75  uint16_t num;
76  struct announcement_data data[];
77 };
78 
79 
80 static struct broadcast_announcement_state {
81  struct broadcast_conn c;
82  struct ctimer send_timer, interval_timer;
83  clock_time_t initial_interval, min_interval, max_interval;
84  clock_time_t current_interval;
85  uint16_t val;
86 } c;
87 
88 
89 #define DEBUG 0
90 #if DEBUG
91 #include <stdio.h>
92 #define PRINTF(...) printf(__VA_ARGS__)
93 #else
94 #define PRINTF(...)
95 #endif
96 
97 #define MIN(a, b) ((a)<(b)?(a):(b))
98 
99 /*---------------------------------------------------------------------------*/
100 static void
101 send_adv(void *ptr)
102 {
103  struct announcement_msg *adata;
104  struct announcement *a;
105 
106  packetbuf_clear();
107  adata = packetbuf_dataptr();
108  adata->num = 0;
109  for(a = announcement_list(); a != NULL && a->has_value; a = list_item_next(a)) {
110  adata->data[adata->num].id = a->id;
111  adata->data[adata->num].value = a->value;
112  adata->num++;
113  }
114 
115  packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN +
116  sizeof(struct announcement_data) * adata->num);
117 
118  PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n",
119  rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->num);
120 
121  if(adata->num > 0) {
122  /* Send the packet only if it contains more than zero announcements. */
123  broadcast_send(&c.c);
124  }
125  PRINTF("%d.%d: sending neighbor advertisement with val %d\n",
127  c.val);
128 }
129 /*---------------------------------------------------------------------------*/
130 static void
131 adv_packet_received(struct broadcast_conn *ibc, const rimeaddr_t *from)
132 {
133  struct announcement_msg adata;
134  int i;
135 
136  /* Copy number of announcements */
137  memcpy(&adata, packetbuf_dataptr(), sizeof(struct announcement_msg));
138  PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n",
140  from->u8[0], from->u8[1], adata.num);
141 
142  if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
143  /* The number of announcements is too large - corrupt packet has
144  been received. */
145  printf("adata.num way out there: %d\n", adata.num);
146  return;
147  }
148 
149  for(i = 0; i < adata.num; ++i) {
150  struct announcement_data data;
151 
152  /* Copy announcements */
153  memcpy(&data.id, &((struct announcement_msg *)packetbuf_dataptr())->data[i].id,
154  sizeof(uint16_t));
155  memcpy(&data.value, &((struct announcement_msg *)packetbuf_dataptr())->data[i].value,
156  sizeof(uint16_t));
157  announcement_heard(from,
158  data.id,
159  data.value);
160  }
161 }
162 /*---------------------------------------------------------------------------*/
163 static void
164 adv_packet_sent(struct broadcast_conn *bc, int status, int num_tx)
165 {
166 }
167 /*---------------------------------------------------------------------------*/
168 static void send_timer(void *ptr);
169 
170 static void
171 set_timers(void)
172 {
173  ctimer_set(&c.interval_timer, c.current_interval, send_timer, NULL);
174  ctimer_set(&c.send_timer, random_rand() % c.current_interval,
175  send_adv, NULL);
176 }
177 /*---------------------------------------------------------------------------*/
178 static void
179 send_timer(void *ptr)
180 {
181  clock_time_t interval;
182 
183  interval = c.current_interval * 2;
184 
185  if(interval > c.max_interval) {
186  interval = c.max_interval;
187  }
188 
189  c.current_interval = interval;
190 
191  /* printf("current_interval %lu\n", (long unsigned int) interval);*/
192 
193  set_timers();
194 }
195 /*---------------------------------------------------------------------------*/
196 static void
197 new_announcement(uint16_t id, uint8_t has_value,
198  uint16_t newval, uint16_t oldval, uint8_t bump)
199 {
200  if(bump == ANNOUNCEMENT_BUMP) {
201  c.current_interval = c.initial_interval;
202  set_timers();
203  /* } else if(newval != oldval) {
204  c.current_interval = c.min_interval;
205  set_timers();*/
206  }
207 }
208 /*---------------------------------------------------------------------------*/
210  {adv_packet_received, adv_packet_sent };
211 /*---------------------------------------------------------------------------*/
212 void
213 broadcast_announcement_init(uint16_t channel,
214  clock_time_t initial,
215  clock_time_t min,
216  clock_time_t max)
217 {
218  broadcast_open(&c.c, channel, &broadcast_callbacks);
219  c.initial_interval = initial;
220  c.min_interval = min;
221  c.max_interval = max;
222 
223  announcement_register_observer_callback(new_announcement);
224 }
225 /*---------------------------------------------------------------------------*/
226 void
227 broadcast_announcement_stop(void)
228 {
229  ctimer_stop(&c.interval_timer);
230  ctimer_stop(&c.send_timer);
231  broadcast_close(&c.c);
232 }
233 /*---------------------------------------------------------------------------*/
234 clock_time_t
235 broadcast_announcement_beacon_interval(void)
236 {
237  return c.current_interval;
238 }
239 /*---------------------------------------------------------------------------*/
240 /** @} */