XbeeLink.cpp 5.03 KB
Newer Older
Franz's avatar
Franz committed
1 2 3 4 5 6 7 8 9
#include <qdebug.h>
#include <QThread>
#include <QMutex>
#include <MG.h>
#include <configuration.h>
#include<string>
#include "XbeeLink.h"

XbeeLink::XbeeLink(QString portName, int baudRate) : 
Don Gagne's avatar
Don Gagne committed
10 11 12 13 14 15 16 17
	m_xbeeCon(NULL),
    m_id(-1),
    m_portName(NULL),
    m_portNameLength(0),
    m_baudRate(baudRate),
    m_connected(false),
	m_addrHigh(0),
    m_addrLow(0)
Franz's avatar
Franz committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
{

	/* setup the xbee */
	this->setPortName(portName);
	
	//this->connect();
	// Set unique ID and add link to the list of links
	this->m_id = getNextLinkId();
	// set the Name
	this->m_name = tr("xbee link") + QString::number(this->m_id);
	emit nameChanged(this->m_name);
}

XbeeLink::~XbeeLink()
{
	if(m_portName)
	{
		delete m_portName;
		m_portName = NULL;
	}
38
	_disconnect();
Franz's avatar
Franz committed
39 40
}

41
QString XbeeLink::getPortName() const
Franz's avatar
Franz committed
42 43 44 45 46 47 48 49 50
{
	QString portName;
	for(unsigned int i = 0;i<this->m_portNameLength;i++)
	{
		portName.append(this->m_portName[i]);
	}
	return portName;
}

51
int XbeeLink::getBaudRate() const
Franz's avatar
Franz committed
52 53 54 55 56 57 58 59 60
{
	return this->m_baudRate;
}

bool XbeeLink::setPortName(QString portName)
{
	bool reconnect(false);
	if(this->m_connected)
	{
61
		_disconnect();
Franz's avatar
Franz committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75
		reconnect = true;
	}
	if(m_portName)
	{
		delete m_portName;
		m_portName = NULL;
	}
	QStringList list = portName.split(QRegExp("\\s+"),QString::SkipEmptyParts);
	if(list.size()>0)
	{
		this->m_portNameLength = list[0].size()+1;
		m_portName = new char[this->m_portNameLength];
		for(int i=0;i<list[0].size();i++)
		{
76
			this->m_portName[i]=list[0][i].toLatin1();
Franz's avatar
Franz committed
77 78 79 80 81 82 83 84 85 86 87 88 89
		}
		this->m_portName[list[0].size()] = '\0';
	}
	else
	{
		this->m_portNameLength = 1;
		m_portName = new char[this->m_portNameLength];
		this->m_portName[0] = '\0';
	}
	
	bool retVal(true);
	if(reconnect)
	{
90
		retVal = _connect();
Franz's avatar
Franz committed
91 92 93 94 95 96 97 98 99 100
	}

	return retVal;
}

bool XbeeLink::setBaudRate(int rate)
{
	bool reconnect(false);
	if(this->m_connected)
	{
101
		_disconnect();
Franz's avatar
Franz committed
102 103 104 105 106 107
		reconnect = true;
	}
	bool retVal(true);
	this->m_baudRate = rate;
	if(reconnect)
	{
108
		retVal = _connect();
Franz's avatar
Franz committed
109 110 111 112
	}
	return retVal;
}

113
int XbeeLink::getId() const
Franz's avatar
Franz committed
114 115 116 117
{
	return this->m_id;
}

118
QString XbeeLink::getName() const
Franz's avatar
Franz committed
119 120 121 122
{
	return this->m_name;
}

123
bool XbeeLink::isConnected() const
Franz's avatar
Franz committed
124 125 126 127
{
	return this->m_connected;
}

128
qint64 XbeeLink::getConnectionSpeed() const
Franz's avatar
Franz committed
129 130 131
{
	return this->m_baudRate;
}
132 133 134 135 136 137 138 139 140 141 142

qint64 XbeeLink::getCurrentInDataRate() const
{
    return 0;
}

qint64 XbeeLink::getCurrentOutDataRate() const
{
    return 0;
}

