Merge PR #67: Deconz: Fixes for command queuing
This commit is contained in:
commit
6200856678
@ -84,7 +84,7 @@ ZigbeeInterfaceDeconzReply::ZigbeeInterfaceDeconzReply(Deconz::Command command,
|
|||||||
m_timer(new QTimer(this)),
|
m_timer(new QTimer(this)),
|
||||||
m_command(command)
|
m_command(command)
|
||||||
{
|
{
|
||||||
m_timer->setInterval(5000);
|
m_timer->setInterval(10000);
|
||||||
m_timer->setSingleShot(true);
|
m_timer->setSingleShot(true);
|
||||||
connect(m_timer, &QTimer::timeout, this, &ZigbeeInterfaceDeconzReply::onTimeout);
|
connect(m_timer, &QTimer::timeout, this, &ZigbeeInterfaceDeconzReply::onTimeout);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -233,9 +233,13 @@ void ZigbeeBridgeControllerDeconz::sendNextRequest()
|
|||||||
if (m_currentReply)
|
if (m_currentReply)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// // FIXME: If the controler request queue is full, wait until it's free again
|
// If the controler request queue is full, wait until it's free again
|
||||||
// if (!m_apsFreeSlotsAvailable)
|
if (!m_apsFreeSlotsAvailable)
|
||||||
// return;
|
return;
|
||||||
|
|
||||||
|
if (!m_available) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the next reply, set the sequence number, send the request data over the interface and start waiting
|
// Get the next reply, set the sequence number, send the request data over the interface and start waiting
|
||||||
m_currentReply = m_replyQueue.dequeue();
|
m_currentReply = m_replyQueue.dequeue();
|
||||||
@ -864,14 +868,15 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_apsFreeSlotsAvailable != deviceState.apsDataRequestFreeSlots) {
|
if (m_apsFreeSlotsAvailable != deviceState.apsDataRequestFreeSlots) {
|
||||||
m_apsFreeSlotsAvailable = deviceState.apsDataRequestFreeSlots;
|
if (!deviceState.apsDataRequestFreeSlots) {
|
||||||
if (!m_apsFreeSlotsAvailable) {
|
|
||||||
// Warn only if the network is up
|
// Warn only if the network is up
|
||||||
if (m_networkState == Deconz::NetworkStateConnected) {
|
if (m_networkState == Deconz::NetworkStateConnected) {
|
||||||
qCWarning(dcZigbeeController()) << "The APS request table is full on the device. Cannot send requests until the queue gets processed on the controller.";
|
qCWarning(dcZigbeeController()) << "The APS request table is full on the device. Cannot send requests until the queue gets processed on the controller.";
|
||||||
|
m_apsFreeSlotsAvailable = false;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
m_apsFreeSlotsAvailable = true;
|
||||||
qCDebug(dcZigbeeController()) << "The APS request table is free again. Sending the next request";
|
qCDebug(dcZigbeeController()) << "The APS request table is free again. Sending the next request";
|
||||||
sendNextRequest();
|
sendNextRequest();
|
||||||
}
|
}
|
||||||
@ -1021,6 +1026,14 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &
|
|||||||
|
|
||||||
// Check if this is the response to the current active reply
|
// Check if this is the response to the current active reply
|
||||||
if (m_currentReply && m_currentReply->sequenceNumber() == sequenceNumber && m_currentReply->command() == command) {
|
if (m_currentReply && m_currentReply->sequenceNumber() == sequenceNumber && m_currentReply->command() == command) {
|
||||||
|
// If the controller is busy, let's try again once the device state reports free slots
|
||||||
|
if (status == Deconz::StatusCodeBusy) {
|
||||||
|
qCWarning(dcZigbeeController()) << "Controller busy. Rescheduling command.";
|
||||||
|
m_apsFreeSlotsAvailable = false;
|
||||||
|
m_replyQueue.prepend(m_currentReply);
|
||||||
|
m_currentReply = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_currentReply->m_responseData = data;
|
m_currentReply->m_responseData = data;
|
||||||
m_currentReply->m_statusCode = status;
|
m_currentReply->m_statusCode = status;
|
||||||
emit m_currentReply->finished();
|
emit m_currentReply->finished();
|
||||||
|
|||||||
@ -76,6 +76,14 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::sendRequest(const ZigbeeNetworkRequest
|
|||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state() == ZigbeeNetwork::StateStarting) {
|
||||||
|
m_requestQueue.append(reply);
|
||||||
|
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||||
|
m_requestQueue.removeAll(reply);
|
||||||
|
});
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeInterfaceDeconzReply *interfaceReply = m_controller->requestSendRequest(request);
|
ZigbeeInterfaceDeconzReply *interfaceReply = m_controller->requestSendRequest(request);
|
||||||
connect(interfaceReply, &ZigbeeInterfaceDeconzReply::finished, reply, [this, reply, interfaceReply](){
|
connect(interfaceReply, &ZigbeeInterfaceDeconzReply::finished, reply, [this, reply, interfaceReply](){
|
||||||
if (interfaceReply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (interfaceReply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
@ -157,6 +165,25 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::requestSetPermitJoin(quint16 shortAddre
|
|||||||
return sendRequest(request);
|
return sendRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetworkDeconz::sendPendingRequests()
|
||||||
|
{
|
||||||
|
while (!m_requestQueue.isEmpty()) {
|
||||||
|
ZigbeeNetworkReply *reply = m_requestQueue.takeFirst();
|
||||||
|
|
||||||
|
ZigbeeInterfaceDeconzReply *interfaceReply = m_controller->requestSendRequest(reply->request());
|
||||||
|
connect(interfaceReply, &ZigbeeInterfaceDeconzReply::finished, reply, [this, reply, interfaceReply](){
|
||||||
|
if (interfaceReply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
|
qCWarning(dcZigbeeController()) << "Could not send request to controller. SQN:" << interfaceReply->sequenceNumber() << interfaceReply->statusCode();
|
||||||
|
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorInterfaceError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The request has been sent successfully to the device, start the timeout timer now
|
||||||
|
startWaitingReply(reply);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state)
|
void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state)
|
||||||
{
|
{
|
||||||
if (m_createState == state)
|
if (m_createState == state)
|
||||||
@ -379,19 +406,21 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
|
|
||||||
setState(StateRunning);
|
setState(StateRunning);
|
||||||
setPermitJoining(0);
|
setPermitJoining(0);
|
||||||
|
sendPendingRequests();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_initializing = false;
|
||||||
|
setState(StateRunning);
|
||||||
|
setPermitJoining(0);
|
||||||
|
|
||||||
ZigbeeNode *coordinatorNode = createNode(m_controller->networkConfiguration().shortAddress, m_controller->networkConfiguration().ieeeAddress, this);
|
ZigbeeNode *coordinatorNode = createNode(m_controller->networkConfiguration().shortAddress, m_controller->networkConfiguration().ieeeAddress, this);
|
||||||
m_coordinatorNode = coordinatorNode;
|
m_coordinatorNode = coordinatorNode;
|
||||||
|
|
||||||
// Network creation done when coordinator node is initialized
|
|
||||||
connect(coordinatorNode, &ZigbeeNode::stateChanged, this, [this, coordinatorNode](ZigbeeNode::State state){
|
connect(coordinatorNode, &ZigbeeNode::stateChanged, this, [this, coordinatorNode](ZigbeeNode::State state){
|
||||||
if (state == ZigbeeNode::StateInitialized) {
|
if (state == ZigbeeNode::StateInitialized) {
|
||||||
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
|
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
|
||||||
m_initializing = false;
|
sendPendingRequests();
|
||||||
setState(StateRunning);
|
|
||||||
setPermitJoining(0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -534,6 +563,7 @@ void ZigbeeNetworkDeconz::runNetworkInitProcess()
|
|||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Set permit join configuration request finished" << reply->statusCode();
|
qCDebug(dcZigbeeNetwork()) << "Set permit join configuration request finished" << reply->statusCode();
|
||||||
setState(StateRunning);
|
setState(StateRunning);
|
||||||
|
sendPendingRequests();
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (m_controller->networkState() == Deconz::NetworkStateOffline) {
|
} else if (m_controller->networkState() == Deconz::NetworkStateOffline) {
|
||||||
|
|||||||
@ -68,6 +68,7 @@ private:
|
|||||||
QString m_protocolVersion;
|
QString m_protocolVersion;
|
||||||
QString m_firmwareVersion;
|
QString m_firmwareVersion;
|
||||||
|
|
||||||
|
QList<ZigbeeNetworkReply*> m_requestQueue;
|
||||||
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
|
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
|
||||||
|
|
||||||
QTimer *m_pollNetworkStateTimer = nullptr;
|
QTimer *m_pollNetworkStateTimer = nullptr;
|
||||||
@ -79,6 +80,8 @@ private:
|
|||||||
|
|
||||||
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
|
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
|
||||||
|
|
||||||
|
void sendPendingRequests();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startNetworkInternally();
|
void startNetworkInternally();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user