Revision 424
changed various things in colonet dragonfly and server to make stuff work
trunk/code/projects/colonet/lib/colonet_dragonfly/colonet_dragonfly.c | ||
---|---|---|
10 | 10 |
|
11 | 11 |
#include <assert.h> |
12 | 12 |
#include <dragonfly_lib.h> |
13 |
#include <battery.h> |
|
13 | 14 |
#include <string.h> |
14 | 15 |
#include <wireless.h> |
15 | 16 |
|
16 |
#include "colonet_dragonfly.h"
|
|
17 |
#include <colonet_dragonfly.h>
|
|
17 | 18 |
|
18 | 19 |
typedef struct { |
19 | 20 |
unsigned char msgId; //is this necessary? |
... | ... | |
69 | 70 |
* |
70 | 71 |
* @return -1 on error (invalid msgId), 0 on success |
71 | 72 |
*/ |
72 |
static void colonet_handle_receive(char type, int source, unsigned char* packet, int length) { |
|
73 |
static void colonet_handle_receive(char type, int wl_source, unsigned char* packet, int length) {
|
|
73 | 74 |
ColonetRobotServerPacket pkt; |
74 | 75 |
unsigned char* args; //up to 7 char args |
75 | 76 |
unsigned int int_args[3]; //up to 3 int (2-byte) args |
... | ... | |
114 | 115 |
case LOG_DISTANCE: |
115 | 116 |
break; |
116 | 117 |
|
117 |
|
|
118 | 118 |
//Analog |
119 | 119 |
case CALL_ANALOG8: |
120 | 120 |
break; |
... | ... | |
122 | 122 |
break; |
123 | 123 |
case WHEEL: |
124 | 124 |
break; |
125 |
|
|
125 | 126 |
case BATTERY: |
126 |
wl_send_robot_to_robot_global_packet(colonet_pgh.groupCode, BATTERY,
|
|
127 |
"brouhaha", 8, 0xA, 0);
|
|
127 |
sprintf((char*)pkt.data, "%d", (int)battery8());
|
|
128 |
wl_send_robot_to_robot_global_packet(colonet_pgh.groupCode, 0, (char*)&pkt, sizeof(pkt), wl_source, 0);
|
|
128 | 129 |
break; |
129 | 130 |
|
130 | 131 |
//BOM |
... | ... | |
178 | 179 |
case BUZZER_OFF: |
179 | 180 |
buzzer_off(); |
180 | 181 |
break; |
181 |
|
|
182 |
// Battery |
|
183 |
case BATTERY: |
|
184 |
usb_puts("Got battery request.\n"); |
|
185 |
|
|
186 |
/* |
|
187 |
int xbeeDongleID = 0xA; // too bad this is hard-coded. |
|
188 |
char data[20]; |
|
189 |
data[0] = 0; // client ID specified in bytes 0-3 |
|
190 |
data[1] = 0; |
|
191 |
data[2] = 0; |
|
192 |
data[3] = 0; |
|
193 |
data[4] = 0; // ??? |
|
194 |
data[5] = RESPONSE_TO_CLIENT_REQUEST; |
|
195 |
data[6] = ' '; |
|
196 |
data[7] = BATTERY; |
|
197 |
data[8] = ' '; |
|
198 |
data[9] = (char) wl_get_xbee_id(); // robot number (self) |
|
199 |
data[10] = ' '; |
|
200 |
data[11] = (char) battery8(); // battery reading |
|
201 |
data[12] = '\0'; |
|
202 |
|
|
203 |
wl_send_robot_to_robot_global_packet(colonet_pgh.groupCode, COLONET_RESPONSE, data, 13, xbeeDongleID, 0); |
|
204 |
usb_puts("lol \n"); |
|
205 |
*/ |
|
206 |
break; |
|
207 |
|
|
208 | 182 |
case ORB_INIT: |
209 | 183 |
orb_init(); |
210 | 184 |
break; |
211 |
//Orb
|
|
185 |
//Orb |
|
212 | 186 |
case ORB_SET: |
213 | 187 |
orb_set(args[0], args[1], args[2]); |
214 | 188 |
break; |
... | ... | |
234 | 208 |
motors_init(); |
235 | 209 |
break; |
236 | 210 |
case MOTOR1_SET: |
237 |
sprintf(buf, "calling motor1_set [%i] [%i]\n", args[0], args[1]);
|
|
211 |
sprintf(buf, "calling motor1_set [%i] [%i]\n", args[0], args[1]);
|
|
238 | 212 |
usb_puts(buf); |
239 | 213 |
motor1_set(args[0], args[1]); |
240 | 214 |
break; |
... | ... | |
295 | 269 |
bom_off(); |
296 | 270 |
break; |
297 | 271 |
|
298 |
//Dio
|
|
272 |
//Dio |
|
299 | 273 |
case DIGITAL_OUTPUT: |
300 | 274 |
digital_output(int_args[0], int_args[1]); |
301 | 275 |
break; |
trunk/code/projects/colonet/lib/colonet_dragonfly/Makefile | ||
---|---|---|
7 | 7 |
|
8 | 8 |
CC = avr-gcc |
9 | 9 |
CFLAGS = -Wall -Wshadow -Wextra -g -mmcu=$(MCU) |
10 |
INCLUDES = -I../ -I../../../libwireless/lib -I../../../../lib/include/libdragonfly |
|
10 |
INCLUDES = -I../ -I../../../libwireless/lib -I../../../../lib/include/libdragonfly -I.
|
|
11 | 11 |
|
12 | 12 |
all: colonet_dragonfly.o |
13 | 13 |
|
trunk/code/projects/colonet/lib/colonet_defs.h | ||
---|---|---|
12 | 12 |
#define COLONET_PACKET_GROUP_ID 8 |
13 | 13 |
#define COLONET_RESPONSE_PACKET_FRAME_ID COLONET_PACKET_GROUP_ID |
14 | 14 |
|
15 |
// Message types |
|
16 |
typedef enum {COLONET_COMMAND = 13, COLONET_REQUEST = 14, |
|
17 |
COLONET_RESPONSE = 15} ColonetMessageType; |
|
15 |
//Colonet Client commands |
|
16 |
//TODO: renamed these to end in LENGTH |
|
17 |
#define MAX_COMMAND_LEN 128 |
|
18 |
#define MAX_RESPONSE_LEN 1024 |
|
18 | 19 |
|
20 |
typedef enum {SEND_TO_ROBOT = 0, REQUEST_FROM_SERVER = 1, RESPONSE_TO_CLIENT_REQUEST = 2} ColonetClientMessageType; |
|
21 |
typedef enum {COLONET_COMMAND = 13, COLONET_REQUEST = 14, COLONET_RESPONSE = 15} ColonetRobotMessageType; |
|
22 |
|
|
19 | 23 |
//Packet properties |
20 |
#define PACKET_DATA_LEN 7
|
|
24 |
#define PACKET_DATA_LEN 16
|
|
21 | 25 |
|
22 | 26 |
#define WL_DEFAULT_PAN 3332 |
23 | 27 |
|
... | ... | |
26 | 30 |
|
27 | 31 |
// Message dests |
28 | 32 |
#define GLOBAL_DEST 200 |
29 |
//#define MAX_NUM_ROBOTS 7 |
|
30 | 33 |
#define COLONET_SERVER_RESPONSE_ADDR 201 |
31 | 34 |
|
32 | 35 |
#define USER_DEFINED_MSG_ID_START 0xF0 |
... | ... | |
37 | 40 |
* wireless library to the robots and from the robots to the colonet wireless |
38 | 41 |
* library. */ |
39 | 42 |
typedef struct { |
40 |
short client_id; // ID number of the client sending the packet. |
|
41 |
// Size of short is common to robots and server. |
|
43 |
short client_id; // ID number of the client sending the packet. Size of short is common to robots and server. |
|
42 | 44 |
unsigned char msg_code; // Specific instruction for the robot -- see below. |
43 | 45 |
unsigned char data[PACKET_DATA_LEN]; |
44 | 46 |
} ColonetRobotServerPacket; |
... | ... | |
157 | 159 |
//response: RESPONSE_TO_CLIENT_REQUEST REQUEST_XBEE_IDS <numRobots> <id0> <id1> ... <idNumRobots> |
158 | 160 |
|
159 | 161 |
|
160 |
|
|
161 |
//Colonet Client commands |
|
162 |
//TODO: renamed these to end in LENGTH |
|
163 |
#define MAX_COMMAND_LEN 128 |
|
164 |
#define MAX_RESPONSE_LEN 1024 |
|
165 |
|
|
166 |
#define SEND_TO_ROBOT 0x00 |
|
167 |
#define REQUEST_FROM_SERVER 0x01 |
|
168 |
#define RESPONSE_TO_CLIENT_REQUEST 0x02 |
|
169 |
|
|
170 |
|
|
171 | 162 |
#endif |
trunk/code/projects/colonet/ColonetServer/wirelessMessageHandler.cpp | ||
---|---|---|
1 |
/** @file wirelessMessageHandler.cpp |
|
2 |
* |
|
3 |
* @author Jason Knichel |
|
4 |
* @author Eugene Marinelli |
|
5 |
* |
|
6 |
* @bug Weird segfault when processing tokens |
|
7 |
*/ |
|
8 |
|
|
9 |
#include <string.h> |
|
10 |
#include <stdio.h> |
|
11 |
#include <unistd.h> |
|
12 |
#include <ctype.h> |
|
13 |
#include <errno.h> |
|
14 |
|
|
15 |
#include <colonet_wireless.h> |
|
16 |
|
|
17 |
#include <wirelessMessageHandler.h> |
|
18 |
#include <options.h> |
|
19 |
#include <ColonetServer.h> |
|
20 |
|
|
21 |
/* Globals */ |
|
22 |
extern ColonetServer colonet_server; |
|
23 |
|
|
24 |
/* Public functions */ |
|
25 |
int wirelessMessageHandler(unsigned char type, short source, int dest, unsigned char* data, int len) { |
|
26 |
printf("Server received wireless message!!!\n"); |
|
27 |
|
|
28 |
printf("server received this packet: "); |
|
29 |
for (int i = 0; i < len; i++) { |
|
30 |
printf("%d ", data[i]); |
|
31 |
} |
|
32 |
printf(" type: %d, source: %d, dest: %d\n", type, source, dest); |
|
33 |
|
|
34 |
return colonet_server.process_received_wireless_message(type, source, dest, data, len); |
|
35 |
} |
trunk/code/projects/colonet/ColonetServer/Command.cpp | ||
---|---|---|
24 | 24 |
connection_pool = connection_pool_temp; |
25 | 25 |
} |
26 | 26 |
|
27 |
Command::~Command() { |
|
28 |
} |
|
27 |
Command::~Command() {} |
|
29 | 28 |
|
29 |
/** |
|
30 |
* Called by connection pool to parse command from client. |
|
31 |
*/ |
|
30 | 32 |
int Command::parse_command(char* command, int pool_index) { |
31 | 33 |
char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]; |
32 | 34 |
int number_tokens = 0; |
33 | 35 |
char* end_pointer = NULL; |
34 | 36 |
int command_id; |
35 | 37 |
|
36 |
if (!connection_pool) { |
|
38 |
if (!connection_pool || !command || pool_index < 0) {
|
|
37 | 39 |
return -1; |
38 | 40 |
} |
39 | 41 |
|
40 |
if (!command) { |
|
41 |
return -1; |
|
42 |
} |
|
43 |
|
|
44 |
if (pool_index < 0) { |
|
45 |
return -1; |
|
46 |
} |
|
47 |
|
|
48 | 42 |
if ((number_tokens = tokenize_command(command, tokens)) < 0) { |
49 | 43 |
return -1; |
50 | 44 |
} |
... | ... | |
59 | 53 |
|
60 | 54 |
if (command_id == SEND_TO_ROBOT) { |
61 | 55 |
if (parse_send_to_robot(number_tokens, tokens, pool_index)) { |
56 |
fprintf(stderr, "parse_send_to_robot failed.\n"); |
|
62 | 57 |
return -1; |
63 | 58 |
} |
64 | 59 |
} else if (command_id == REQUEST_FROM_SERVER) { |
... | ... | |
145 | 140 |
return 0; |
146 | 141 |
} |
147 | 142 |
|
148 |
int Command::parse_send_to_robot(int number_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index) {
|
|
149 |
int i;
|
|
150 |
unsigned char int_tokens[MAX_TOKENS];
|
|
151 |
int number_int_tokens = number_tokens;
|
|
152 |
unsigned char arguments[PACKET_DATA_LEN]; |
|
143 |
/**
|
|
144 |
* @brief Sends parsed command from server to robot(s).
|
|
145 |
*/
|
|
146 |
int Command::parse_send_to_robot(int number_int_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index) {
|
|
147 |
unsigned char int_tokens[MAX_TOKENS], arguments[PACKET_DATA_LEN];
|
|
153 | 148 |
|
154 | 149 |
memset(arguments, 1, PACKET_DATA_LEN); |
155 | 150 |
|
156 | 151 |
// Convert tokens to ints |
157 |
for (i = ROBOT_COMMAND_OFFSET; i < number_int_tokens; i++) { |
|
152 |
for (int i = ROBOT_COMMAND_OFFSET; i < number_int_tokens; i++) {
|
|
158 | 153 |
int_tokens[i-ROBOT_COMMAND_OFFSET] = atoi(tokens[i]); |
159 | 154 |
} |
160 | 155 |
|
161 | 156 |
// Fill arguments buffer with arguments |
162 |
for (i = ROBOT_COMMAND_LEN; i < number_int_tokens-ROBOT_COMMAND_OFFSET; i++) { |
|
157 |
for (int i = ROBOT_COMMAND_LEN; i < number_int_tokens-ROBOT_COMMAND_OFFSET; i++) {
|
|
163 | 158 |
arguments[i-ROBOT_COMMAND_LEN] = int_tokens[i]; |
164 | 159 |
} |
165 | 160 |
|
... | ... | |
169 | 164 |
return -1; |
170 | 165 |
} |
171 | 166 |
|
167 |
printf("parsed command from internet client: "); |
|
168 |
for (int i = 0; i < number_int_tokens - ROBOT_COMMAND_OFFSET; i++) { |
|
169 |
printf("%d ", int_tokens[i]); |
|
170 |
} |
|
171 |
printf("\n"); |
|
172 |
|
|
172 | 173 |
// Send packet to robot |
173 |
fprintf(stderr, "Calling colonet_wl_send(%d, %d, %d, arguments)\n", |
|
174 |
int_tokens[0], int_tokens[1], int_tokens[2]); |
|
175 |
if (colonet_wl_send((short)pool_index, int_tokens[0], (ColonetMessageType)int_tokens[1], int_tokens[2], arguments) |
|
176 |
!= 0) { |
|
174 |
if (colonet_wl_send((short)pool_index, int_tokens[0], (ColonetRobotMessageType)int_tokens[1], int_tokens[2], |
|
175 |
arguments) != 0) { |
|
177 | 176 |
fprintf(stderr, "Error - Colonet_wl_send failed.\n"); |
178 | 177 |
exit(1); |
179 | 178 |
} |
... | ... | |
181 | 180 |
return 0; |
182 | 181 |
} |
183 | 182 |
|
183 |
/** |
|
184 |
* |
|
185 |
*/ |
|
184 | 186 |
int Command::parse_request_from_server(int number_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index) { |
185 | 187 |
char* end_pointer = NULL; |
186 | 188 |
|
trunk/code/projects/colonet/ColonetServer/colonet_wireless.cpp | ||
---|---|---|
14 | 14 |
#include <fcntl.h> |
15 | 15 |
#include <signal.h> |
16 | 16 |
|
17 |
#include <ColonetServer.h> |
|
17 | 18 |
#include <wireless.h> // Colonet wireless library. |
18 | 19 |
#include <wl_token_ring.h> |
19 | 20 |
|
... | ... | |
33 | 34 |
#define dbg_fprintf(...) |
34 | 35 |
#endif |
35 | 36 |
|
36 |
static MsgHandlerFunction message_handler; |
|
37 |
extern ColonetServer colonet_server; |
|
38 |
|
|
37 | 39 |
static bool logging_enabled; |
38 | 40 |
static char log_filename[80]; |
39 | 41 |
static pthread_t listener_thread; |
... | ... | |
48 | 50 |
static int log_packet(unsigned char* packet, int len); |
49 | 51 |
|
50 | 52 |
/**************************** Public functions *******************************/ |
51 |
int colonet_wl_init(char* wl_port_, MsgHandlerFunction message_handler_, char* log_filename_) {
|
|
53 |
int colonet_wl_init(char* wl_port_, char* log_filename_) { |
|
52 | 54 |
if (log_filename_ != NULL) { |
53 | 55 |
logging_enabled = true; |
54 | 56 |
strcpy(log_filename, log_filename_); |
... | ... | |
56 | 58 |
|
57 | 59 |
strncpy(wl_port, wl_port_, 40); |
58 | 60 |
|
59 |
message_handler = message_handler_; |
|
60 |
|
|
61 | 61 |
wl_set_com_port(wl_port); |
62 | 62 |
|
63 | 63 |
printf("Calling wl_init(%s)...\n", wl_port); |
... | ... | |
93 | 93 |
return 0; |
94 | 94 |
} |
95 | 95 |
|
96 |
int colonet_wl_send(short client_source, short dest, ColonetMessageType msg_type, unsigned char msg_code, |
|
97 |
unsigned char* args) {
|
|
96 |
int colonet_wl_send(short client_source, short dest, ColonetRobotMessageType msg_type, unsigned char msg_code,
|
|
97 |
unsigned char* args) { |
|
98 | 98 |
printf("colonet_wl_send: client_source:%d, dest:%d, msg_code:%d\n", client_source, dest, msg_code); |
99 | 99 |
|
100 | 100 |
ColonetRobotServerPacket pkt; |
... | ... | |
112 | 112 |
return -1; |
113 | 113 |
} |
114 | 114 |
} else { |
115 |
printf("sending to specific robot.\n");
|
|
115 |
printf("sending to specific robot: %d.\n", dest);
|
|
116 | 116 |
if (wl_send_robot_to_robot_global_packet(COLONET_PACKET_GROUP_ID, (char)msg_type, (char*)(&pkt), |
117 | 117 |
sizeof(ColonetRobotServerPacket), dest, COLONET_RESPONSE_PACKET_FRAME_ID) != 0) { |
118 | 118 |
return -1; |
... | ... | |
170 | 170 |
} |
171 | 171 |
|
172 | 172 |
static void handle_response(int frame, int received) { |
173 |
printf("handle response\n");
|
|
173 |
//printf("got response.\n");
|
|
174 | 174 |
} |
175 | 175 |
|
176 |
static void handle_receive(char type, int source, unsigned char* packet, |
|
177 |
int len) { |
|
178 |
ColonetRobotServerPacket pkt; |
|
179 |
pkt.client_id = packet[0] | (packet[1]<<8) | (packet[2]<<16) | (packet[3]<<24); //little endian |
|
176 |
static void handle_receive(char type, int source, unsigned char* data, int len) { |
|
177 |
ColonetRobotServerPacket* pkt = (ColonetRobotServerPacket*)data; |
|
180 | 178 |
|
181 |
memcpy(pkt.data, packet + 5, PACKET_DATA_LEN); |
|
182 |
|
|
183 | 179 |
if (logging_enabled) { |
184 |
log_packet(packet, len);
|
|
180 |
log_packet(data, len);
|
|
185 | 181 |
} |
186 | 182 |
|
187 |
message_handler(type, source, pkt.client_id, packet, len); |
|
183 |
char processed_data[80]; |
|
184 |
sprintf(processed_data, "%d %d %d %s\n", RESPONSE_TO_CLIENT_REQUEST, pkt->msg_code, source, pkt->data); |
|
188 | 185 |
|
186 |
colonet_server.process_received_wireless_message(pkt->client_id, processed_data, strlen(processed_data)); |
|
187 |
|
|
189 | 188 |
printf("handle receive\n"); |
190 | 189 |
} |
191 | 190 |
|
trunk/code/projects/colonet/ColonetServer/includes/wirelessMessageHandler.h | ||
---|---|---|
1 |
/** |
|
2 |
* |
|
3 |
* @author Jason Knichel |
|
4 |
* |
|
5 |
*/ |
|
6 |
|
|
7 |
#ifndef WIRELESSMESSAGEHANDLER_H |
|
8 |
#define WIRELESSMESSAGEHANDLER_H |
|
9 |
|
|
10 |
#include <colonet_wireless.h> |
|
11 |
|
|
12 |
int wirelessMessageHandler(unsigned char type, short source, int dest, |
|
13 |
unsigned char* data, int len); |
|
14 |
|
|
15 |
#endif |
trunk/code/projects/colonet/ColonetServer/includes/ConnectionPool.h | ||
---|---|---|
42 | 42 |
int check_clients(); |
43 | 43 |
|
44 | 44 |
int write_to_client(int pool_index, char * message, int length); |
45 |
|
|
46 | 45 |
void add_new_socket_to_pool(int new_socket); |
47 |
|
|
48 | 46 |
int perform_select(int listen_socket); |
49 |
|
|
50 | 47 |
int is_socket_ready_to_read(int socket); |
51 |
|
|
52 | 48 |
int get_number_clients_ready(); |
53 | 49 |
|
54 | 50 |
private: |
trunk/code/projects/colonet/ColonetServer/includes/ColonetServer.h | ||
---|---|---|
13 | 13 |
public: |
14 | 14 |
ColonetServer(); |
15 | 15 |
~ColonetServer(); |
16 |
|
|
16 | 17 |
int initialize_server(int argc, char * argv[]); |
18 |
int start_listening(void); |
|
19 |
int run_server(void); |
|
20 |
int process_received_wireless_message(int dest, char* data, int len); |
|
17 | 21 |
|
18 |
int start_listening(); |
|
19 |
|
|
20 |
int run_server(); |
|
21 |
|
|
22 |
int process_received_wireless_message(unsigned char type, short source, int dest, |
|
23 |
unsigned char * data, int len); |
|
24 |
|
|
25 | 22 |
private: |
26 | 23 |
ConnectionPool connection_pool; |
27 | 24 |
Log logger; |
28 | 25 |
int listen_socket; |
29 | 26 |
|
30 |
int initialize_wireless(); |
|
27 |
int initialize_wireless(void);
|
|
31 | 28 |
int initialize_connection(int port); |
32 | 29 |
}; |
33 | 30 |
|
trunk/code/projects/colonet/ColonetServer/includes/Command.h | ||
---|---|---|
16 | 16 |
~Command(); |
17 | 17 |
|
18 | 18 |
int parse_command(char* command, int pool_index); |
19 |
|
|
20 |
private: |
|
19 | 21 |
int tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]); |
20 | 22 |
int check_tokens(unsigned char* tokens, int number_tokens); |
21 | 23 |
|
22 |
private: |
|
23 | 24 |
int parse_send_to_robot(int number_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index); |
24 | 25 |
int parse_request_from_server(int number_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index); |
25 | 26 |
|
trunk/code/projects/colonet/ColonetServer/includes/colonet_wireless.h | ||
---|---|---|
11 | 11 |
|
12 | 12 |
#include <colonet_defs.h> |
13 | 13 |
|
14 |
typedef int(*MsgHandlerFunction)(unsigned char type, short source, int dest, unsigned char* data, int len); |
|
15 |
|
|
16 | 14 |
/** @brief Initializes colonet wireless library |
17 | 15 |
* |
18 | 16 |
* @param wl_port Either SERIAL_PORT or USB_PORT (as defined in COLONET_DEFS) |
... | ... | |
23 | 21 |
* |
24 | 22 |
* @return new ColonetWireless object |
25 | 23 |
*/ |
26 |
int colonet_wl_init(char* wl_port, MsgHandlerFunction message_handler_, char* log_filename_);
|
|
24 |
int colonet_wl_init(char* wl_port, char* log_filename_); |
|
27 | 25 |
|
28 | 26 |
/** @brief Spawns a thread which reads data from the hardware interface |
29 | 27 |
* with the colony (either a dongle or a robot programmed to relay data) |
... | ... | |
40 | 38 |
* |
41 | 39 |
* @return void |
42 | 40 |
*/ |
43 |
int colonet_wl_send(short client_source, short dest, ColonetMessageType msg_type, unsigned char msg_code, |
|
41 |
int colonet_wl_send(short client_source, short dest, ColonetRobotMessageType msg_type, unsigned char msg_code,
|
|
44 | 42 |
unsigned char* args); |
45 | 43 |
|
46 | 44 |
int colonet_get_num_robots(void); |
trunk/code/projects/colonet/ColonetServer/ConnectionPool.cpp | ||
---|---|---|
258 | 258 |
return number_clients_ready; |
259 | 259 |
} |
260 | 260 |
|
261 |
|
|
261 |
/** |
|
262 |
*/ |
|
262 | 263 |
int ConnectionPool::read_data(int pool_index, int client_file_descriptor) { |
263 | 264 |
char temporary_buffer[READ_BUFFER_SIZE]; |
264 | 265 |
char temporary_command_buffer[READ_BUFFER_SIZE+1]; |
... | ... | |
288 | 289 |
memmove(temporary_buffer, temporary_buffer+length, READ_BUFFER_SIZE - length); |
289 | 290 |
} |
290 | 291 |
|
291 |
printf("Read buffer is %s\n", read_buffer[pool_index]); |
|
292 |
printf("read_data: Read buffer is %s\n", read_buffer[pool_index]);
|
|
292 | 293 |
|
293 | 294 |
char* newline_position; |
294 | 295 |
|
... | ... | |
301 | 302 |
//TODO: this is from before all this code was put in the loop. reconsider |
302 | 303 |
// how to check this error condition and do it elsewhere |
303 | 304 |
if (!newline_position && (read_buffer_size[pool_index] == READ_BUFFER_SIZE)) { |
304 |
read_buffer_size[pool_index] = 0;
|
|
305 |
break;
|
|
305 |
read_buffer_size[pool_index] = 0;
|
|
306 |
break;
|
|
306 | 307 |
} |
307 | 308 |
|
308 | 309 |
//if no newline is found then there is not a command in the buffer |
309 | 310 |
if (!newline_position) { |
310 |
break;
|
|
311 |
break;
|
|
311 | 312 |
} |
312 | 313 |
|
313 | 314 |
command_length = (newline_position - read_buffer[pool_index])+1; |
... | ... | |
315 | 316 |
//the newline was found in garbage in the currently not used portion |
316 | 317 |
// of the read buffer |
317 | 318 |
if (command_length > read_buffer_size[pool_index]) { |
318 |
break;
|
|
319 |
break;
|
|
319 | 320 |
} |
320 | 321 |
|
321 | 322 |
memcpy(temporary_command_buffer, read_buffer[pool_index], command_length); |
... | ... | |
323 | 324 |
temporary_command_buffer[command_length-1] = '\0'; |
324 | 325 |
//did this because telnet was putting a \r\n on the end instead of just \n |
325 | 326 |
if (isspace(temporary_command_buffer[command_length-2])) { |
326 |
temporary_command_buffer[command_length-2] = '\0';
|
|
327 |
temporary_command_buffer[command_length-2] = '\0';
|
|
327 | 328 |
} |
328 | 329 |
|
329 | 330 |
memmove(read_buffer[pool_index], read_buffer[pool_index]+command_length, read_buffer_size[pool_index] - command_length); |
330 | 331 |
read_buffer_size[pool_index] -= command_length; |
331 | 332 |
|
332 | 333 |
if (command_length > MAX_COMMAND_LEN) { |
333 |
printf("The command was too long. Tossing command out.\n");
|
|
334 |
break;
|
|
334 |
fprintf(stderr, "Command was too long. Tossing command out.\n");
|
|
335 |
break;
|
|
335 | 336 |
} |
336 | 337 |
|
337 | 338 |
Command command(this); |
338 | 339 |
if (command.parse_command(temporary_command_buffer, pool_index) != 0) { |
339 |
printf("There was an error parsing command\n");
|
|
340 |
break;
|
|
340 |
fprintf(stderr, "Error parsing command\n");
|
|
341 |
break;
|
|
341 | 342 |
} |
342 | 343 |
} |
343 | 344 |
} |
... | ... | |
345 | 346 |
return 0; |
346 | 347 |
} |
347 | 348 |
|
348 |
|
|
349 | 349 |
int ConnectionPool::write_data(int pool_index, int client_file_descriptor) { |
350 | 350 |
if (write_buffer_size[pool_index] == 0) { |
351 | 351 |
return 0; |
trunk/code/projects/colonet/ColonetServer/ColonetServer.cpp | ||
---|---|---|
21 | 21 |
|
22 | 22 |
#include <ColonetServer.h> |
23 | 23 |
#include <ConnectionPool.h> |
24 |
#include <wirelessMessageHandler.h> |
|
25 | 24 |
#include <options.h> |
26 | 25 |
#include <Log.h> |
27 | 26 |
|
28 | 27 |
#define LISTEN_BACKLOG 5 |
29 | 28 |
#define LOG_BUFFER_LENGTH 128 |
29 |
#define MAX_MSG_BUFFER_LENGTH 128 |
|
30 | 30 |
|
31 | 31 |
#define u_int32_t unsigned |
32 | 32 |
|
... | ... | |
108 | 108 |
if (connection_pool.is_socket_ready_to_read(listen_socket)) { |
109 | 109 |
printf("Something is trying to connect...\n"); |
110 | 110 |
if ((accept_socket = accept(listen_socket, (struct sockaddr*) &client_addr, &client_addr_size)) < 0) { |
111 |
if (errno == EMFILE) { |
|
112 |
printf("\tWhen attempting to accept a connection, " |
|
113 |
"reached the per process limit of file descriptors." |
|
114 |
" Dropping the new connection.\n"); |
|
115 |
continue; |
|
116 |
} else { |
|
117 |
printf("\tThere was an error when attempting to accept a connection"); |
|
118 |
} |
|
119 |
continue; |
|
111 |
if (errno == EMFILE) { |
|
112 |
printf("\tWhen attempting to accept a connection, reached the per process limit of file descriptors." |
|
113 |
" Dropping the new connection.\n"); |
|
114 |
continue; |
|
115 |
} else { |
|
116 |
printf("\tThere was an error when attempting to accept a connection"); |
|
117 |
} |
|
118 |
continue; |
|
120 | 119 |
} |
121 | 120 |
|
122 | 121 |
char log_buffer[LOG_BUFFER_LENGTH]; |
123 | 122 |
snprintf(log_buffer, LOG_BUFFER_LENGTH, "Client at address %s attempting to connect.", |
124 |
inet_ntoa(client_addr.sin_addr));
|
|
123 |
inet_ntoa(client_addr.sin_addr));
|
|
125 | 124 |
logger.log_string(LOG_TYPE_CONNECT, log_buffer); |
126 | 125 |
|
127 | 126 |
if (connection_pool.add_client(accept_socket) < 0) { |
128 |
printf("\tThere was an error when trying to add a client to the connection pool.");
|
|
129 |
continue;
|
|
127 |
printf("\tThere was an error when trying to add a client to the connection pool.");
|
|
128 |
continue;
|
|
130 | 129 |
} |
131 | 130 |
|
132 | 131 |
snprintf(log_buffer, LOG_BUFFER_LENGTH, "Client at address %s successfully added to connection pool.", |
133 |
inet_ntoa(client_addr.sin_addr));
|
|
132 |
inet_ntoa(client_addr.sin_addr));
|
|
134 | 133 |
logger.log_string(LOG_TYPE_CONNECT, log_buffer); |
135 | 134 |
} |
136 | 135 |
|
... | ... | |
143 | 142 |
return 0; |
144 | 143 |
} |
145 | 144 |
|
146 |
int ColonetServer::process_received_wireless_message(unsigned char type, short source, int dest, |
|
147 |
unsigned char * data, int len) { |
|
148 |
if (type == COLONET_RESPONSE) { |
|
149 |
printf("response\n"); |
|
150 |
|
|
151 |
//Greg's code |
|
152 |
char * buffer = (char *) &(data[5]); |
|
153 |
int buflen = strlen(buffer); |
|
154 |
buffer[buflen] = '\n'; |
|
155 |
buflen++; |
|
156 |
|
|
157 |
if (connection_pool.write_to_client(dest, buffer, buflen) == ERROR_INVALID_CLIENT_ID) { |
|
158 |
printf("The robot wanted to pass the data to a client not in the pool.\n"); |
|
159 |
return -1; |
|
160 |
} |
|
161 |
|
|
162 |
printf("Put data in write buffer for client.\n"); |
|
163 |
} else { |
|
164 |
printf("not a response\n"); |
|
145 |
/** |
|
146 |
* @param source - ID of robot that message is from. |
|
147 |
* @param dest - ID of internet client to send message to. |
|
148 |
* @param data - Data to send to internet client. |
|
149 |
* @param len - Length of the data param. |
|
150 |
*/ |
|
151 |
int ColonetServer::process_received_wireless_message(int dest, char* data, int len) { |
|
152 |
if (connection_pool.write_to_client(dest, data, len) == ERROR_INVALID_CLIENT_ID) { |
|
153 |
printf("The robot wanted to pass the data to a client not in the pool.\n"); |
|
165 | 154 |
return -1; |
166 | 155 |
} |
167 | 156 |
|
157 |
//("Put data in write buffer for client.\n"); |
|
158 |
|
|
168 | 159 |
return 0; |
169 | 160 |
} |
170 | 161 |
|
171 |
|
|
172 | 162 |
/** |
173 | 163 |
* @brief Initializes the wireless |
174 | 164 |
* |
... | ... | |
184 | 174 |
printf("Logging disabled.\n"); |
185 | 175 |
} |
186 | 176 |
|
187 |
if (colonet_wl_init(optionsG.wireless_port, wirelessMessageHandler, log_filename) != 0) {
|
|
177 |
if (colonet_wl_init(optionsG.wireless_port, log_filename) != 0) { |
|
188 | 178 |
fprintf(stderr, "ERROR - colonet_wl_init failed.\n"); |
189 | 179 |
return -1; |
190 | 180 |
} |
trunk/code/projects/colonet/ColonetServer/Makefile | ||
---|---|---|
3 | 3 |
CC = g++ |
4 | 4 |
CFLAGS = -Wall -Wshadow -Wextra -g -pg |
5 | 5 |
|
6 |
COLONETCPPFILES = Main.cpp ColonetServer.cpp wirelessMessageHandler.cpp ConnectionPool.cpp Command.cpp colonet_wireless.cpp
|
|
6 |
COLONETCPPFILES = Main.cpp ColonetServer.cpp ConnectionPool.cpp Command.cpp colonet_wireless.cpp includes/*.h
|
|
7 | 7 |
COLONETCPPOBJECTS = $(COLONETCPPFILES:.cpp=.o) |
8 | 8 |
COLONETFILES = options.c |
9 | 9 |
COLONETOBJECTS = $(COLONETFILES:.c=.o) |
trunk/code/projects/colonet/utilities/wireless/wireless.c | ||
---|---|---|
1 |
/* |
|
2 |
Wireless |
|
3 |
Eugene Marinelli |
|
4 |
|
|
5 |
(See .h for details) |
|
6 |
*/ |
|
7 |
|
|
8 |
/* Includes */ |
|
9 |
#include <firefly+_lib.h> |
|
10 |
#include <string.h> |
|
11 |
#include <avr/interrupt.h> |
|
12 |
|
|
13 |
#include "wireless.h" |
|
14 |
|
|
15 |
/* Constants */ |
|
16 |
#define PREFIX0 'R' |
|
17 |
#define PREFIX1 'C' |
|
18 |
|
|
19 |
//wl_buf positions |
|
20 |
#define WL_SRC_LOC 2 |
|
21 |
#define WL_DEST_LOC 3 |
|
22 |
#define WL_DATA_START 4 |
|
23 |
|
|
24 |
#define WL_TIMEOUT 4 |
|
25 |
#define WL_TIMEOUT_INITIAL 4 |
|
26 |
|
|
27 |
/* Globals */ |
|
28 |
static WL_Packet latest_packet; |
|
29 |
static WL_Packet tmp_packet; |
|
30 |
static char new_message; //set to 1 if there is a new message, else 0 |
|
31 |
static char listener_addr; //address that the robot is listening on |
|
32 |
|
|
33 |
static int message_length; //length of the messages sent/received |
|
34 |
|
|
35 |
//static unsigned char wl_to_flag; |
|
36 |
//static unsigned int wl_to_count; |
|
37 |
//static unsigned int wl_to_max; |
|
38 |
|
|
39 |
/* Internal function headers */ |
|
40 |
static void wl_timeout_handler(void); |
|
41 |
|
|
42 |
/* External function definitions */ |
|
43 |
int wl_init(int msg_len, char listener_address){ |
|
44 |
if(msg_len > WL_MSG_MAX_LEN){ |
|
45 |
printf("Error: %s: message length must be less than %d\n", __FUNCTION__, |
|
46 |
WL_MSG_MAX_LEN); |
|
47 |
return -1; |
|
48 |
} |
|
49 |
|
|
50 |
message_length = msg_len; |
|
51 |
|
|
52 |
listener_addr = listener_address; |
|
53 |
|
|
54 |
rtc_init(PRESCALE_DIV_128, 64, &wl_timeout_handler); |
|
55 |
/* executes the function about every 1/4 sec */ |
|
56 |
|
|
57 |
//wl_to_flag = 0; |
|
58 |
//wl_to_count = 0; |
|
59 |
|
|
60 |
UCSR0B |= _BV(RXCIE) | _BV(RXEN); |
|
61 |
|
|
62 |
sei(); |
|
63 |
|
|
64 |
new_message = 0; |
|
65 |
memset(&latest_packet, 0, sizeof(WL_Packet)); |
|
66 |
|
|
67 |
return 0; |
|
68 |
} |
|
69 |
|
|
70 |
int wl_send(char* msg, char dest){ |
|
71 |
int i = 0; |
|
72 |
WL_Packet packet; |
|
73 |
|
|
74 |
if(strlen(msg) > WL_MSG_MAX_LEN){ |
|
75 |
printf("Error: %s: message is too long\n", __FUNCTION__); |
|
76 |
return -1; |
|
77 |
} |
|
78 |
|
|
79 |
wl_create_packet(msg, listener_addr, dest, &packet); |
|
80 |
|
|
81 |
serial_putchar(packet.prefix[0]); |
|
82 |
serial_putchar(packet.prefix[1]); |
|
83 |
serial_putchar(packet.src); |
|
84 |
serial_putchar(packet.dest); |
|
85 |
|
|
86 |
for(i = 0; i < message_length; i++){ |
|
87 |
serial_putchar(packet.msg[i]); |
|
88 |
} |
|
89 |
|
|
90 |
serial_putchar(packet.checksum); |
|
91 |
|
|
92 |
return 0; |
|
93 |
} |
|
94 |
|
|
95 |
int wl_recv(char* msgbuf, char* src, char* dest){ |
|
96 |
if(!new_message){ |
|
97 |
return 0; //no new message |
|
98 |
} |
|
99 |
|
|
100 |
strcpy(msgbuf, latest_packet.msg); |
|
101 |
|
|
102 |
*src = latest_packet.src; |
|
103 |
*dest = latest_packet.dest; |
|
104 |
|
|
105 |
new_message = 0; |
|
106 |
|
|
107 |
return strlen(msgbuf); |
|
108 |
} |
|
109 |
|
|
110 |
char wl_get_checksum(WL_Packet* packet){ |
|
111 |
char checksum = 0; |
|
112 |
int i; |
|
113 |
|
|
114 |
checksum += packet->src; |
|
115 |
checksum += packet->dest; |
|
116 |
for(i = 0; i < message_length; i++) { |
|
117 |
checksum += packet->msg[i]; |
|
118 |
} |
|
119 |
|
|
120 |
return checksum; |
|
121 |
} |
|
122 |
|
|
123 |
int wl_create_packet(char* msg, char src, char dest, WL_Packet* packet){ |
|
124 |
packet->prefix[0] = 'R'; |
|
125 |
packet->prefix[1] = 'C'; |
|
126 |
|
|
127 |
packet->src = src; |
|
128 |
packet->dest = dest; |
|
129 |
|
|
130 |
memset(packet->msg, 0, message_length); |
|
131 |
strcpy(packet->msg, msg); |
|
132 |
|
|
133 |
packet->checksum = wl_get_checksum(packet); |
|
134 |
|
|
135 |
return 0; |
|
136 |
} |
|
137 |
|
|
138 |
/* Internal function definitions */ |
|
139 |
|
|
140 |
//use on new avr-libc |
|
141 |
//ISR(USART0_RX_vect) |
|
142 |
SIGNAL(SIG_USART0_RECV){ |
|
143 |
char wl_input = UDR0; |
|
144 |
static unsigned int wl_index = 0; |
|
145 |
static unsigned char wl_chksum = 0; |
|
146 |
|
|
147 |
if(wl_index == 0){ |
|
148 |
//first packet? - check chksum to make sure we're not beginning |
|
149 |
if(wl_input == PREFIX0) { |
|
150 |
wl_to_count = 0; //at this point we're not timing out |
|
151 |
wl_index = 1; |
|
152 |
} |
|
153 |
}else if(wl_index == 1){ |
|
154 |
if(wl_input != PREFIX1){ |
|
155 |
wl_index = 0; |
|
156 |
}else{ |
|
157 |
wl_index = WL_SRC_LOC; |
|
158 |
} |
|
159 |
}else if(wl_index == WL_SRC_LOC){ |
|
160 |
tmp_packet.src = wl_input; |
|
161 |
wl_index = WL_DEST_LOC; |
|
162 |
}else if(wl_index == WL_DEST_LOC){ |
|
163 |
tmp_packet.dest = wl_input; |
|
164 |
wl_index = WL_DATA_START; |
|
165 |
}else if(wl_index < WL_DATA_START + message_length){ |
|
166 |
//getting the rest of the packet |
|
167 |
tmp_packet.msg[wl_index-WL_DATA_START] = wl_input; |
|
168 |
wl_index++; |
|
169 |
}else if(wl_index == WL_DATA_START + message_length){ |
|
170 |
//we are at checksum location |
|
171 |
tmp_packet.checksum = wl_input; |
|
172 |
wl_chksum = wl_get_checksum(&tmp_packet); |
|
173 |
|
|
174 |
if(tmp_packet.checksum == wl_chksum) { |
|
175 |
//checksum is correct |
|
176 |
memcpy(&latest_packet, &tmp_packet, sizeof(WL_Packet)); |
|
177 |
new_message = 1; |
|
178 |
} else { //chksum failed |
|
179 |
serial1_putchar('F'); |
|
180 |
lcd_putchar('F'); |
|
181 |
|
|
182 |
printf("checksum failed - was %d, should have been %d\n", wl_input, |
|
183 |
wl_chksum); |
|
184 |
} |
|
185 |
|
|
186 |
wl_index = 0; |
|
187 |
} |
|
188 |
} |
|
189 |
|
|
190 |
|
|
191 |
/* |
|
192 |
\fn wl_timeout_handler |
|
193 |
Handles the timeout case. |
|
194 |
|
|
195 |
A time out occurs about every 1/4 second. This function is called each time |
|
196 |
one occurs. In the case where a robot first turns on, it will wait for a long |
|
197 |
time before declaring itself the leader. Otherwise, if enough time-outs |
|
198 |
occur in a row, wl_to_flag will be set to 1. This will cause a timeout |
|
199 |
packet to be sent next time around |
|
200 |
|
|
201 |
*/ |
|
202 |
static void wl_timeout_handler( void ) { |
|
203 |
//increment the total number of wireless time-outs |
|
204 |
wl_to_count++; |
|
205 |
|
|
206 |
static int wl_first_to_count = 0; |
|
207 |
static int first_time = 1; |
|
208 |
|
|
209 |
//first time time out routine - listen for a long time |
|
210 |
if(first_time) { |
|
211 |
if(wl_to_count > WL_TIMEOUT_INITIAL) { |
|
212 |
//increment the counter for first timeouts |
|
213 |
wl_first_to_count++; |
|
214 |
|
|
215 |
//you don't actually want to send out a packet |
|
216 |
//-- you would confuse other robots |
|
217 |
wl_to_flag = 0; |
|
218 |
wl_to_count = 0; |
|
219 |
} |
|
220 |
|
|
221 |
first_time = 0; |
|
222 |
} else { |
|
223 |
//not the first time - regular time out routine |
|
224 |
//if you have enough timeouts |
|
225 |
if(wl_to_count > WL_TIMEOUT) { |
|
226 |
//lcd_putchar('z'); |
|
227 |
|
|
228 |
//change the time-out flag to 1 |
|
229 |
wl_to_flag = 1; |
|
230 |
wl_to_count = 0; |
|
231 |
} |
|
232 |
} |
|
233 |
} |
trunk/code/projects/colonet/utilities/wireless/wireless.h | ||
---|---|---|
1 |
#ifndef WIRELESS_H |
|
2 |
#define WIRELESS_H |
|
3 |
|
|
4 |
/* |
|
5 |
Wireless - wireless functions for Colony |
|
6 |
|
|
7 |
Eugene Marinelli |
|
8 |
7/22/06 |
|
9 |
*/ |
|
10 |
|
|
11 |
#define WL_MSG_MAX_LEN 16 |
|
12 |
#define WL_PACKET_MAX_LEN (WL_MSG_MAX_LEN+5) |
|
13 |
|
|
14 |
#define GLOBAL_DEST 200 |
|
15 |
|
|
16 |
typedef struct { |
|
17 |
char prefix[2]; |
|
18 |
char src; |
|
19 |
char dest; |
|
20 |
char msg[WL_MSG_MAX_LEN]; |
|
21 |
char checksum; |
|
22 |
} WL_Packet; |
|
23 |
|
|
24 |
/* wl_init |
|
25 |
msg_len (< WL_MSG_MAX_LEN) is the length of the messages sent |
|
26 |
in the packets. |
|
27 |
listener_address is the address to listen on |
|
28 |
*/ |
|
29 |
int wl_init(int msg_len, char listener_address); |
|
30 |
|
|
31 |
int wl_send(char* msg, char dest); |
|
32 |
int wl_recv(char* msgbuf, char* src, char* dest); |
|
33 |
// get most recent valid message - implement message queue later |
|
34 |
|
|
35 |
int wl_create_packet(char* msg, char src, char dest, WL_Packet* packet); |
|
36 |
char wl_get_checksum(WL_Packet* packet); |
|
37 |
|
|
38 |
#endif |
trunk/code/projects/libwireless/lib/wireless.h | ||
---|---|---|
107 | 107 |
* @param packet the packet received |
108 | 108 |
* @param length the length of the packet |
109 | 109 |
**/ |
110 |
void (*handle_receive) (char type, int source, unsigned char* packet, |
|
111 |
int length); |
|
110 |
void (*handle_receive) (char type, int source, unsigned char* packet, int length); |
|
112 | 111 |
|
113 | 112 |
/** |
114 | 113 |
* Called for any cleanup when the network is turned off. |
trunk/code/projects/libwireless/lib/wireless.c | ||
---|---|---|
110 | 110 |
} |
111 | 111 |
|
112 | 112 |
//begin timeout timer |
113 |
#ifdef ROBOT
|
|
114 |
#ifdef FIREFLY
|
|
113 |
#ifdef ROBOT |
|
114 |
#ifdef FIREFLY |
|
115 | 115 |
rtc_init(PRESCALE_DIV_256, 32, &timer_handler); |
116 |
#else
|
|
116 |
#else |
|
117 | 117 |
rtc_init(HALF_SECOND, &timer_handler); |
118 |
#endif
|
|
119 |
#else
|
|
118 |
#endif |
|
119 |
#else |
|
120 | 120 |
|
121 | 121 |
//create our timer |
122 | 122 |
struct itimerval timer_val; |
... | ... | |
142 | 142 |
sigemptyset(&wl_sig_act.sa_mask); |
143 | 143 |
sigaction(SIGALRM, &wl_sig_act, 0); |
144 | 144 |
sigaction(SIGINT, &wl_sig_act, 0); |
145 |
#endif
|
|
145 |
#endif |
|
146 | 146 |
|
147 | 147 |
return 0; |
148 | 148 |
} |
... | ... | |
153 | 153 |
void wl_terminate() |
154 | 154 |
{ |
155 | 155 |
int i; |
156 |
for (i = 0; i < WL_MAX_PACKET_GROUPS; i++) |
|
156 |
for (i = 0; i < WL_MAX_PACKET_GROUPS; i++) {
|
|
157 | 157 |
if (wl_packet_groups[i] != NULL && |
158 |
wl_packet_groups[i]->unregister != NULL) |
|
158 |
wl_packet_groups[i]->unregister != NULL) {
|
|
159 | 159 |
wl_packet_groups[i]->unregister(); |
160 |
} |
|
161 |
} |
|
160 | 162 |
|
161 | 163 |
xbee_terminate(); |
162 | 164 |
} |
... | ... | |
272 | 274 |
* @param len the packet length in bytes |
273 | 275 |
* @param frame the frame number to see with a TX_STATUS response |
274 | 276 |
**/ |
275 |
void wl_send_pan_packet(char group, char type, |
|
276 |
char* data, int len, char frame) |
|
277 |
void wl_send_pan_packet(char group, char type, char* data, int len, char frame) |
|
277 | 278 |
{ |
278 | 279 |
wl_send_packet(group, type, data, len, XBEE_BROADCAST, |
279 | 280 |
XBEE_OPTIONS_NONE, frame); |
Also available in: Unified diff