Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / ColonetServer / colonet_wireless.cpp @ 399

History | View | Annotate | Download (6.08 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 <wireless.h> // Colonet wireless library.
18
#include <wl_token_ring.h>
19

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

    
23
/******************************* Definitions *********************************/
24

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

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

    
36
static MsgHandlerFunction message_handler;
37
static bool logging_enabled;
38
static char log_filename[80];
39
static pthread_t listener_thread;
40
static char wl_port[40];
41

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

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

    
57
  strncpy(wl_port, wl_port_, 40);
58

    
59
  message_handler = message_handler_;
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
void colonet_wl_send(short client_source, short dest, ColonetMessageType 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
    pkt.data[i] = args[i];
106
  }
107

    
108
  if (dest == GLOBAL_DEST) {
109
    printf("sending to global dest\n");
110

    
111
    wl_send_global_packet(COLONET_PACKET_GROUP_ID, (char)msg_type, (char*)(&pkt), sizeof(ColonetRobotServerPacket), 0);
112
  } else {
113
    printf("sending to specific robot.\n");
114
    wl_send_robot_to_robot_global_packet(COLONET_PACKET_GROUP_ID, (char)msg_type, (char*)(&pkt),
115
                                         sizeof(ColonetRobotServerPacket), dest, COLONET_RESPONSE_PACKET_FRAME_ID);
116
  }
117
}
118

    
119
int colonet_get_num_robots(void) {
120
  return wl_token_get_num_robots();
121
}
122

    
123
int* colonet_get_xbee_ids(int* numrobots) {
124
  int num_robots = wl_token_get_num_robots();
125
  int* ids = (int*)malloc(num_robots * sizeof(int));
126

    
127
  wl_token_iterator_begin();
128

    
129
  int* p = ids;
130
  while (wl_token_iterator_has_next()) {
131
    *p = wl_token_iterator_next();
132
    p++;
133
  }
134

    
135
  *numrobots = num_robots;
136
  return ids;
137
}
138

    
139
// Returns int**; should be freed
140
int** colonet_get_sensor_matrix(int* numrobots, int** ids_) {
141
  int num_robots;
142
  int* ids = colonet_get_xbee_ids(&num_robots);
143

    
144
  int** m = (int**)malloc(num_robots * sizeof(int*));
145
  for (int i = 0; i < num_robots; i++) {
146
    m[i] = (int*)malloc(num_robots * sizeof(int*));
147
  }
148

    
149
  for (int i = 0; i < num_robots; i++) {
150
    for (int j = 0; j < num_robots; j++) {
151
      m[i][j] = wl_token_get_sensor_reading(ids[i], ids[j]);
152
    }
153
  }
154

    
155
  *numrobots = num_robots;
156
  *ids_ = ids;
157
  return m;
158
}
159

    
160
/**************************** Private functions ******************************/
161

    
162
static void timeout_handler() {
163
  printf("colonet wireless - timeout!\n");
164
}
165

    
166
static void handle_response(int frame, int received) {
167
  printf("handle response\n");
168
}
169

    
170
static void handle_receive(char type, int source, unsigned char* packet,
171
                           int len) {
172
  ColonetRobotServerPacket pkt;
173
  pkt.client_id = packet[0] | (packet[1]<<8) | (packet[2]<<16) | (packet[3]<<24); //little endian
174

    
175
  memcpy(pkt.data, packet + 5, PACKET_DATA_LEN);
176

    
177
  if (logging_enabled) {
178
    log_packet(packet, len);
179
  }
180

    
181
  message_handler(type, source, pkt.client_id, packet, len);
182

    
183
  printf("handle receive\n");
184
}
185

    
186
static void unregister(void) {
187
  printf("unregister\n");
188
}
189

    
190
/** @brief Analogous to the "SIGNAL" or "ISR" function on the robots.
191
 * Listens for bytes on the wireless port and constructs packets based on them.
192
 * Not part of the ColonetWireless class since a function pointer must be
193
 * passed in starting the thread that runs it (tricky or impossible if it's
194
 * a class function).
195
 *
196
 * @param args Pointer to arguments.  Can be safely casted to ListenerArgs type
197
 * @return NULL
198
 */
199
static void* listen(void* args) {
200
  printf("Called listen.\n");
201

    
202
  PacketGroupHandler pgh = {COLONET_PACKET_GROUP_ID,
203
                            timeout_handler,
204
                            handle_response,
205
                            handle_receive,
206
                            unregister};
207
  wl_register_packet_group(&pgh);
208

    
209
  while (1) {
210
    wl_do();
211
  }
212

    
213
  wl_terminate();
214
  pthread_exit(NULL);
215
  return NULL;
216
}
217

    
218
/** @brief
219
 *
220
 * @param pkt Packet to be logged
221
 *
222
 * @return 0 on success, -1 on failure
223
 */
224
int log_packet(unsigned char* packet, int len) {
225
  FILE* logfile = fopen(log_filename, "a");
226

    
227
  if (logfile == NULL) {
228
    dbg_printf("%s: Error - fopen %s failed.\n", log_filename, __FUNCTION__);
229
    return -1;
230
  }
231

    
232
  for (int i = 0; i < len; i++) {
233
    fprintf(logfile, "%d ", *((unsigned char*)packet + i));
234
  }
235
  fprintf(logfile, "\n");
236

    
237
  fclose(logfile);
238
  return 0;
239
}