00001
00032 #include "nanotron_swarm/cntronbase.h"
00033
00034 #include <unistd.h>
00035 #include <fcntl.h>
00036 #include <stdio.h>
00037 #include <iostream>
00038 #include <sstream>
00039 #include <string.h>
00040 #include <vector>
00041
00042 CNTronBase::CNTronBase(int baseId) {
00043 m_portHandler = 0;
00044 m_baseId = baseId;
00045 }
00046
00047 CNTronBase::~CNTronBase(void) {
00048 finish();
00049 }
00050
00051 int CNTronBase::getBaseId(void) const {
00052 return m_baseId;
00053 }
00054
00055 unsigned int CNTronBase::numBeacons() const {
00056 return m_nodes.size();
00057 }
00058
00059 void CNTronBase::printBeacons() const {
00060 int nodeID;
00061 int penalization, failures;
00062 std::map<int, CNTronNode>::const_iterator it;
00063
00064 std::cout << "\n[DEBUG] Detected Beacons (N = " << m_nodes.size() << "):"
00065 << std::endl;
00066 for (unsigned int i = 0; i < m_nodes.size(); i++) {
00067
00068 nodeID = m_nodeIDs[i];
00069
00070 penalization = m_nodes.at(nodeID).penalization;
00071 failures = m_nodes.at(nodeID).failures;
00072
00073 std::cout << "[DEBUG] Node " << nodeID << " - Penalization: "
00074 << penalization << " - Failures: " << failures << std::endl;
00075 }
00076 }
00077
00078
00079 int CNTronBase::init(const char *pDev) {
00080 struct termios my_termios;
00081
00082
00083 if (m_portHandler > 0)
00084 close(m_portHandler);
00085
00086
00087 m_portHandler = open(pDev, O_RDWR | O_NOCTTY);
00088 if (m_portHandler < 0)
00089 return -5;
00090
00091
00092 tcgetattr(m_portHandler, &my_termios);
00093 tcflush(m_portHandler, TCIOFLUSH);
00094
00095
00096 my_termios.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | IXON
00097 | INLCR | IGNCR | ICRNL);
00098 my_termios.c_iflag |= IGNBRK | IXOFF;
00099 my_termios.c_oflag &= ~(OPOST);
00100 my_termios.c_cflag |= CLOCAL | CREAD;
00101 my_termios.c_cflag &= ~PARENB;
00102 my_termios.c_cflag |= CS8;
00103 my_termios.c_cflag &= ~CSTOPB;
00104 my_termios.c_cflag &= ~CRTSCTS;
00105 my_termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | NOFLSH
00106 | TOSTOP | ISIG | IEXTEN);
00107 my_termios.c_cc[VMIN] = 1;
00108
00109
00110
00111
00112
00113 my_termios.c_cc[VTIME] = 2.5;
00114 cfsetispeed(&my_termios, B115200);
00115 cfsetospeed(&my_termios, B115200);
00116 tcsetattr(m_portHandler, TCSANOW, &my_termios);
00117
00118
00119 if (m_baseId == DEFAULT_ID)
00120 return readBaseID();
00121
00122
00123 return 0;
00124 }
00125
00126
00127 void CNTronBase::finish(void) {
00128
00129 if (m_portHandler > 0) {
00130 close(m_portHandler);
00131 m_portHandler = 0;
00132 }
00133 }
00134
00135
00136 int CNTronBase::readBaseID() {
00137 std::string cmd = READNODEID;
00138 int result, size;
00139 char c;
00140
00141
00142 result = sendCommand(cmd.c_str(), cmd.size());
00143 if (result < 0)
00144 return -1;
00145
00146
00147
00148
00149 c = 0;
00150 size = 0;
00151 while (c != '\n') {
00152 result = read(m_portHandler, &c, 1);
00153 if (result < 0) {
00154 usleep(10000);
00155 return -5;
00156 }
00157
00158 if (result == 1) {
00159 m_readBuff[size++] = c;
00160 }
00161 }
00162 m_readBuff[size] = '\0';
00163
00164
00165
00166
00167
00168
00169 char dirMAC[12];
00170 strncpy(dirMAC,m_readBuff,12);
00171
00172 m_baseId=chartohex(dirMAC);
00173
00174 return 0;
00175
00176
00177
00178
00179
00180 }
00181
00182
00183 int CNTronBase::sendCommand(const char* command, int size) {
00184 int i = 1;
00185 int dataWritten;
00186
00187 for (i = 0; i < size; i++) {
00188 dataWritten = write(m_portHandler, command + i, 1);
00189 if (dataWritten < 0)
00190 return -6;
00191 }
00192 return 0;
00193 }
00194
00195
00196 int CNTronBase::readRange(unsigned int node, CNTronRange& pData,
00197 std::string& msg) {
00198
00199 int result, size, err_code, returnCode;
00200 float range;
00201 char c;
00202 int nodeID;
00203 std::map<int, CNTronNode>::iterator it;
00204 CNTronNode nodeInf;
00205
00206 if (node < m_nodes.size()) {
00207 nodeID = m_nodeIDs[node];
00208 nodeInf = m_nodes[nodeID];
00209 } else {
00210 msg = "Node not detected";
00211 return -1;
00212 }
00213
00214 if (checkPenalization(nodeInf) != 0) {
00215 return 0;
00216 }
00217
00218
00219
00220 std::string cmd = RANGETO(nodeInf.mac);
00221 sendCommand(cmd.c_str(), cmd.length());
00222
00223
00224 c = 0;
00225 size = 0;
00226 while (c != '\n') {
00227 result = read(m_portHandler, &c, 1);
00228 if (result < 0) {
00229 usleep(10000);
00230 return -5;
00231 }
00232
00233 if (result == 1) {
00234 m_readBuff[size++] = c;
00235 }
00236 }
00237 m_readBuff[size] = '\0';
00238 sscanf(m_readBuff, "%d, %f, %*d", &err_code, &range);
00239
00240 returnCode = 0;
00241
00242
00243
00244
00245
00246
00247
00248 std::stringstream ss;
00249 switch (err_code) {
00250 case 0:
00251
00252 nodeInf.failures = 0;
00253 pData.beaconId = nodeInf.id;
00254
00255
00256 pData.emitterId = m_baseId;
00257 pData.range = range;
00258
00259 if (range < 0) {
00260 msg = "[WARNING] Negative range received";
00261 } else {
00262 returnCode = 1;
00263 }
00264
00265 break;
00266 case 2:
00267
00268
00269
00270
00271 case 3:
00272 nodeInf.failures++;
00273
00274
00275
00276
00277 break;
00278 case 4:
00279 msg = "[WARNING] Timeout while ranging with " + nodeInf.id;
00280 break;
00281 default:
00282
00283 break;
00284 }
00285
00286 if (nodeInf.failures >= MAX_NO_ACK) {
00287 nodeInf.penalization = PENALIZACION;
00288 if (clock_gettime(CLOCK_MONOTONIC_RAW, &nodeInf.penalizationTime)
00289 == -1) {
00290 nodeInf.penalizationTime.tv_sec = 0;
00291 nodeInf.penalizationTime.tv_nsec = 0;
00292 }
00293 }
00294
00295 m_nodes[nodeID] = nodeInf;
00296
00297 return returnCode;
00298 }
00299
00300 int CNTronBase::checkPenalization(CNTronNode& nodeInf) {
00301 timespec now;
00302 long delay = -1;
00303
00304 if (nodeInf.penalization > 0) {
00305 if (clock_gettime(CLOCK_MONOTONIC_RAW, &now) != -1) {
00306 delay = now.tv_sec
00307 - nodeInf.penalizationTime.tv_sec;
00308 }
00309
00310 if (delay > 0 && delay > MAX_PENALIZATION_TIME) {
00311 nodeInf.penalization = 0;
00312 nodeInf.failures = 0;
00313 }
00314 }
00315
00316 return nodeInf.penalization;
00317 }
00318
00319
00320 int CNTronBase::detectBeacons() {
00321 int result, size, lines, line = 0, age;
00322 char c;
00323 std::string cmd = GETBEACONS(255);
00324 char id[12];
00325 CNTronNode node;
00326
00327 result = sendCommand(cmd.c_str(), cmd.size());
00328 if (result < 0)
00329 return -1;
00330
00331
00332 c = 0;
00333 while (c != '#') {
00334 result = read(m_portHandler, &c, 1);
00335 if (result < 0) {
00336 usleep(10000);
00337 return -5;
00338 }
00339 }
00340
00341
00342 c = 0;
00343 size = 0;
00344 while (c != '\n') {
00345 result = read(m_portHandler, &c, 1);
00346 if (result < 0) {
00347 usleep(10000);
00348 return -5;
00349 }
00350 if (result == 1) {
00351 m_readBuff[size++] = c;
00352 }
00353 }
00354 m_readBuff[size] = '\0';
00355 sscanf(m_readBuff, "%d", &lines);
00356
00357
00358 for (line = 1; line <= lines; line++) {
00359
00360 c = 0;
00361 size = 0;
00362 while (c != '\n') {
00363 result = read(m_portHandler, &c, 1);
00364 if (result < 0) {
00365 usleep(10000);
00366 return -5;
00367 }
00368
00369 if (result == 1) {
00370 m_readBuff[size++] = c;
00371 }
00372 }
00373
00374
00375 if (line >= 3) {
00376 m_readBuff[size] = '\0';
00377
00378 sscanf(m_readBuff, "%d:%s", &age, id);
00379
00380 if (age <= MAX_AGE) {
00381
00382 int nodeID = chartohex(id);
00383 if (m_nodes.count(nodeID) == 0) {
00384 node.failures = 0;
00385 node.penalization = 0;
00386 node.id = nodeID;
00387
00388 strncpy(node.mac, id, 12);
00389 node.mac[12] = '\0';
00390
00391 m_nodes[nodeID] = node;
00392 m_nodeIDs.push_back(nodeID);
00393 } else {
00394 if (checkPenalization(m_nodes[nodeID]) > 0) {
00395 m_nodes[nodeID].penalization--;
00396 }
00397 }
00398 }
00399 }
00400 }
00401
00402 #if DEBUG
00403 printBeacons();
00404 #endif
00405
00406 return 0;
00407 }
00408
00409 int CNTronBase::chartohex(char * cnum) {
00410 int result = 0;
00411 int num[2];
00412 int i;
00413
00414 i = 10;
00415 if ((cnum[i] >= 'A') && (cnum[i] <= 'F'))
00416 num[1] = (cnum[i] - 'A') + 10;
00417 else
00418 num[1] = (cnum[i] - '0');
00419
00420 i = 11;
00421 if ((cnum[i] >= 'A') && (cnum[i] <= 'F'))
00422 num[0] = (cnum[i] - 'A') + 10;
00423 else
00424 num[0] = (cnum[i] - '0');
00425
00426 result = num[1] * 16 + num[0];
00427
00428 return result;
00429 }