Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / server / Command.cpp @ 520

History | View | Annotate | Download (8.87 KB)

1 128 jknichel
/**
2
 * @file Command.cpp
3
 *
4
 * @author Jason Knichel
5
 * @date 10/9/07
6 144 jknichel
 *
7
 * @todo make it so command doesn't rely on connection pool.  have methods
8
 *       that may return a response return it by getting a response array passed in to them
9
 *       that they fill in and then colonet server takes the contents of that response array
10
 *       and sends it to the appropriate client
11 128 jknichel
 */
12
13 156 emarinel
#include <ctype.h>
14
#include <stdio.h>
15 128 jknichel
#include <stdlib.h>
16
#include <string.h>
17 156 emarinel
18 161 emarinel
#include <colonet_wireless.h>
19
20 391 emarinel
#include <Command.h>
21
#include <ConnectionPool.h>
22 447 emarinel
#include <map>
23
#include <vision.h>
24 128 jknichel
25 447 emarinel
using namespace std;
26
27 453 emarinel
Command::Command(ConnectionPool * connection_pool_temp, ColonetServer* cs) {
28 139 jknichel
  connection_pool = connection_pool_temp;
29 453 emarinel
  colonet_server = cs;
30 128 jknichel
}
31
32 424 emarinel
Command::~Command() {}
33 128 jknichel
34 424 emarinel
/**
35
* Called by connection pool to parse command from client.
36
*/
37 139 jknichel
int Command::parse_command(char* command, int pool_index) {
38 128 jknichel
  char tokens[MAX_TOKENS][MAX_TOKEN_SIZE];
39
  int number_tokens = 0;
40
  char* end_pointer = NULL;
41
  int command_id;
42
43 424 emarinel
  if (!connection_pool || !command || pool_index < 0) {
44 139 jknichel
    return -1;
45
  }
46
47 128 jknichel
  if ((number_tokens = tokenize_command(command, tokens)) < 0) {
48
    return -1;
49
  }
50
51
  //the 10 in the function call indicates number is base 10
52
  command_id = strtol(tokens[0], &end_pointer, 10);
53
54
  if (!end_pointer || *end_pointer != '\0') {
55
    printf("There was an error converting first token into a number.\n");
56
    return -1;
57
  }
58
59
  if (command_id == SEND_TO_ROBOT) {
60 156 emarinel
    if (parse_send_to_robot(number_tokens, tokens, pool_index)) {
61 424 emarinel
      fprintf(stderr, "parse_send_to_robot failed.\n");
62 129 jknichel
      return -1;
63 128 jknichel
    }
64
  } else if (command_id == REQUEST_FROM_SERVER) {
65 139 jknichel
    if (parse_request_from_server(number_tokens, tokens, pool_index)) {
66 128 jknichel
      return -1;
67
    }
68
  }
69
70
  return 0;
71
}
72
73
/**
74
 * @brief Breaks a command up into tokens
75
 *
76
 * @param command The command to tokenize
77
 * @param tokens A two dimensional character array to store the tokens in
78
 *
79
 * @return 0 on success, negative error code on failure
80
 */
81
int Command::tokenize_command(char* command, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE]) {
82
  char* next_token = command;
83
  char* end_token = NULL;
84
  int number_tokens = 0;
85
86
  if (!command) {
87
    return -1;
88
  }
89
90
  while ((end_token = strstr(next_token, " "))) {
91
    *end_token = '\0';
92
93
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
94
      return -1;
95
    }
96
97
    strcpy(tokens[number_tokens], next_token);
98
99
    number_tokens++;
100
    next_token = end_token + 1;
101
102
    while (isspace(*next_token) && *next_token != '\0') {
103
      next_token++;
104
    }
105
  }
106
107
  if (end_token == NULL && *next_token != '\0') {
108
    if (strlen(next_token) > MAX_TOKEN_SIZE-1) {
109
      return -1;
110
    }
111
112
    strcpy(tokens[number_tokens], next_token);
113
114
    number_tokens++;
115
  }
116
117
  return number_tokens;
118
}
119
120 161 emarinel
/**
121 128 jknichel
 * @brief checks a list of tokens to see if it's valid
122
 *
123
 * @param tokens The tokens to check
124
 * @param number_tokens The number of tokens contained in the tokens parameter
125
 *
126
 * @return 0 if tokens is valid
127
 */
