Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / server / colonet_wireless.cpp @ 566

History | View | Annotate | Download (7.54 KB)

1
/** @file colonet_wireless.c
2
 *
3
 * @brief Implementation of server-side colonet wireless library
4
 *
5
 * @author Eugene Marinelli
6
 */
7

    
8
/********************************* Includes **********************************/
9
#include <string>
10
#include <pthread.h>
11
#include <iostream>
12
#include <fstream>
13
#include <unistd.h>
14
#include <fcntl.h>
15
#include <signal.h>
16

    
17
#include <ColonetServer.h>
18
#include <wireless.h> // Colonet wireless library.
19
#include <wl_token_ring.h>
20

    
21
#include <colonet_defs.h>
22
#include <colonet_wireless.h>
23

    
24
/******************************* Definitions *********************************/
25

    
26
//Enable debug printouts
27
#define DEBUG 1
28

    
29
#ifdef DEBUG
30
#define dbg_printf(...) printf(__VA_ARGS__)
31
#define dbg_fprintf(...) fprintf(__VA_ARGS__)
32
#else
33
#define dbg_printf(...)
34
#define dbg_fprintf(...)
35
#endif
36

    
37
extern ColonetServer colonet_server;
38

    
39
static bool logging_enabled;
40
static char log_filename[80];
41
static pthread_t listener_thread;
42
static char wl_port[40];
43

    
44
/************************* Internal prototypes *******************************/
45
static void* listen(void* args);
46
static void timeout_handler(void);
47
static void handle_response(int frame, int received);
48
static void handle_receive(char type, int source, unsigned char* packet, int len);
49
static void unregister(void);
50
static int log_packet(unsigned char* packet, int len);
51

    
52
/**************************** Public functions *******************************/
53
int colonet_wl_init(char* wl_port_, char* log_filename_) {
54
  if (log_filename_ != NULL) {
55
    logging_enabled = true;
56
    strcpy(log_filename, log_filename_);
57
  }
58

    
59
  strncpy(wl_port, wl_port_, 40);
60

    
61
  wl_set_com_port(wl_port);
62

    
63
  printf("Calling wl_init(%s)...\n", wl_port);
64
  if (wl_init() != 0) {
65
    fprintf(stderr, "wl_init failed.\n");
66
    return -1;
67
  }
68

    
69
  wl_token_ring_register();
70

    
71
  printf("Joining token ring...\n");
72
  if (wl_token_ring_join() != 0) {
73
    fprintf(stderr, "Failed to join token ring.\n");
74
    return -1;
75
  }
76
  printf("Joined token ring.\n");
77

    
78
  return 0;
79
}
80

    
81
void colonet_wl_kill_listener_thread() {
82
  pthread_kill(listener_thread, 9);
83
}
84

    
85
int colonet_wl_run_listener_thread() {
86
  dbg_printf("Spawning listener thread...\n");
87

    
88
  if (pthread_create(&listener_thread, NULL, listen, NULL)) {
89
    perror("pthread_create");
90
    return -1;
91
  }
92

    
93
  return 0;
94
}
95

    
96
int colonet_wl_send(short client_source, short dest, ColonetRobotMessageType msg_type, unsigned char msg_code,
97
  unsigned char* args) {
98
  //printf("colonet_wl_send: client_source:%d, dest:%d, msg_code:%d\n", client_source, dest, msg_code);
99

    
100
  ColonetRobotServerPacket pkt;
101
  pkt.client_id = client_source;
102
  pkt.msg_code = msg_code;
103

    
104
  for (int i = 0; i < PACKET_DATA_LEN; i++) {
105
    //printf("data %i: %u\n", i, args[i]);
106
    pkt.data[i] = args[i];
107
  }
108

    
109
  if (dest == GLOBAL_DEST) {
110
    //printf("sending to global dest\n");
111
    if (wl_send_global_packet(COLONET_PACKET_GROUP_ID, (char)msg_type, (char*)(&pkt),
112
                              sizeof(ColonetRobotServerPacket), 0) != 0) {
113
      return -1;
114
    }
115
  } else {
116
    //("sending to specific robot: %d.\n", dest);
117
    if (wl_send_robot_to_robot_global_packet(COLONET_PACKET_GROUP_ID, (char)msg_type, (char*)(&pkt),
118
      sizeof(ColonetRobotServerPacket), dest, COLONET_RESPONSE_PACKET_FRAME_ID) != 0) {
119
      return -1;
120
    }
121
  }
122

    
123
  return 0;
124
}
125

    
126
int colonet_get_num_robots(void) {
127
  return wl_token_get_num_robots();
128
}
129

    
130
int* colonet_get_xbee_ids(int* numrobots) {
131
  int num_robots = wl_token_get_num_robots();
132
  int* ids = (int*)malloc(num_robots * sizeof(int));
133

    
134
  wl_token_iterator_begin();
135

    
136
  int i = 0;
137
  while (wl_token_iterator_has_next()) {
138
    ids[i] = wl_token_iterator_next();
139
    i++;
140
  }
141

    
142
  *numrobots = num_robots;
143
  return ids;
144
}
145

    
146
// Returns int**; should be freed
147
int** colonet_get_sensor_matrix(int* numrobots, int** ids_) {
148
  int num_robots;
149
  int* ids = colonet_get_xbee_ids(&num_robots);
150

    
151
  int** m = (int**)malloc(num_robots * sizeof(int*));
152
  for (int i = 0; i < num_robots; i++) {
153
    m[i] = (int*)malloc(num_robots * sizeof(int*));
154
  }
155

    
156
  for (int i = 0; i < num_robots; i++) {
157
    for (int j = 0; j < num_robots; j++) {
158
      m[i][j] = wl_token_get_sensor_reading(ids[i], ids[j]);
159
    }
160
  }
161

    
162
  *numrobots = num_robots;
163
  *ids_ = ids;
164
  return m;
165
}
166

    
167
/**************************** Private functions ******************************/
168

    
169
static void timeout_handler() {
170
  // printf("colonet wireless - timeout!\n");
171
}
172

    
173
static void handle_response(int frame, int received) {
174
  //TODO: These are just here to get rid of compiler warnings
175
  frame = frame;
176
  received = received;
177
  //printf("got response.\n");
178
}
179

    
180
static void handle_receive(char type, int source, unsigned char* data, int len) {
181
  //TODO: These are just here to get rid of compiler warnings
182
  type = type;
183

    
184
  //printf("!!!***Got packet from robot***!!!\n");
185

    
186
  ColonetRobotServerPacket* pkt = (ColonetRobotServerPacket*)data;
187

    
188
  if (logging_enabled) {
189
    log_packet(data, len);
190
  }
191

    
192
  if (pkt->msg_code == ROBOT_REQUEST_POSITION_FROM_SERVER) {
193
    /* Robot has requested its position. */
194
    int robot_x, robot_y;
195
    PositionMonitor* pm = colonet_server.getPositionMonitor();
196
    int num_robots = pm->getNumVisibleRobots();
197
    int ret = pm->getRobotPosition(source, &robot_x, &robot_y);
198
    if (ret != 0 && num_robots != 1) {
199
      fprintf(stderr, "Robot %d requested position, but its position is not known.\n", source);
200
    } else {
201
      if (ret != 0 /* && num_robots == 1 */) {
202
        VisionPosition pos = pm->getFirstPosition();
203
        robot_x = pos.x;
204
        robot_y = pos.y;
205
      }
206

    
207
      unsigned char response[80];
208
      response[0] = (robot_x >> 8) & 0xFF;
209
      response[1] = robot_x & 0xFF;
210
      response[2] = (robot_y >> 8) & 0xFF;
211
      response[3] = robot_y & 0xFF;
212

    
213
      fprintf(stderr, "Robot %d requested position.  Its position is %d,%d.\n", source, robot_x, robot_y);
214

    
215
      if (colonet_wl_send(-1, source, COLONET_COMMAND, SERVER_REPORT_POSITION_TO_ROBOT, response) != 0) {
216
        fprintf(stderr, "colonet_wl_send failed!\n");
217
        exit(1);
218
      }
219
    }
220
  } else {
221
    char processed_data[80];
222
    sprintf(processed_data, "%d %d %d %s\n", RESPONSE_TO_CLIENT_REQUEST, pkt->msg_code, source, pkt->data);
223

    
224
    colonet_server.process_received_wireless_message(pkt->client_id, processed_data, strlen(processed_data));
225
  }
226
}
227

    
228
static void unregister(void) {
229
  printf("unregister\n");
230
}
231

    
232
/** @brief Analogous to the "SIGNAL" or "ISR" function on the robots.
233
 * Listens for bytes on the wireless port and constructs packets based on them.
234
 * Not part of the ColonetWireless class since a function pointer must be
235
 * passed in starting the thread that runs it (tricky or impossible if it's
236
 * a class function).
237
 *
238
 * @param args Pointer to arguments.  Can be safely casted to ListenerArgs type
239
 * @return NULL
240
 */