Franz's avatar
Franz committed
143 144
bool XbeeLink::hardwareConnect()
{
oberion's avatar
oberion committed
145
	emit tryConnectBegin(true);
Franz's avatar
Franz committed
146 147
	if(this->isConnected())
	{
148
		_disconnect();
Franz's avatar
Franz committed
149 150 151 152 153 154 155 156 157
	}
	if (*this->m_portName == '\0')
	{
		return false;
	}
	if (xbee_setupAPI(this->m_portName,this->m_baudRate,0x2B,0x3E8) == -1) 
		{
		  /* oh no... it failed */
			qDebug() <<"xbee_setup() failed...\n";
oberion's avatar
oberion committed
158
			emit tryConnectEnd(true);
Franz's avatar
Franz committed
159 160 161
			return false;
		}
	this->m_xbeeCon = xbee_newcon('A',xbee2_data,0x13A200,0x403D0935);
oberion's avatar
oberion committed
162
	emit tryConnectEnd(true);
Franz's avatar
Franz committed
163 164 165 166 167 168
	this->m_connected = true;
	emit connected();
	emit connected(true);
	return true;
}

169
bool XbeeLink::_connect(void)
Franz's avatar
Franz committed
170
{
171
	if (this->isRunning()) _disconnect();
Franz's avatar
Franz committed
172 173 174 175
    this->start(LowPriority);
    return true;
}

176
bool XbeeLink::_disconnect(void)
Franz's avatar
Franz committed
177 178 179 180 181
{
	if(this->isRunning()) this->terminate(); //stop running the thread, restart it upon connect

	if(this->m_xbeeCon)
	{
oberion's avatar
oberion committed
182
		xbee_end();
Franz's avatar
Franz committed
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
		this->m_xbeeCon = NULL;
	}
	this->m_connected = false;

	emit disconnected();
	emit connected(false);
	return true;
}

void XbeeLink::writeBytes(const char *bytes, qint64 length)  // TO DO: delete the data array
{
	char *data;
	data = new char[length];
	for(long i=0;i<length;i++)
	{
		data[i] = bytes[i];
	}
	if(!xbee_nsenddata(this->m_xbeeCon,data,length)) // return value of 0 is successful written
	{
202 203 204
        // Log the amount and time written out for future data rate calculations.
        QMutexLocker dataRateLocker(&dataRateMutex);
        logDataRateToBuffer(outDataWriteAmounts, outDataWriteTimes, &outDataIndex, length, QDateTime::currentMSecsSinceEpoch());
Franz's avatar
Franz committed
205 206 207
	}
	else
	{
208
		_disconnect();
Franz's avatar
Franz committed
209 210 211 212 213 214 215 216 217 218 219 220 221 222
		emit communicationError(this->getName(), tr("Could not send data - link %1 is disconnected!").arg(this->getName()));
	}
}

void XbeeLink::readBytes()
{
	xbee_pkt *xbeePkt;
	xbeePkt = xbee_getpacketwait(this->m_xbeeCon);
	if(!(NULL==xbeePkt))
	{
		QByteArray data;
		for(unsigned int i=0;i<=xbeePkt->datalen;i++)
		{
			data.push_back(xbeePkt->data[i]);
223 224 225 226 227 228 229
        }

        emit bytesReceived(this, data);

        // Log the amount and time received for future data rate calculations.
        QMutexLocker dataRateLocker(&dataRateMutex);
        logDataRateToBuffer(inDataWriteAmounts, inDataWriteTimes, &inDataIndex, data.length(), QDateTime::currentMSecsSinceEpoch());
Franz's avatar
Franz committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
	}
}

void XbeeLink::run()
{
    // Initialize the connection
	if(this->hardwareConnect())
	{
		// Qt way to make clear what a while(1) loop does
		forever 
		{
			this->readBytes();
	    }
	}
}

oberion's avatar
oberion committed
246 247 248 249 250 251 252 253 254 255 256 257
bool XbeeLink::setRemoteAddressHigh(quint32 high)
{
	this->m_addrHigh = high;
	return true;
}

bool XbeeLink::setRemoteAddressLow(quint32 low)
{
	this->m_addrLow = low;
	return true;
}

Franz's avatar
Franz committed
258 259 260 261 262 263 264 265 266
/*
void CALLTYPE XbeeLink::portCallback(xbee_con *xbeeCon, xbee_pkt *XbeePkt)
{
	QByteArray buf;
	for(quint8 i=0;i<XbeePkt->datalen;i++)
	{
		buf.push_back(XbeePkt->data[i]);
	}
	emit bytesReceived(this, buf);
267
}*/