XbeeLink.cpp 4.72 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
	m_xbeeCon(NULL),
    m_portName(NULL),
    m_portNameLength(0),
    m_baudRate(baudRate),
    m_connected(false),
	m_addrHigh(0),
    m_addrLow(0)
Franz's avatar
Franz committed
17 18 19 20 21 22 23 24 25 26 27 28 29
{

	/* setup the xbee */
	this->setPortName(portName);
}

XbeeLink::~XbeeLink()
{
	if(m_portName)
	{
		delete m_portName;
		m_portName = NULL;
	}
30
	_disconnect();
Franz's avatar
Franz committed
31 32
}

33
QString XbeeLink::getPortName() const
Franz's avatar
Franz committed
34 35 36 37 38 39 40 41 42
{
	QString portName;
	for(unsigned int i = 0;i<this->m_portNameLength;i++)
	{
		portName.append(this->m_portName[i]);
	}
	return portName;
}

43
int XbeeLink::getBaudRate() const
Franz's avatar
Franz committed
44 45 46 47 48 49 50 51 52
{
	return this->m_baudRate;
}

bool XbeeLink::setPortName(QString portName)
{
	bool reconnect(false);
	if(this->m_connected)
	{
53
		_disconnect();
Franz's avatar
Franz committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67
		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++)
		{
68
			this->m_portName[i]=list[0][i].toLatin1();
Franz's avatar
Franz committed
69 70 71 72 73 74 75 76 77 78 79 80 81
		}
		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)
	{
82
		retVal = _connect();
Franz's avatar
Franz committed
83 84 85 86 87 88 89 90 91 92
	}

	return retVal;
}

bool XbeeLink::setBaudRate(int rate)
{
	bool reconnect(false);
	if(this->m_connected)
	{
93
		_disconnect();
Franz's avatar
Franz committed
94 95 96 97 98 99
		reconnect = true;
	}
	bool retVal(true);
	this->m_baudRate = rate;
	if(reconnect)
	{
100
		retVal = _connect();
Franz's avatar
Franz committed
101 102 103 104
	}
	return retVal;
}

105
QString XbeeLink::getName() const
Franz's avatar
Franz committed
106 107 108 109
{
	return this->m_name;
}

110
bool XbeeLink::isConnected() const
Franz's avatar
Franz committed
111 112 113 114
{
	return this->m_connected;
}

115
qint64 XbeeLink::getConnectionSpeed() const
Franz's avatar
Franz committed
116 117 118
{
	return this->m_baudRate;
}
119 120 121 122 123 124 125 126 127 128 129

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

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

Franz's avatar
Franz committed
130 131
bool XbeeLink::hardwareConnect()
{
oberion's avatar
oberion committed
132
	emit tryConnectBegin(true);
Franz's avatar
Franz committed
133 134
	if(this->isConnected())
	{
135
		_disconnect();
Franz's avatar
Franz committed
136 137 138 139 140 141 142 143 144
	}
	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
145
			emit tryConnectEnd(true);
Franz's avatar
Franz committed
146 147 148
			return false;
		}
	this->m_xbeeCon = xbee_newcon('A',xbee2_data,0x13A200,0x403D0935);
oberion's avatar
oberion committed
149
	emit tryConnectEnd(true);
Franz's avatar
Franz committed
150 151 152 153 154
	this->m_connected = true;
	emit connected();
	return true;
}

155
bool XbeeLink::_connect(void)
Franz's avatar
Franz committed
156
{
157
	if (this->isRunning()) _disconnect();
Franz's avatar
Franz committed
158 159 160 161
    this->start(LowPriority);
    return true;
}

162
bool XbeeLink::_disconnect(void)
Franz's avatar
Franz committed
163 164 165 166 167
{
	if(this->isRunning()) this->terminate(); //stop running the thread, restart it upon connect

	if(this->m_xbeeCon)
	{
oberion's avatar
oberion committed
168
		xbee_end();
Franz's avatar
Franz committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
		this->m_xbeeCon = NULL;
	}
	this->m_connected = false;

	emit disconnected();
	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
	{
187 188 189
        // 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
190 191 192
	}
	else
	{
193
		_disconnect();
194
		emit communicationError(tr("Link Error"), QString("Error on link: %1. Could not send data - link is disconnected!").arg(getName()));
Franz's avatar
Franz committed
195 196 197 198 199 200 201 202 203 204 205 206 207
	}
}

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]);
208 209 210 211 212 213 214
        }

        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
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
	}
}

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
231 232 233 234 235 236 237 238 239 240 241 242
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
243 244 245 246 247 248 249 250 251
/*
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);
252
}*/