diff --git a/projects/WEAtHeR/Jamfile b/projects/WEAtHeR/Jamfile index d2eb26f50..3576888c6 100644 --- a/projects/WEAtHeR/Jamfile +++ b/projects/WEAtHeR/Jamfile @@ -1,5 +1,5 @@ -SubDir TOP projects weather ; +SubDir TOP projects WEAtHeR ; -Module weather : main.c : sht11 ltc4150 swtimer auto_init ; +Module WEAtHeR : main.c weather_routing.c protocol_msg_gateway.c : sht11 ltc4150 cc110x gpioint swtimer shell shell_commands posix_io uart0 auto_init rtc ; -UseModule weather ; +UseModule WEAtHeR ; diff --git a/projects/WEAtHeR/main.c b/projects/WEAtHeR/main.c index 2c248b117..878c5bba3 100644 --- a/projects/WEAtHeR/main.c +++ b/projects/WEAtHeR/main.c @@ -3,31 +3,200 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "weather_routing.h" +#include "weather_protocol.h" +#include "protocol_msg_gateway.h" + +#define SHELL_STACK_SIZE (2048) +#define PH_STACK_SIZE (2048) + +/* per default not acting as data sink */ +static uint8_t data_sink = 0; +static uint8_t data_src = 0; + +char shell_stack_buffer[SHELL_STACK_SIZE]; +char ph_stack_buffer[PH_STACK_SIZE]; + +void weather_send(char* unused); +void weather_sink(char* unused); + +shell_t shell; +const shell_command_t sc[] = { + {"sender", "Enables node as data source.", weather_send}, + {"sink", "Enables node as data sink.", weather_sink}, + {NULL, NULL, NULL}}; + +void shell_runner(void) { + shell_init(&shell, sc, uart0_readc, uart0_putc); + posix_open(uart0_handler_pid, 0); + shell_run(&shell); +} + +void weather_send(char* unused) { + if (data_src) { + data_src = 0; + puts("Disabling data source mode."); + } + else { + data_src = 1; + puts("Enabling data source mode."); + } +} + +void weather_sink(char* unused) { + if (data_sink) { + data_sink = 0; + puts("Disabling data sink mode."); + } + else { + data_sink = 1; + puts("Enabling data sink mode."); + } +} -int main(void) -{ +static void handle_packet(void* msg, int msg_size, packet_info_t* packet_info) { + weather_packet_header_t *header = (weather_packet_header_t*) msg; + + printf("\n\t Pkt received from phy: %u\n" + "\t -> SEQ: %u | TYPE: %u | SRC: %hu \n\n", + packet_info->phy_src, + header->seq_nr, + header->type, + header->src + ); + + /* when destination is set, but I'm not the receiver, pass to routing */ + if (!data_sink) { + if (header->type == WEATHER_DATA) { + weather_data_pkt_t* wdp = (weather_data_pkt_t*) msg; + /* ;;;;;;; */ + printf("%hu;%hu;%04lX;%04X;%.2f;%.2f;%.2f;%.2f\n", + header->src, + 0, + wdp->timestamp, + 0, + wdp->temperature, + wdp->relhum, + wdp->relhum_temp, + wdp->energy); + } + + puts("Not for me, routing, baby!"); + route_packet(msg, msg_size); + return; + } + + /* in all other cases handle the packet */ + switch (header->type) { + case WEATHER_HELLO: { + if (msg_size < sizeof(weather_hello_pkt_t)) { + puts("Bad hello packet received."); + } else { + puts("Hello packet received - no handler implemented"); + } + break; + } + case WEATHER_CHAT: { + puts("\n*================================================================================*"); + printf("\tCHAT MESSAGE from %hu: %s\n\n", packet_info->phy_src, ((weather_chat_pkt_t*) msg)->mesg); + puts("*================================================================================*\n"); + break; + } + case WEATHER_DATA: { + weather_data_pkt_t* wdp = (weather_data_pkt_t*) msg; + time_t local_time = rtc_time(NULL); + /* ;;;;;;; */ + printf("%hu;%u;%04lX;%04lX;%.2f;%.2f;%.2f;%.2f\n", + header->src, + 1, + wdp->timestamp, + local_time, + wdp->temperature, + wdp->relhum, + wdp->relhum_temp, + wdp->energy); + break; + } + default: { + printf("Unknown packet type \"%i\" received.", header->type); + } + } +} + +/* endless loop for packet handling */ +static void protocol_handler_thread(void) { + msg_t m; + puts("Protocol handler thread started."); + + while(1) { + msg_receive(&m); + + packet_t packet; + int pos = m.content.value; + packet = packet_buffer[pos]; + + handle_packet(packet.payload, packet.msg_size, &(packet.packet_info)); + } +} + +int main(void) { + weather_data_pkt_t wdp; sht11_val_t sht11_val; - double mAh = 0; uint8_t success = 0; + + wdp.header.seq_nr = 0; + wdp.header.type = WEATHER_DATA; puts(""); puts("WEAtHeR: Wireless Energy-Aware mulTi-Hop sEnsor Reading."); - puts("Printing \"temperature in °C;relative humidity;temperature compensated relative humidity\"."); + /* ;;;;;;; */ + puts("Printing \"node id of data source;node id of sink;timestamp of measurement;timestamp at data sink;temperature in °C;relative humidity;temperature compensated relative humidity;energy value\"."); puts(""); + thread_create(shell_stack_buffer, SHELL_STACK_SIZE, PRIORITY_MAIN-1, CREATE_STACKTEST, shell_runner, "shell"); + + /* create thread for radio packet handling */ + int pid = thread_create(ph_stack_buffer, PH_STACK_SIZE, PRIORITY_MAIN-5, CREATE_STACKTEST, protocol_handler_thread, "protocol_handler"); + set_protocol_handler_thread(pid); + ltc4150_start(); + rtc_enable(); while (1) { - success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); - mAh = ltc4150_get_total_mAh(); - if (!success) { - printf("error;error;error\n"); - } - else { - printf("%.2f;%.2f;%.2f;%.2f\n", sht11_val.temperature, sht11_val.relhum, sht11_val.relhum_temp, mAh); + if (data_src) { + wdp.header.src = cc1100_get_address(); + wdp.timestamp = rtc_time(NULL); + wdp.energy = ltc4150_get_total_mAh(); + success = sht11_read_sensor(&sht11_val, HUMIDITY|TEMPERATURE); + if (!success) { + printf("error;error;error\n"); + } + else { + wdp.temperature = sht11_val.temperature; + wdp.relhum = sht11_val.relhum; + wdp.relhum_temp = sht11_val.relhum_temp; + if (cc1100_send_csmaca(0, WEATHER_PROTOCOL_NR, 0, (char*)&wdp, sizeof(weather_data_pkt_t))) { + printf("Successfully sent packet: \n"); + wdp.header.seq_nr++; + } + else { + puts("Error on sending packet!"); + } + } + LED_RED_TOGGLE; } - LED_RED_TOGGLE; swtimer_usleep(60 * 1000*1000); } } diff --git a/projects/WEAtHeR/protocol_msg_gateway.c b/projects/WEAtHeR/protocol_msg_gateway.c new file mode 100644 index 000000000..1e439c5d5 --- /dev/null +++ b/projects/WEAtHeR/protocol_msg_gateway.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include "protocol_msg_gateway.h" + +#define NUM_PROTOCOL_HANDLER_PIDS 8 + +static uint16_t protocol_handler_pid; + +static int packet_buffer_next = 0; +packet_t packet_buffer[PACKET_BUFFER_SIZE]; + +static void protocol_msg_gateway(void* payload, int msg_size, protocol_t protocol, packet_info_t* packet_info) { + msg_t m; + +// if ((((int16_t) packet_info->phy_src) > (((int16_t) cc1100_get_address()) + 10)) || (((int16_t) packet_info->phy_src) < (((int16_t) cc1100_get_address()) - 10))) { + // return; + // } + if (protocol_handler_pid <= 0) { + puts("protocol_handler(): received packet without protocol handler. msg dropped."); + return; + } + + int mypos = packet_buffer_next++; + if (packet_buffer_next == PACKET_BUFFER_SIZE) packet_buffer_next = 0; + + packet_t *p = &(packet_buffer[mypos]); + p->packet_info = *packet_info; + p->msg_size = msg_size; + memcpy(p->payload, payload, msg_size); + + m.type = 0; + m.content.value = mypos; + int success = msg_send_int(&m, protocol_handler_pid); + if (! success) { + /* should set timer to retry. Dropping pkt for now. */ + puts("protocol_handler(): msg dropped."); + } +} + +void init_protocol_msg_gateway() { + cc1100_set_packet_monitor(protocol_msg_gateway); +} + +int set_protocol_handler_thread(int pid) { + protocol_handler_pid = pid; + return 0; +} diff --git a/projects/WEAtHeR/protocol_msg_gateway.h b/projects/WEAtHeR/protocol_msg_gateway.h new file mode 100644 index 000000000..dd190da99 --- /dev/null +++ b/projects/WEAtHeR/protocol_msg_gateway.h @@ -0,0 +1,18 @@ +#ifndef __PROTOCOL_MSG_GATEWAY_H +#define __PROTOCOL_MSG_GATEWAY_H + +#define PACKET_BUFFER_SIZE 32 +#define MAXIMUM_PAYLOAD_SIZE 64 + +typedef struct { + packet_info_t packet_info; + unsigned int msg_size; + char payload[MAXIMUM_PAYLOAD_SIZE]; +} packet_t; + +void init_protocol_msg_gateway(); +int set_protocol_handler_thread(int pid); + +extern packet_t packet_buffer[PACKET_BUFFER_SIZE]; + +#endif /* __PROTOCOL_MSG_GATEWAY_H */ diff --git a/projects/WEAtHeR/weather_protocol.h b/projects/WEAtHeR/weather_protocol.h new file mode 100644 index 000000000..f504204c9 --- /dev/null +++ b/projects/WEAtHeR/weather_protocol.h @@ -0,0 +1,41 @@ +#ifndef WEATHER_PROTOCOL_H_ +#define WEATHER_PROTOCOL_H_ + +#include +#include + +#define WEATHER_PROTOCOL_NR 6 + +typedef enum { + WEATHER_HELLO, + WEATHER_CHAT, + WEATHER_DATA +} packet_types; + +typedef struct { + uint16_t seq_nr; + uint8_t src; + uint8_t type; + uint8_t resevered; +} weather_packet_header_t; + +typedef struct __attribute__ ((packed)) { + weather_packet_header_t header; +} weather_hello_pkt_t; + +typedef struct { + weather_packet_header_t header; + uint8_t len; + char mesg[40]; +} weather_chat_pkt_t; + +typedef struct { + weather_packet_header_t header; + time_t timestamp; + double temperature; + double relhum; + double relhum_temp; + double energy; +} weather_data_pkt_t; + +#endif diff --git a/projects/WEAtHeR/weather_routing.c b/projects/WEAtHeR/weather_routing.c new file mode 100644 index 000000000..8c354b021 --- /dev/null +++ b/projects/WEAtHeR/weather_routing.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include "weather_protocol.h" +#include "weather_routing.h" + +static source_timestamp_t sources[MAX_SOURCES]; + +static uint8_t update_sources(uint8_t id, time_t timestamp) { + uint8_t i; + for (i = 0; i < MAX_SOURCES; i++) { + /* source id found */ + if (sources[i].id == id) { + /* more current timestamp received, updating */ + if (sources[i].timestamp < timestamp) { + sources[i].timestamp = timestamp; + return 1; + } + /* older, but still valid timestamp, not updating */ + else if (sources[i].timestamp < timestamp + MAX_INTERVAL) { + return 1; + } + /* timestamp too old, discard this packet */ + else { + puts("Timestamp too old, not routing"); + return 0; + } + } + /* source id not yet stored creating new entry */ + else if (!sources[i].id) { + sources[i].id = id; + sources[i].timestamp = timestamp; + return 1; + } + } + puts("No more sources could be stored!"); + return 0; +} + +void route_packet(void* msg, int msg_size) { + weather_packet_header_t *header = (weather_packet_header_t*) msg; + if (header->type == WEATHER_DATA) { + weather_data_pkt_t* wdp = (weather_data_pkt_t*) msg; + if (!update_sources(wdp->header.src, wdp->timestamp)) { + return; + } + } + + if ((100.0 * rand()/(double) RAND_MAX) <= FLOODING_PROB) { + printf("Broadcasting packet..."); + if (cc1100_send_csmaca(0, WEATHER_PROTOCOL_NR, 0, (char*)msg, msg_size)) { + puts("successful!"); + } + else { + puts("failed!"); + } + } +} + diff --git a/projects/WEAtHeR/weather_routing.h b/projects/WEAtHeR/weather_routing.h new file mode 100644 index 000000000..14d050177 --- /dev/null +++ b/projects/WEAtHeR/weather_routing.h @@ -0,0 +1,17 @@ +#ifndef WEATHER_ROUTING_H +#define WEATHER_ROUTING_H + +#include + +#define FLOODING_PROB (100) +#define MAX_SOURCES (10) +#define MAX_INTERVAL (5 * 60) + +typedef struct { + uint8_t id; + time_t timestamp; +} source_timestamp_t; + +void route_packet(void* msg, int msg_size); + +#endif /* WEATHER_ROUTING_H */