128
int Command::check_tokens(unsigned char* tokens, int number_tokens) {
129
  if (number_tokens > 3 + PACKET_DATA_LEN) {
130
    /* Too many tokens */
131
    return -1;
132
  }
133
134
  if (number_tokens < 3) {
135
    /* Not enough tokens */
136
    return -1;
137
  }
138 161 emarinel
139 128 jknichel
  if (tokens[1] != COLONET_REQUEST && tokens[1] != COLONET_COMMAND) {
140
    /* Invalid message type */
141
    return -1;
142
  }
143
144
  return 0;
145
}
146 129 jknichel
147 424 emarinel
/**
148
* @brief Sends parsed command from server to robot(s).
149
*/
150
int Command::parse_send_to_robot(int number_int_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index) {
151
  unsigned char int_tokens[MAX_TOKENS], arguments[PACKET_DATA_LEN];
152 129 jknichel
153
  memset(arguments, 1, PACKET_DATA_LEN);
154
155 161 emarinel
  // Convert tokens to ints
156 424 emarinel
  for (int i = ROBOT_COMMAND_OFFSET; i < number_int_tokens; i++) {
157 129 jknichel
    int_tokens[i-ROBOT_COMMAND_OFFSET] = atoi(tokens[i]);
158
  }
159
160 161 emarinel
  // Fill arguments buffer with arguments
161 424 emarinel
  for (int i = ROBOT_COMMAND_LEN; i < number_int_tokens-ROBOT_COMMAND_OFFSET; i++) {
162 129 jknichel
    arguments[i-ROBOT_COMMAND_LEN] = int_tokens[i];
163
  }
164
165 161 emarinel
  // Check the tokens
166 129 jknichel
  if (check_tokens(int_tokens, number_int_tokens) < 0) {
167 151 gtress
    fprintf(stderr, "%s: Error - Invalid robot command/request.\n", __FUNCTION__);
168 129 jknichel
    return -1;
169
  }
170
171 516 emarinel
  //printf("parsed command from internet client: ");
172 424 emarinel
  for (int i = 0; i < number_int_tokens - ROBOT_COMMAND_OFFSET; i++) {
173
    printf("%d ", int_tokens[i]);
174
  }
175
  printf("\n");
176
177 161 emarinel
  // Send packet to robot
178 424 emarinel
  if (colonet_wl_send((short)pool_index, int_tokens[0], (ColonetRobotMessageType)int_tokens[1], int_tokens[2],
179
    arguments) != 0) {
180 418 emarinel
    fprintf(stderr, "Error - Colonet_wl_send failed.\n");
181
    exit(1);
182 408 emarinel
  }
183 156 emarinel
184 129 jknichel
  return 0;
185
}
186 130 jknichel
187 424 emarinel
/**
188
*
189
*/
190 139 jknichel
int Command::parse_request_from_server(int number_tokens, char tokens[MAX_TOKENS][MAX_TOKEN_SIZE], int pool_index) {
191 130 jknichel
  char* end_pointer = NULL;
192
193 139 jknichel
  if (!connection_pool) {
194
    return -1;
195
  }
196
197 156 emarinel
  if (number_tokens < 2) {
198 130 jknichel
    return -1;
199 156 emarinel
  }
200 130 jknichel
201
  end_pointer=NULL;
202
  int second_token = strtol(tokens[1], &end_pointer, 10);
203
204
  if (!end_pointer || *end_pointer != '\0') {
205
    printf("There was an error converting second token into a number.\n");
206
    return -1;
207
  }
208 161 emarinel
209 445 emarinel
  switch (second_token) {
210
  case REQUEST_BOM_MATRIX:
211 139 jknichel
    if (parse_request_bom_matrix(pool_index)) {
212 131 jknichel
      return -1;
213 130 jknichel
    }
214 445 emarinel
    break;
215
216
  case REQUEST_XBEE_IDS:
217 139 jknichel
    if (parse_request_xbee_ids(pool_index)) {
218 131 jknichel
      return -1;
219
    }
220 445 emarinel
    break;
221
222
  case CLIENT_REQUEST_ROBOT_POSITIONS:
223
    if (parse_request_robot_positions(pool_index)) {
224
      return -1;
225
    }
226
    break;
227
228 453 emarinel
  case CLIENT_ASSIGN_ROBOT_ID:
229 520 emarinel
    colonet_server->getPositionMonitor()->assignRealId(atoi(tokens[2]), atoi(tokens[3]));
230 450 emarinel
    break;
231
232 445 emarinel
  default:
233 516 emarinel
    char* my_current_message = "Invalid request!\n";
234
    //printf("Sending %s\n", my_current_message);
235 131 jknichel
    connection_pool->write_to_client(pool_index, my_current_message, strlen(my_current_message));
236 445 emarinel
    break;
237 131 jknichel
  }
238 130 jknichel
239 131 jknichel
  return 0;
240
}
241 130 jknichel
242 139 jknichel
int Command::parse_request_bom_matrix(int pool_index) {
243 135 jknichel
  char response_bom_matrix_buffer[MAX_RESPONSE_LEN];
244 131 jknichel
  char temp_bom_matrix_buffer[MAX_RESPONSE_LEN];
245 161 emarinel
246 139 jknichel
  if (!connection_pool) {
247
    return -1;
248
  }
249
250 297 emarinel
  int num_robots;
251 299 jknichel
  int * xbee_ids;
252
  int** bom_matrix = colonet_get_sensor_matrix(&num_robots, &xbee_ids);
253 130 jknichel
254 297 emarinel
  printf("number of robots is %d\n", num_robots);
255 161 emarinel
256 131 jknichel
  //TODO: make this better
257
  //TODO: make sure I don't need to do MAX_RESPONSE_LENGTH-1
258 297 emarinel
  snprintf(response_bom_matrix_buffer, MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_BOM_MATRIX,
259
           num_robots);
260
  for (int i = 0; i < num_robots; i++) {
261
    for (int j = 0; j < num_robots; j++) {
262 131 jknichel
      //TODO: don't use strcpy
263 135 jknichel
      strcpy(temp_bom_matrix_buffer, response_bom_matrix_buffer);
264 130 jknichel
      //TODO: put length checking in here so array doesn't go out of bounds
265
      //TODO: maybe use strncat?
266 131 jknichel
      strcat(temp_bom_matrix_buffer," %d");
267 297 emarinel
      snprintf(response_bom_matrix_buffer, MAX_RESPONSE_LEN, temp_bom_matrix_buffer, bom_matrix[i][j]);
268 130 jknichel
    }
269
  }
270 135 jknichel
  strcat(response_bom_matrix_buffer,"\n");
271
  connection_pool->write_to_client(pool_index, response_bom_matrix_buffer, strlen(response_bom_matrix_buffer));
272 516 emarinel
  //printf("Sending %s", response_bom_matrix_buffer);
273 297 emarinel
274
  for (int i = 0; i < num_robots; i++) {
275
    free(bom_matrix[i]);
276
  }
277
  free(bom_matrix);
278 130 jknichel
279 299 jknichel
  free(xbee_ids);
280
281 130 jknichel
  return 0;
282
}
283 131 jknichel
284 445 emarinel
int Command::parse_request_robot_positions(int pool_index) {
285 516 emarinel
  //printf("*****parse_request_robot_positions\n");
286 455 emarinel
287 453 emarinel
  map<int, VisionPosition> positions = colonet_server->getPositionMonitor()->getAllRobotPositions();
288 455 emarinel
  map<int, VisionPosition>::iterator iter;
289 447 emarinel
290 466 emarinel
  char position_buffer[256];
291
  position_buffer[0] = 0;
292
  sprintf(position_buffer, "%d %d", RESPONSE_TO_CLIENT_REQUEST, CLIENT_REQUEST_ROBOT_POSITIONS);
293
294 455 emarinel
  for (iter = positions.begin(); iter != positions.end(); iter++) {
295
    char tmpbuf[80];
296 466 emarinel
    sprintf(tmpbuf, " %d %d %d", iter->first, iter->second.x, iter->second.y);
297 455 emarinel
    strcat(position_buffer, tmpbuf);
298
  }
299
300 466 emarinel
  strcat(position_buffer, "\n");
301
302 516 emarinel
  //printf("position buffer is: %s\n", position_buffer);
303 466 emarinel
304 455 emarinel
  connection_pool->write_to_client(pool_index, position_buffer, strlen(position_buffer));
305
306 445 emarinel
  return 0;
307
}
308
309 139 jknichel
int Command::parse_request_xbee_ids(int pool_index) {
310 297 emarinel
  char temp_xbee_id_buffer[MAX_RESPONSE_LEN];
311 131 jknichel
  char xbee_id_buffer[MAX_RESPONSE_LEN];
312 161 emarinel
313 297 emarinel
  int num_robots;
314
  int* xbee_ids = colonet_get_xbee_ids(&num_robots);
315
316 516 emarinel
  //printf("num_robots: %d\n", num_robots);
317
  //printf("xbee_ids: ");
318
  //for (int i = 0; i < num_robots; i++) {
319
  //  printf("%d ", xbee_ids[i]);
320
  //}
321
  //printf("\n");
322 418 emarinel
323 139 jknichel
  if (!connection_pool) {
324
    return -1;
325
  }
326
327 297 emarinel
  snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, "%d %d %d", RESPONSE_TO_CLIENT_REQUEST, REQUEST_XBEE_IDS, num_robots);
328 161 emarinel
329 297 emarinel
  for (int i = 0; i < num_robots; i++) {
330 131 jknichel
    strcpy(temp_xbee_id_buffer, xbee_id_buffer);
331
    //TODO: put length checking in here so array doesn't go out of bounds
332
    //TODO: maybe use strncat?
333
    strcat(temp_xbee_id_buffer, " %d");
334 297 emarinel
    snprintf(xbee_id_buffer, MAX_RESPONSE_LEN, temp_xbee_id_buffer, xbee_ids[i]);
335 131 jknichel
  }
336
  strcat(xbee_id_buffer, "\n");
337
  connection_pool->write_to_client(pool_index, xbee_id_buffer, strlen(xbee_id_buffer));
338 516 emarinel
  //printf("Sending %s", xbee_id_buffer);
339 131 jknichel
340 297 emarinel
  free(xbee_ids);
341
342 131 jknichel
  return 0;
343
}