Contiki 2.6
|
00001 /** 00002 * \addtogroup rimeexamples 00003 * @{ 00004 */ 00005 00006 /* 00007 * Copyright (c) 2006, Swedish Institute of Computer Science. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 3. Neither the name of the Institute nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00028 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00029 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00031 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00032 * SUCH DAMAGE. 00033 * 00034 * This file is part of the Contiki operating system. 00035 * 00036 * $Id: broadcast-announcement.c,v 1.7 2010/10/11 23:43:01 adamdunkels Exp $ 00037 */ 00038 00039 /** 00040 * \file 00041 * An example announcement back-end, based on the broadcast primitive 00042 * \author 00043 * Adam Dunkels <adam@sics.se> 00044 */ 00045 00046 #include "contiki.h" 00047 00048 #include "net/rime.h" 00049 #include "net/rime/announcement.h" 00050 #include "net/rime/broadcast.h" 00051 #include "lib/random.h" 00052 #include "lib/list.h" 00053 00054 #if NETSIM 00055 #include "ether.h" 00056 #endif 00057 00058 #include <string.h> 00059 #include <stddef.h> 00060 00061 struct announcement_data { 00062 uint16_t id; 00063 uint16_t value; 00064 }; 00065 00066 #ifdef BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS 00067 #define NUM_DUPS BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS 00068 #else /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */ 00069 #define NUM_DUPS 5 00070 #endif /* BROADCAST_ANNOUNCEMENT_CONF_MAX_DUPS */ 00071 00072 #define ANNOUNCEMENT_MSG_HEADERLEN 2 00073 struct announcement_msg { 00074 uint16_t num; 00075 struct announcement_data data[]; 00076 }; 00077 00078 00079 static struct broadcast_announcement_state { 00080 struct broadcast_conn c; 00081 struct ctimer send_timer, interval_timer; 00082 clock_time_t initial_interval, min_interval, max_interval; 00083 clock_time_t current_interval; 00084 uint16_t val; 00085 } c; 00086 00087 00088 #define DEBUG 0 00089 #if DEBUG 00090 #include <stdio.h> 00091 #define PRINTF(...) printf(__VA_ARGS__) 00092 #else 00093 #define PRINTF(...) 00094 #endif 00095 00096 #define MIN(a, b) ((a)<(b)?(a):(b)) 00097 00098 /*---------------------------------------------------------------------------*/ 00099 static void 00100 send_adv(void *ptr) 00101 { 00102 struct announcement_msg *adata; 00103 struct announcement *a; 00104 00105 packetbuf_clear(); 00106 adata = packetbuf_dataptr(); 00107 adata->num = 0; 00108 for(a = announcement_list(); a != NULL && a->has_value; a = list_item_next(a)) { 00109 adata->data[adata->num].id = a->id; 00110 adata->data[adata->num].value = a->value; 00111 adata->num++; 00112 } 00113 00114 packetbuf_set_datalen(ANNOUNCEMENT_MSG_HEADERLEN + 00115 sizeof(struct announcement_data) * adata->num); 00116 00117 PRINTF("%d.%d: sending neighbor advertisement with %d announcements\n", 00118 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], adata->num); 00119 00120 if(adata->num > 0) { 00121 /* Send the packet only if it contains more than zero announcements. */ 00122 broadcast_send(&c.c); 00123 } 00124 PRINTF("%d.%d: sending neighbor advertisement with val %d\n", 00125 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00126 c.val); 00127 } 00128 /*---------------------------------------------------------------------------*/ 00129 static void 00130 adv_packet_received(struct broadcast_conn *ibc, const rimeaddr_t *from) 00131 { 00132 struct announcement_msg adata; 00133 struct announcement_data data; 00134 uint8_t *ptr; 00135 int i; 00136 00137 ptr = packetbuf_dataptr(); 00138 00139 /* Copy number of announcements */ 00140 memcpy(&adata, ptr, sizeof(struct announcement_msg)); 00141 PRINTF("%d.%d: adv_packet_received from %d.%d with %d announcements\n", 00142 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00143 from->u8[0], from->u8[1], adata.num); 00144 00145 if(ANNOUNCEMENT_MSG_HEADERLEN + adata.num * sizeof(struct announcement_data) > packetbuf_datalen()) { 00146 /* The number of announcements is too large - corrupt packet has 00147 been received. */ 00148 PRINTF("adata.num way out there: %d\n", adata.num); 00149 return; 00150 } 00151 00152 ptr += ANNOUNCEMENT_MSG_HEADERLEN; 00153 for(i = 0; i < adata.num; ++i) { 00154 /* Copy announcements */ 00155 memcpy(&data, ptr, sizeof(struct announcement_data)); 00156 announcement_heard(from, data.id, data.value); 00157 ptr += sizeof(struct announcement_data); 00158 } 00159 } 00160 /*---------------------------------------------------------------------------*/ 00161 static void 00162 adv_packet_sent(struct broadcast_conn *bc, int status, int num_tx) 00163 { 00164 } 00165 /*---------------------------------------------------------------------------*/ 00166 static void send_timer(void *ptr); 00167 00168 static void 00169 set_timers(void) 00170 { 00171 ctimer_set(&c.interval_timer, c.current_interval, send_timer, NULL); 00172 ctimer_set(&c.send_timer, random_rand() % c.current_interval, 00173 send_adv, NULL); 00174 } 00175 /*---------------------------------------------------------------------------*/ 00176 static void 00177 send_timer(void *ptr) 00178 { 00179 clock_time_t interval; 00180 00181 interval = c.current_interval * 2; 00182 00183 if(interval > c.max_interval) { 00184 interval = c.max_interval; 00185 } 00186 00187 c.current_interval = interval; 00188 00189 /* printf("current_interval %lu\n", (long unsigned int) interval);*/ 00190 00191 set_timers(); 00192 } 00193 /*---------------------------------------------------------------------------*/ 00194 static void 00195 new_announcement(uint16_t id, uint8_t has_value, 00196 uint16_t newval, uint16_t oldval, uint8_t bump) 00197 { 00198 if(bump == ANNOUNCEMENT_BUMP) { 00199 c.current_interval = c.initial_interval; 00200 set_timers(); 00201 /* } else if(newval != oldval) { 00202 c.current_interval = c.min_interval; 00203 set_timers();*/ 00204 } 00205 } 00206 /*---------------------------------------------------------------------------*/ 00207 static CC_CONST_FUNCTION struct broadcast_callbacks broadcast_callbacks = 00208 {adv_packet_received, adv_packet_sent }; 00209 /*---------------------------------------------------------------------------*/ 00210 void 00211 broadcast_announcement_init(uint16_t channel, 00212 clock_time_t initial, 00213 clock_time_t min, 00214 clock_time_t max) 00215 { 00216 broadcast_open(&c.c, channel, &broadcast_callbacks); 00217 c.initial_interval = initial; 00218 c.min_interval = min; 00219 c.max_interval = max; 00220 00221 announcement_register_observer_callback(new_announcement); 00222 } 00223 /*---------------------------------------------------------------------------*/ 00224 void 00225 broadcast_announcement_stop(void) 00226 { 00227 ctimer_stop(&c.interval_timer); 00228 ctimer_stop(&c.send_timer); 00229 broadcast_close(&c.c); 00230 } 00231 /*---------------------------------------------------------------------------*/ 00232 clock_time_t 00233 broadcast_announcement_beacon_interval(void) 00234 { 00235 return c.current_interval; 00236 } 00237 /*---------------------------------------------------------------------------*/ 00238 /** @} */