Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SensorNetwork.cpp
00001 /************************************************************************************** 00002 * Copyright (c) 2016, Tomoaki Yamaguchi 00003 * 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * and the Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * Tomoaki Yamaguchi - initial API and implementation 00015 **************************************************************************************/ 00016 00017 #include <stdio.h> 00018 #include <unistd.h> 00019 #include <termios.h> 00020 #include <fcntl.h> 00021 #include <string.h> 00022 #include <stdlib.h> 00023 #include <sys/time.h> 00024 #include <sys/types.h> 00025 #include <sys/select.h> 00026 #include "SensorNetwork.h" 00027 #include "MQTTSNGWProcess.h" 00028 00029 using namespace std; 00030 using namespace MQTTSNGW; 00031 00032 /*=========================================== 00033 Class SensorNetAddreess 00034 ============================================*/ 00035 SensorNetAddress::SensorNetAddress() 00036 { 00037 memset(_address64, 0, 8); 00038 memset(_address16, 0, 2); 00039 } 00040 00041 SensorNetAddress::~SensorNetAddress() 00042 { 00043 00044 } 00045 00046 void SensorNetAddress::setAddress(uint8_t* address64, uint8_t* address16) 00047 { 00048 memcpy(_address64, address64, 8); 00049 memcpy(_address16, address16, 2); 00050 } 00051 00052 00053 int SensorNetAddress::setAddress(string* address64) 00054 { 00055 memcpy(_address64, address64->c_str(), 8); 00056 memset(_address16, 0, sizeof(_address16)); 00057 return 0; 00058 } 00059 00060 void SensorNetAddress::setBroadcastAddress(void) 00061 { 00062 memset(_address64, 0, 6); 00063 _address64[6] = 0xff; 00064 _address64[7] = 0xff; 00065 _address16[0] = 0xff; 00066 _address16[1] = 0xfe; 00067 } 00068 00069 bool SensorNetAddress::isMatch(SensorNetAddress* addr) 00070 { 00071 00072 return (memcmp(this->_address64, addr->_address64, 8 ) == 0 && memcmp(this->_address16, addr->_address16, 2) == 0); 00073 } 00074 00075 SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr) 00076 { 00077 memcpy(_address64, addr._address64, 8); 00078 memcpy(_address16, addr._address16, 2); 00079 return *this; 00080 } 00081 00082 char* SensorNetAddress::sprint(char* buf) 00083 { 00084 char* pbuf = buf; 00085 for ( int i = 0; i < 8; i++ ) 00086 { 00087 sprintf(pbuf, "%02X", _address64[i]); 00088 pbuf += 2; 00089 } 00090 return buf; 00091 } 00092 00093 /*=========================================== 00094 Class SensorNetwork 00095 ============================================*/ 00096 SensorNetwork::SensorNetwork() 00097 { 00098 00099 } 00100 00101 SensorNetwork::~SensorNetwork() 00102 { 00103 00104 } 00105 00106 int SensorNetwork::unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendToAddr) 00107 { 00108 return XBee::unicast(payload, payloadLength, sendToAddr); 00109 } 00110 00111 int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength) 00112 { 00113 return XBee::broadcast(payload, payloadLength); 00114 } 00115 00116 int SensorNetwork::read(uint8_t* buf, uint16_t bufLen) 00117 { 00118 return XBee::recv(buf, bufLen, &_clientAddr); 00119 } 00120 00121 int SensorNetwork::initialize(void) 00122 { 00123 char param[MQTTSNGW_PARAM_MAX]; 00124 uint32_t baudrate = 9600; 00125 uint8_t apimode = 2; 00126 00127 if (theProcess->getParam("ApiMode", param) == 0) 00128 { 00129 apimode = (uint8_t)atoi(param); 00130 } 00131 setApiMode(apimode); 00132 _description = "API mode "; 00133 sprintf(param, "%d", apimode); 00134 _description += param; 00135 00136 if (theProcess->getParam("Baudrate", param) == 0) 00137 { 00138 baudrate = (uint32_t)atoi(param); 00139 } 00140 _description += ", Baudrate "; 00141 sprintf(param ,"%d", baudrate); 00142 _description += param; 00143 00144 theProcess->getParam("SerialDevice", param); 00145 _description += ", SerialDevice "; 00146 _description += param; 00147 00148 return XBee::open(param, baudrate); 00149 } 00150 00151 const char* SensorNetwork::getDescription(void) 00152 { 00153 return _description.c_str(); 00154 } 00155 00156 SensorNetAddress* SensorNetwork::getSenderAddress(void) 00157 { 00158 return &_clientAddr; 00159 } 00160 00161 /*=========================================== 00162 Class XBee 00163 ============================================*/ 00164 XBee::XBee(){ 00165 _serialPort = new SerialPort(); 00166 _respCd = 0; 00167 _respId = 0; 00168 _dataLen = 0; 00169 _frameId = 0; 00170 _apiMode = 2; 00171 } 00172 00173 XBee::~XBee(){ 00174 if ( _serialPort ) 00175 { 00176 delete _serialPort; 00177 } 00178 } 00179 00180 int XBee::open(char* device, int baudrate) 00181 { 00182 int rate = B9600; 00183 00184 switch (baudrate) 00185 { 00186 case 9600: 00187 rate = B9600; 00188 break; 00189 case 19200: 00190 rate = B19200; 00191 break; 00192 case 38400: 00193 rate = B38400; 00194 break; 00195 case 57600: 00196 rate = B57600; 00197 break; 00198 case 115200: 00199 rate = B115200; 00200 break; 00201 default: 00202 return -1; 00203 } 00204 00205 return _serialPort->open(device, rate, false, 1, O_RDWR | O_NOCTTY); 00206 } 00207 00208 int XBee::broadcast(const uint8_t* payload, uint16_t payloadLen){ 00209 SensorNetAddress addr; 00210 addr.setBroadcastAddress(); 00211 return send(payload, (uint8_t) payloadLen, &addr); 00212 } 00213 00214 int XBee:: unicast(const uint8_t* payload, uint16_t payloadLen, SensorNetAddress* addr){ 00215 return send(payload, (uint8_t) payloadLen, addr); 00216 } 00217 00218 int XBee::recv(uint8_t* buf, uint16_t bufLen, SensorNetAddress* clientAddr) 00219 { 00220 uint8_t data[128]; 00221 int len; 00222 00223 while ( true ) 00224 { 00225 00226 if ( (len = readApiFrame(data)) > 0 ) 00227 { 00228 00229 if ( data[0] == API_RESPONSE ) 00230 { 00231 memcpy(clientAddr->_address64, data + 1, 8); 00232 memcpy(clientAddr->_address16, data + 9, 2); 00233 len -= 12; 00234 memcpy( buf, data + 12, len); 00235 return len; 00236 } 00237 else if ( data[0] == API_XMITSTATUS ) 00238 { 00239 _respCd = data[5]; 00240 _respId = data[1]; 00241 _sem.post(); 00242 } 00243 } 00244 else 00245 { 00246 return 0; 00247 } 00248 } 00249 } 00250 00251 int XBee::readApiFrame(uint8_t* recvData){ 00252 uint8_t buf; 00253 uint8_t pos = 0; 00254 uint8_t checksum = 0; 00255 uint8_t len = 0; 00256 00257 while ( _serialPort->recv(&buf) ) 00258 { 00259 if ( buf == START_BYTE) 00260 { 00261 pos = 1; 00262 D_NWSTACK("\r\n===> Recv: "); 00263 break; 00264 } 00265 } 00266 00267 if ( pos == 0 ) 00268 { 00269 goto errexit; 00270 } 00271 00272 if ( recv(&buf) < 0 ) // MSB length 00273 { 00274 goto errexit; 00275 } 00276 00277 if ( recv(&buf) < 0 ) // LSB length 00278 { 00279 goto errexit; 00280 } 00281 else 00282 { 00283 len = buf; 00284 } 00285 00286 pos = 0; 00287 while ( len-- ) 00288 { 00289 if ( recv(&buf) < 0 ) 00290 { 00291 goto errexit; 00292 } 00293 recvData[pos++] = buf; 00294 checksum += buf; 00295 } 00296 00297 recv(&buf); // checksum 00298 if ( (0xff - checksum ) == buf ){ 00299 D_NWSTACK(" checksum ok\r\n"); 00300 return pos; 00301 } 00302 else 00303 { 00304 D_NWSTACK(" checksum error %02x\r\n", 0xff - checksum); 00305 goto errexit; 00306 } 00307 errexit: 00308 _serialPort->flush(); 00309 return -1; 00310 } 00311 00312 int XBee::send(const uint8_t* payload, uint8_t pLen, SensorNetAddress* addr){ 00313 D_NWSTACK("\r\n===> Send: "); 00314 uint8_t checksum = 0; 00315 _respCd = -1; 00316 00317 _serialPort->send(START_BYTE); 00318 send(0x00); // Message Length 00319 send(14 + pLen); // Message Length 00320 00321 _serialPort->send(API_XMITREQUEST); // Transmit Request API 00322 checksum += API_XMITREQUEST; 00323 00324 if (_frameId++ == 0x00 ) // Frame ID 00325 { 00326 _frameId = 1; 00327 } 00328 send(_frameId); 00329 checksum += _frameId; 00330 00331 for ( int i = 0; i < 8; i++) // Address64 00332 { 00333 send(addr->_address64[i]); 00334 checksum += addr->_address64[i]; 00335 } 00336 for ( int i = 0; i < 2; i++) // Address16 00337 { 00338 send(addr->_address16[i]); 00339 checksum += addr->_address16[i]; 00340 } 00341 00342 send(0x00); // Broadcast Radius 00343 checksum += 0x00; 00344 00345 send(0x00); // Option: Use the extended transmission timeout 0x40 00346 checksum += 0x00; 00347 00348 D_NWSTACK("\r\n Payload: "); 00349 00350 for ( uint8_t i = 0; i < pLen; i++ ){ 00351 send(payload[i]); // Payload 00352 checksum += payload[i]; 00353 } 00354 00355 checksum = 0xff - checksum; 00356 D_NWSTACK(" checksum "); 00357 send(checksum); 00358 D_NWSTACK("\r\n"); 00359 00360 /* wait Txim Status 0x8B */ 00361 _sem.timedwait(XMIT_STATUS_TIME_OVER); 00362 00363 if ( _respCd || _frameId != _respId ) 00364 { 00365 D_NWSTACK(" frameId = %02x Not Acknowleged\r\n", _frameId); 00366 return -1; 00367 } 00368 return (int)pLen; 00369 } 00370 00371 void XBee::send(uint8_t c) 00372 { 00373 if(_apiMode == 2 && (c == START_BYTE || c == ESCAPE || c == XON || c == XOFF)){ 00374 _serialPort->send(ESCAPE); 00375 _serialPort->send(c ^ 0x20); 00376 }else{ 00377 _serialPort->send(c); 00378 } 00379 } 00380 00381 int XBee::recv(uint8_t* buf) 00382 { 00383 if (_serialPort->recv(buf) ) 00384 { 00385 if ( *buf == ESCAPE && _apiMode == 2 ) 00386 { 00387 _serialPort->recv(buf); 00388 *buf = 0x20 ^ *buf; 00389 } 00390 return 0; 00391 } 00392 return -1; 00393 } 00394 00395 void XBee::setApiMode(uint8_t mode) 00396 { 00397 _apiMode = mode; 00398 } 00399 00400 /*========================================= 00401 Class SerialPort 00402 =========================================*/ 00403 SerialPort::SerialPort() 00404 { 00405 _tio.c_iflag = IGNBRK | IGNPAR; 00406 _tio.c_cflag = CS8 | CLOCAL | CRTSCTS | CREAD; 00407 _tio.c_cc[VINTR] = 0; 00408 _tio.c_cc[VTIME] = 10; // 1 sec. 00409 _tio.c_cc[VMIN] = 1; 00410 _fd = 0; 00411 } 00412 00413 SerialPort::~SerialPort() 00414 { 00415 if (_fd) 00416 { 00417 ::close(_fd); 00418 } 00419 } 00420 00421 int SerialPort::open(char* devName, unsigned int baudrate, bool parity, 00422 unsigned int stopbit, unsigned int flg) 00423 { 00424 _fd = ::open(devName, flg); 00425 if (_fd < 0) 00426 { 00427 return _fd; 00428 } 00429 00430 if (parity) 00431 { 00432 _tio.c_cflag = _tio.c_cflag | PARENB; 00433 } 00434 if (stopbit == 2) 00435 { 00436 _tio.c_cflag = _tio.c_cflag | CSTOPB; 00437 } 00438 00439 if (cfsetspeed(&_tio, baudrate) < 0) 00440 { 00441 return errno; 00442 } 00443 return tcsetattr(_fd, TCSANOW, &_tio); 00444 } 00445 00446 bool SerialPort::send(unsigned char b) 00447 { 00448 if (write(_fd, &b, 1) < 0) 00449 { 00450 return false; 00451 } 00452 else 00453 { 00454 D_NWSTACK( " %02x", b); 00455 return true; 00456 } 00457 } 00458 00459 bool SerialPort::recv(unsigned char* buf) 00460 { 00461 struct timeval timeout; 00462 fd_set rfds; 00463 FD_ZERO(&rfds); 00464 FD_SET(_fd, &rfds); 00465 timeout.tv_sec = 0; 00466 timeout.tv_usec = 500000; // 500ms 00467 if ( select(_fd + 1, &rfds, 0, 0, &timeout) > 0 ) 00468 { 00469 if (read(_fd, buf, 1) > 0) 00470 { 00471 D_NWSTACK( " %02x",buf[0] ); 00472 return true; 00473 } 00474 } 00475 return false; 00476 } 00477 00478 void SerialPort::flush(void) 00479 { 00480 tcsetattr(_fd, TCSAFLUSH, &_tio); 00481 } 00482
Generated on Wed Jul 13 2022 10:46:03 by
1.7.2