241
static void* listen(void* args) {
242
  //TODO: These are just here to get rid of compiler warnings
243
  args = args;
244

    
245
  printf("Called listen.\n");
246

    
247
  PacketGroupHandler pgh = {COLONET_PACKET_GROUP_ID,
248
                            timeout_handler,
249
                            handle_response,
250
                            handle_receive,
251
                            unregister};
252
  wl_register_packet_group(&pgh);
253

    
254
  while (1) {
255
    wl_do();
256
    usleep(1000);
257
  }
258

    
259
  wl_terminate();
260
  return NULL;
261
}
262

    
263
/** @brief
264
 *
265
 * @param pkt Packet to be logged
266
 *
267
 * @return 0 on success, -1 on failure
268
 */
269
int log_packet(unsigned char* packet, int len) {
270
  FILE* logfile = fopen(log_filename, "a");
271

    
272
  if (logfile == NULL) {
273
    dbg_printf("%s: Error - fopen %s failed.\n", log_filename, __FUNCTION__);
274
    return -1;
275
  }
276

    
277
  for (int i = 0; i < len; i++) {
278
    fprintf(logfile, "%d ", *((unsigned char*)packet + i));
279
  }
280
  fprintf(logfile, "\n");
281

    
282
  fclose(logfile);
283
  return 0;
284
}