Fixes reconnecting the ZigBee controller after a reset during runtime
Resets may occur by unplugging the stick or calling a softReset() from the software side. Additionally resets the stick when 5 subsequent timeouts happen as there are firmwares of the CC2652 available which tend to crash occationally.pull/79/head
parent
0f18424d6d
commit
22837865f1
|
|
@ -99,6 +99,7 @@ void ZigbeeInterfaceTi::setAvailable(bool available)
|
|||
|
||||
void ZigbeeInterfaceTi::onReconnectTimeout()
|
||||
{
|
||||
qCDebug(dcZigbeeInterface()) << "Reconnecting to serial port...";
|
||||
if (m_serialPort && !m_serialPort->isOpen()) {
|
||||
if (!m_serialPort->open(QSerialPort::ReadWrite)) {
|
||||
setAvailable(false);
|
||||
|
|
@ -169,9 +170,7 @@ void ZigbeeInterfaceTi::onError(const QSerialPort::SerialPortError &error)
|
|||
{
|
||||
if (error != QSerialPort::NoError && m_serialPort->isOpen()) {
|
||||
qCWarning(dcZigbeeInterface()) << "Serial port error:" << error << m_serialPort->errorString();
|
||||
m_reconnectTimer->start();
|
||||
m_serialPort->close();
|
||||
setAvailable(false);
|
||||
reconnectController();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +206,7 @@ void ZigbeeInterfaceTi::sendPacket(Ti::CommandType type, Ti::SubSystem subSystem
|
|||
|
||||
bool ZigbeeInterfaceTi::enable(const QString &serialPort, qint32 baudrate)
|
||||
{
|
||||
qCDebug(dcZigbeeInterface()) << "Start UART interface " << serialPort << baudrate;
|
||||
qCDebug(dcZigbeeInterface()) << "Starting UART interface " << serialPort << baudrate;
|
||||
|
||||
if (m_serialPort) {
|
||||
delete m_serialPort;
|
||||
|
|
@ -243,13 +242,18 @@ void ZigbeeInterfaceTi::reconnectController()
|
|||
if (!m_serialPort)
|
||||
return;
|
||||
|
||||
if (m_serialPort->isOpen())
|
||||
if (m_serialPort->isOpen()) {
|
||||
m_serialPort->close();
|
||||
}
|
||||
|
||||
QString portName = m_serialPort->portName();
|
||||
int baudrate = m_serialPort->baudRate();
|
||||
setAvailable(false);
|
||||
|
||||
delete m_serialPort;
|
||||
m_serialPort = nullptr;
|
||||
setAvailable(false);
|
||||
m_reconnectTimer->start();
|
||||
|
||||
enable(portName, baudrate);
|
||||
}
|
||||
|
||||
void ZigbeeInterfaceTi::disable()
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ Ti::StatusCode ZigbeeInterfaceTiReply::statusCode() const
|
|||
return m_statusCode;
|
||||
}
|
||||
|
||||
bool ZigbeeInterfaceTiReply::timendOut() const
|
||||
bool ZigbeeInterfaceTiReply::timedOut() const
|
||||
{
|
||||
return m_timeout;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public:
|
|||
// Response content
|
||||
Ti::StatusCode statusCode() const;
|
||||
|
||||
bool timendOut() const;
|
||||
bool timedOut() const;
|
||||
bool aborted() const;
|
||||
void abort();
|
||||
|
||||
|
|
|
|||
|
|
@ -72,14 +72,22 @@ ZigbeeInterfaceTiReply* ZigbeeBridgeControllerTi::reset()
|
|||
stream << static_cast<quint8>(Ti::ResetTypeSoft);
|
||||
ZigbeeInterfaceTiReply *resetReply = sendCommand(Ti::SubSystemSys, Ti::SYSCommandResetReq, payload);
|
||||
waitFor(resetReply, Ti::SubSystemSys, Ti::SYSCommandResetInd);
|
||||
connect(resetReply, &ZigbeeInterfaceTiReply::finished, this, [=](){
|
||||
m_interface->reconnectController();
|
||||
});
|
||||
return resetReply;
|
||||
}
|
||||
|
||||
ZigbeeInterfaceTiReply *ZigbeeBridgeControllerTi::init()
|
||||
{
|
||||
m_registeredEndpointIds.clear();
|
||||
|
||||
ZigbeeInterfaceTiReply *initReply = new ZigbeeInterfaceTiReply(this, 15000);
|
||||
|
||||
ZigbeeInterfaceTiReply *resetReply = reset();
|
||||
// Not using public reset() as that will start the init from scratch by reconnecting the controller
|
||||
NEW_PAYLOAD
|
||||
stream << static_cast<quint8>(Ti::ResetTypeSoft);
|
||||
ZigbeeInterfaceTiReply *resetReply = sendCommand(Ti::SubSystemSys, Ti::SYSCommandResetReq, payload);
|
||||
connect(resetReply, &ZigbeeInterfaceTiReply::finished, initReply, [=]() {
|
||||
|
||||
qCDebug(dcZigbeeController()) << "Skipping CC2530/CC2531 bootloader.";
|
||||
|
|
@ -486,17 +494,25 @@ void ZigbeeBridgeControllerTi::sendNextRequest()
|
|||
|
||||
ZigbeeInterfaceTiReply *ZigbeeBridgeControllerTi::sendCommand(Ti::SubSystem subSystem, quint8 command, const QByteArray &payload, int timeout)
|
||||
{
|
||||
// Create the reply
|
||||
ZigbeeInterfaceTiReply *reply = new ZigbeeInterfaceTiReply(subSystem, command, this, payload, timeout);
|
||||
|
||||
// Make sure we clean up on timeout
|
||||
connect(reply, &ZigbeeInterfaceTiReply::timeout, this, [reply](){
|
||||
qCWarning(dcZigbeeController()) << "Reply timeout" << reply;
|
||||
// Note: send next reply with the finished signal
|
||||
});
|
||||
connect(reply, &ZigbeeInterfaceTiReply::finished, reply, [=](){
|
||||
|
||||
if (reply->timedOut()) {
|
||||
if (m_controllerState == ControllerStateRunning) {
|
||||
qCWarning(dcZigbeeController()) << "Interface command timed out.";
|
||||
if (++m_timeouts < 5) {
|
||||
qCInfo(dcZigbeeController()) << "Retrying..." << m_timeouts << "/" << 5;
|
||||
sendCommand(subSystem, command, payload, timeout);
|
||||
} else {
|
||||
qCInfo(dcZigbeeController()) << "Resetting ZigBee interface";
|
||||
m_interface->reconnectController();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_timeouts = 0;
|
||||
}
|
||||
|
||||
// Auto delete the object on finished
|
||||
connect(reply, &ZigbeeInterfaceTiReply::finished, reply, [this, reply](){
|
||||
if (m_currentReply == reply) {
|
||||
m_currentReply = nullptr;
|
||||
QMetaObject::invokeMethod(this, "sendNextRequest", Qt::QueuedConnection);
|
||||
|
|
@ -731,6 +747,9 @@ void ZigbeeBridgeControllerTi::onInterfaceAvailableChanged(bool available)
|
|||
ZigbeeInterfaceTiReply *reply = m_replyQueue.dequeue();
|
||||
reply->abort();
|
||||
}
|
||||
|
||||
m_controllerState = ControllerStateDown;
|
||||
emit controllerStateChanged(m_controllerState);
|
||||
}
|
||||
|
||||
setAvailable(available);
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ private:
|
|||
QTimer m_permitJoinTimer;
|
||||
|
||||
QList<int> m_registeredEndpointIds;
|
||||
int m_timeouts = 0;
|
||||
|
||||
void finishRequest(Ti::StatusCode statusCode = Ti::StatusCodeSuccess);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ ZigbeeClusterReply *ZigbeeCluster::createClusterReply(const ZigbeeNetworkRequest
|
|||
zclReply->m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
|
||||
m_pendingReplies.insert(zclReply->transactionSequenceNumber(), zclReply);
|
||||
connect(zclReply, &ZigbeeClusterReply::finished, this, [this, zclReply](){
|
||||
qCDebug(dcZigbeeCluster()) << "ZCL request to" << zclReply->request().destinationShortAddress() << "finished with status:" << zclReply->error();
|
||||
zclReply->deleteLater();
|
||||
m_pendingReplies.remove(zclReply->transactionSequenceNumber());
|
||||
});
|
||||
|
|
@ -367,6 +368,7 @@ bool ZigbeeCluster::verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetwo
|
|||
case ZigbeeNetworkReply::ErrorNoError:
|
||||
// The request has been transported successfully to he destination, now
|
||||
// wait for the expected indication or check if we already recieved it
|
||||
qCDebug(dcZigbeeCluster()) << "ZCL request sent. Waiting for response data indication...";
|
||||
zclReply->m_apsConfirmReceived = true;
|
||||
if (!zclReply->m_zclIndicationReceived) {
|
||||
zclReply->m_timeoutTimer.start();
|
||||
|
|
|
|||
Loading…
Reference in New Issue