First Commit of MQTT-SN Gateway

Add    new SensorNetwork XBee
Add    a sensor network type in a start message.
Update MQTTSNClient to avoid build warning.
Update WiringPi's functions to my original ones. 
BugFix check msgId before adding waitdTopicId table.
BugFix Process termination procedures
Update print curent time in millseconds.
update move currentDateTime() to linux directory.
Bugfix: blink blue lightiIndicator.
Bugfix: Register returns wrong id.
change a status of the client to Disconnected.
change client status procedure
Update README
BugFix: change Network Disconnect procedures.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
This commit is contained in:
tomoaki
2016-05-13 19:18:47 +09:00
parent 826b2a83b0
commit 64fa07b391
63 changed files with 9206 additions and 1138 deletions

View File

@@ -0,0 +1,434 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation
**************************************************************************************/
#include "SensorNetwork.h"
#include "MQTTSNGWProcess.h"
#include "Threading.h"
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
using namespace std;
using namespace MQTTSNGW;
/*===========================================
Class SensorNetAddreess
============================================*/
SensorNetAddress::SensorNetAddress()
{
memset(_address64, 0, sizeof(_address64));
memset(_address16, 0, sizeof(_address16));
}
SensorNetAddress::~SensorNetAddress()
{
}
void SensorNetAddress::setAddress(uint8_t* address64, uint8_t* address16)
{
memcpy(_address64, address64, 8);
memcpy(_address16, address16, 2);
}
int SensorNetAddress::setAddress(string* address64)
{
memcpy(_address64, address64->c_str(), 8);
memset(_address16, 0, sizeof(_address16));
return 0;
}
void SensorNetAddress::setBroadcastAddress(void)
{
memset(_address64, 0, 6);
_address64[6] = 0xff;
_address64[7] = 0xff;
_address16[0] = 0xff;
_address16[1] = 0xfe;
}
bool SensorNetAddress::isMatch(SensorNetAddress* addr)
{
return (memcmp(this->_address64, addr->_address64, 8 ) == 0 && memcmp(this->_address16, addr->_address16, 2) == 0);
}
SensorNetAddress& SensorNetAddress::operator =(SensorNetAddress& addr)
{
memcpy(_address64, addr._address64, 8);
memcpy(_address16, addr._address16, 2);
return *this;
}
/*===========================================
Class SensorNetwork
============================================*/
SensorNetwork::SensorNetwork()
{
}
SensorNetwork::~SensorNetwork()
{
}
int SensorNetwork::unicast(const uint8_t* payload, uint16_t payloadLength, SensorNetAddress* sendToAddr)
{
return XBee::unicast(payload, payloadLength, sendToAddr);
}
int SensorNetwork::broadcast(const uint8_t* payload, uint16_t payloadLength)
{
return XBee::broadcast(payload, payloadLength);
}
int SensorNetwork::read(uint8_t* buf, uint16_t bufLen)
{
return XBee::recv(buf, bufLen, &_clientAddr);
}
int SensorNetwork::initialize(void)
{
char param[MQTTSNGW_PARAM_MAX];
uint16_t baudrate = 9600;
if (theProcess->getParam("Baudrate", param) == 0)
{
baudrate = (uint16_t)atoi(param);
}
theProcess->getParam("SerialDevice", param);
return XBee::open(param, baudrate);
}
const char* SensorNetwork::getType(void)
{
return "XBee";
}
/*===========================================
Class XBee
============================================*/
XBee::XBee(){
_serialPort = new SerialPort();
_respCd = 0;
_dataLen = 0;
_frameId = 0;
}
XBee::~XBee(){
if ( _serialPort )
{
delete _serialPort;
}
}
int XBee::open(char* device, int baudrate)
{
int rate = B9600;
switch (baudrate)
{
case 9600:
rate = B9600;
break;
case 19200:
rate = B19200;
break;
case 38400:
rate = B38400;
break;
case 57600:
rate = B57600;
break;
case 115200:
rate = B115200;
break;
default:
return -1;
}
return _serialPort->open(device, rate, false, 1, O_RDWR | O_NOCTTY);
}
int XBee::broadcast(const uint8_t* payload, uint16_t payloadLen){
SensorNetAddress addr;
addr.setBroadcastAddress();
send(payload, (uint8_t) payloadLen, &addr);
return 1;
}
int XBee:: unicast(const uint8_t* payload, uint16_t payloadLen, SensorNetAddress* addr){
send(payload, (uint8_t) payloadLen, addr);
return 1;
}
int XBee::recv(uint8_t* buf, uint16_t bufLen, SensorNetAddress* clientAddr)
{
uint8_t data[128];
int len;
while ( true )
{
if ( (len = readApiFrame(data)) > 0 )
{
if ( data[0] == API_RESPONSE )
{
memcpy(clientAddr->_address64, data + 1, 8);
memcpy(clientAddr->_address16, data + 9, 2);
len -= 12;
memcpy( buf, data + 12, len);
return len;
}
else if ( data[0] == API_XMITSTATUS )
{
_respCd = data[5];
_respId = data[1];
_sem.post();
}
}
}
}
int XBee::readApiFrame(uint8_t* recvData){
uint8_t buf;
uint8_t pos = 0;
uint8_t checksum = 0;
uint8_t len = 0;
while ( _serialPort->recv(&buf) )
{
if ( buf == START_BYTE)
{
pos = 1;
D_NWSTACK("\r\n===> Recv: ");
break;
}
}
if ( pos == 0 )
{
goto errexit;
}
if ( recv(&buf) < 0 ) // MSB length
{
goto errexit;
}
if ( recv(&buf) < 0 ) // LSB length
{
goto errexit;
}
else
{
len = buf;
}
pos = 0;
while ( len-- )
{
if ( recv(&buf) < 0 )
{
goto errexit;
}
recvData[pos++] = buf;
checksum += buf;
}
recv(&buf); // checksum
if ( (0xff - checksum ) == buf ){
D_NWSTACK(" checksum ok\r\n");
return pos;
}
else
{
D_NWSTACK(" checksum error %02x\r\n", 0xff - checksum);
goto errexit;
}
errexit:
_serialPort->flush();
return -1;
}
int XBee::send(const uint8_t* payload, uint8_t pLen, SensorNetAddress* addr){
D_NWSTACK("\r\n===> Send: ");
uint8_t checksum = 0;
_respCd = -1;
_serialPort->send(START_BYTE);
send(0x00); // Message Length
send(14 + pLen); // Message Length
_serialPort->send(API_XMITREQUEST); // Transmit Request API
checksum += API_XMITREQUEST;
if (_frameId++ == 0x00 ) // Frame ID
{
_frameId = 1;
}
send(_frameId);
checksum += _frameId;
for ( int i = 0; i < 8; i++) // Address64
{
send(addr->_address64[i]);
checksum += addr->_address64[i];
}
for ( int i = 0; i < 2; i++) // Address16
{
send(addr->_address16[i]);
checksum += addr->_address16[i];
}
send(0x00); // Broadcast Radius
checksum += 0x00;
send(0x00); // Option: Use the extended transmission timeout 0x40
checksum += 0x00;
D_NWSTACK("\r\n Payload: ");
for ( uint8_t i = 0; i < pLen; i++ ){
send(payload[i]); // Payload
checksum += payload[i];
}
checksum = 0xff - checksum;
D_NWSTACK(" checksum ");
send(checksum);
D_NWSTACK("\r\n");
/* wait Txim Status 0x8B */
_sem.timedwait(5000); // 5sec
if ( _respCd || _frameId != _respId )
{
D_NWSTACK(" frameId = %02x Not Acknowleged\r\n", _frameId);
return -1;
}
return 0;
}
void XBee::send(uint8_t c)
{
if(c == START_BYTE || c == ESCAPE || c == XON || c == XOFF){
_serialPort->send(ESCAPE);
_serialPort->send(c ^ 0x20);
}else{
_serialPort->send(c);
}
}
int XBee::recv(uint8_t* buf)
{
if (_serialPort->recv(buf) )
{
if ( *buf == ESCAPE)
{
_serialPort->recv(buf);
*buf = 0x20 ^ *buf;
}
return 0;
}
return -1;
}
/*=========================================
Class SerialPort
=========================================*/
SerialPort::SerialPort()
{
_tio.c_iflag = IGNBRK | IGNPAR;
_tio.c_cflag = CS8 | CLOCAL | CRTSCTS;
_tio.c_cc[VINTR] = 0;
_tio.c_cc[VTIME] = 0;
_tio.c_cc[VMIN] = 1;
_fd = 0;
}
SerialPort::~SerialPort()
{
if (_fd)
{
::close(_fd);
}
}
int SerialPort::open(char* devName, unsigned int baudrate, bool parity,
unsigned int stopbit, unsigned int flg)
{
_fd = ::open(devName, flg);
if (_fd < 0)
{
return _fd;
}
if (parity)
{
_tio.c_cflag = _tio.c_cflag | PARENB;
}
if (stopbit == 2)
{
_tio.c_cflag = _tio.c_cflag | CSTOPB;
}
if (cfsetspeed(&_tio, baudrate) < 0)
{
return errno;
}
return tcsetattr(_fd, TCSANOW, &_tio);
}
bool SerialPort::send(unsigned char b)
{
if (write(_fd, &b, 1) < 0)
{
return false;
}
else
{
D_NWSTACK( " %02x", b);
return true;
}
}
bool SerialPort::recv(unsigned char* buf)
{
if (read(_fd, buf, 1) == 0)
{
return false;
}
else
{
D_NWSTACK( " %02x",buf[0] );
return true;
}
}
void SerialPort::flush(void)
{
tcsetattr(_fd, TCSAFLUSH, &_tio);
}