Fix initialization error due to timeout issue and improve debugging

pull/10/head
Simon Stürz 2020-12-02 12:03:44 +01:00
parent 4e8254fcb9
commit 1eed81562a
9 changed files with 90 additions and 43 deletions

View File

@ -68,7 +68,8 @@ public:
StatusProtocolError = 0x01,
StatusUnknownCommand = 0x02,
StatusInvalidCrc = 0x03,
StatusStackError = 0x04
StatusStackError = 0x04,
StatusTimeout = 0xff
};
Q_ENUM(Status)

View File

@ -98,6 +98,8 @@ void ZigbeeInterfaceNxpReply::setFinished()
void ZigbeeInterfaceNxpReply::onTimeout()
{
m_timeout = true;
m_status = Nxp::StatusTimeout;
emit timeout();
emit finished();
}

View File

@ -71,7 +71,7 @@ private:
QByteArray m_requestData;
// Response content
Nxp::Status m_status = Nxp::StatusUnknownCommand; // FIXME
Nxp::Status m_status = Nxp::StatusUnknownCommand;
QByteArray m_responseData;
void setFinished();

View File

@ -94,6 +94,7 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re
// Enqueu reply and send next one if we have enouth capacity
m_replyQueue.enqueue(reply);
qCDebug(dcZigbeeNetwork()) << "=== Pending replies count (enqueued)" << m_replyQueue.count();
sendNextReply();
return reply;
@ -181,6 +182,8 @@ void ZigbeeNetworkNxp::sendNextReply()
ZigbeeNetworkReply *reply = m_replyQueue.dequeue();
qCDebug(dcZigbeeNetwork()) << "=== Pending replies count (dequeued)" << m_replyQueue.count();
ZigbeeInterfaceNxpReply *interfaceReply = m_controller->requestSendRequest(reply->request());
connect(interfaceReply, &ZigbeeInterfaceNxpReply::finished, reply, [this, reply, interfaceReply](){
if (interfaceReply->status() != Nxp::StatusSuccess) {
@ -246,7 +249,6 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::requestSetPermitJoin(quint16 shortAddress,
bool ZigbeeNetworkNxp::processVersionReply(ZigbeeInterfaceNxpReply *reply)
{
qCDebug(dcZigbeeNetwork()) << "Version reply finished" << reply->status();
if (reply->timendOut()) {
m_reconnectCounter++;
if (m_reconnectCounter >= 3) {
@ -271,7 +273,9 @@ bool ZigbeeNetworkNxp::processVersionReply(ZigbeeInterfaceNxpReply *reply)
qCWarning(dcZigbeeNetwork()) << "Failed to read firmware version. Retry" << m_reconnectCounter << "/ 3";
ZigbeeInterfaceNxpReply *reply = m_controller->requestVersion();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
processVersionReply(reply);
if (processVersionReply(reply)) {
m_controller->refreshControllerState();
}
});
return false;
@ -436,22 +440,25 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr
connect(coordinatorNode, &ZigbeeNode::stateChanged, this, [this, coordinatorNode](ZigbeeNode::State state){
if (state == ZigbeeNode::StateInitialized) {
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
// ZigbeeClusterGroups *groupsCluster = coordinatorNode->getEndpoint(0x01)->inputCluster<ZigbeeClusterGroups>(ZigbeeClusterLibrary::ClusterIdGroups);
// if (!groupsCluster) {
// qCWarning(dcZigbeeNetwork()) << "Failed to get groups cluster from coordinator. The coordinator will not be in default group 0x0000";
// setState(StateRunning);
// setPermitJoining(0);
// return;
// }
/* Note: this currently has been hardcoded into the firmware. TODO: implement appropriate method for binding coordinator to group
// ZigbeeClusterReply *reply = groupsCluster->addGroup(0x0000, "Default");
// connect(reply, &ZigbeeClusterReply::finished, this, [=](){
// if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
// qCWarning(dcZigbeeNetwork()) << "Failed to add coordinator to default group 0x0000. The coordinator will not be in default group 0x0000";
// }
// setState(StateRunning);
// setPermitJoining(0);
// });
ZigbeeClusterGroups *groupsCluster = coordinatorNode->getEndpoint(0x01)->inputCluster<ZigbeeClusterGroups>(ZigbeeClusterLibrary::ClusterIdGroups);
if (!groupsCluster) {
qCWarning(dcZigbeeNetwork()) << "Failed to get groups cluster from coordinator. The coordinator will not be in default group 0x0000";
setState(StateRunning);
setPermitJoining(0);
return;
}
ZigbeeClusterReply *reply = groupsCluster->addGroup(0x0000, "Default");
connect(reply, &ZigbeeClusterReply::finished, this, [=](){
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
qCWarning(dcZigbeeNetwork()) << "Failed to add coordinator to default group 0x0000. The coordinator will not be in default group 0x0000";
}
setState(StateRunning);
setPermitJoining(0);
});
*/
setState(StateRunning);
setPermitJoining(0);
@ -613,8 +620,10 @@ void ZigbeeNetworkNxp::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress iee
setNodeReachable(node, true);
return;
} else {
qCDebug(dcZigbeeNetwork()) << "Already known device announced with different network address. Removing node and reinitialize...";
removeNode(node);
qCWarning(dcZigbeeNetwork()) << "Already known device announced with different network address. FIXME: update the network address or reinitialize node...";
//removeNode(node);
}
}

View File

@ -211,9 +211,10 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestSimpleDescriptor(quint8 endp
return zdoReply;
}
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindShortAddress(quint8 sourceEndpointId, quint16 clusterId, quint16 destinationAddress)
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindGroupAddress(quint8 sourceEndpointId, quint16 clusterId, quint16 destinationAddress)
{
qCDebug(dcZigbeeDeviceObject()) << "Request bind short address from" << m_node << "endpoint" << clusterId << "to" << destinationAddress;
qCDebug(dcZigbeeDeviceObject()) << "Request bind group address from" << m_node << "endpoint" << ZigbeeUtils::convertByteToHexString(sourceEndpointId)
<< static_cast<ZigbeeClusterLibrary::ClusterId>(clusterId) << "to group" << ZigbeeUtils::convertUint16ToHexString(destinationAddress);
// Build APS request
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::BindRequest);
@ -260,7 +261,9 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindShortAddress(quint8 sour
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindIeeeAddress(quint8 sourceEndpointId, quint16 clusterId, const ZigbeeAddress &destinationIeeeAddress, quint8 destinationEndpointId)
{
qCDebug(dcZigbeeDeviceObject()) << "Request bind ieee address from" << m_node << "endpoint" << clusterId << "to" << destinationIeeeAddress.toString() << destinationEndpointId;
qCDebug(dcZigbeeDeviceObject()) << "Request bind IEEE address from" << m_node << "endpoint" << ZigbeeUtils::convertByteToHexString(sourceEndpointId)
<< static_cast<ZigbeeClusterLibrary::ClusterId>(clusterId) << "to" << destinationIeeeAddress.toString() << "endpoint"
<< ZigbeeUtils::convertByteToHexString(destinationEndpointId);
// Build APS request
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::BindRequest);
@ -358,6 +361,49 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestUnbind(const ZigbeeDevicePro
return zdoReply;
}
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindRegister(const ZigbeeAddress &ieeeAddress)
{
qCDebug(dcZigbeeDeviceObject()) << "Request bind register" << m_node << ieeeAddress.toString();
// Build APS request
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::BindRegisterRequest);
// Generate a new transaction sequence number for this device object
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
// Build ZDO frame
QByteArray asdu;
QDataStream stream(&asdu, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << transactionSequenceNumber;
stream << ieeeAddress.toUInt64();
// Set the ZDO frame as APS request payload
request.setAsdu(asdu);
// Create the device object reply and wait for the response indication
ZigbeeDeviceObjectReply *zdoReply = createZigbeeDeviceObjectReply(request, transactionSequenceNumber);
// Send the request, on finished read the confirm information
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){
if (!verifyNetworkError(zdoReply, networkReply)) {
finishZdoReply(zdoReply);
return;
}
// The request was successfully sent to the device
// Now check if the expected indication response received already
if (zdoReply->isComplete()) {
finishZdoReply(zdoReply);
return;
}
// We received the confirmation but not yet the indication
});
return zdoReply;
}
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLeaveNetwork(bool rejoin, bool removeChildren)
{
qCDebug(dcZigbeeDeviceObject()) << "Request management leave network from" << m_node << "rejoin" << rejoin << "remove children" << removeChildren;
@ -442,17 +488,6 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLqi(quint8 startIndex)
// Now check if the expected indication response received already
if (zdoReply->isComplete()) {
qCDebug(dcZigbeeDeviceObject()) << "Successfully received response for" << static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId());
// TODO: pars child table
// QByteArray response = zdoReply->responseAdpu().payload;
// QDataStream stream(&response, QIODevice::ReadOnly);
// stream.setByteOrder(QDataStream::LittleEndian);
// quint8 statusValue; quint8 tableEntries; quint8 startIndex;
// ZigbeeDeviceProfile::Status status;
finishZdoReply(zdoReply);
return;
}

View File

@ -50,10 +50,10 @@ public:
// TODO: implement other device and service discovery methods
// End device binding
ZigbeeDeviceObjectReply *requestBindShortAddress(quint8 sourceEndpointId, quint16 clusterId, quint16 destinationAddress);
ZigbeeDeviceObjectReply *requestBindGroupAddress(quint8 sourceEndpointId, quint16 clusterId, quint16 destinationAddress);
ZigbeeDeviceObjectReply *requestBindIeeeAddress(quint8 sourceEndpointId, quint16 clusterId, const ZigbeeAddress &destinationIeeeAddress, quint8 destinationEndpointId);
ZigbeeDeviceObjectReply *requestUnbind(const ZigbeeDeviceProfile::BindingTableListRecord &bindingRecord);
ZigbeeDeviceObjectReply *requestBindRegister(const ZigbeeAddress &ieeeAddress);
// Management request
ZigbeeDeviceObjectReply *requestMgmtLeaveNetwork(bool rejoin = false, bool removeChildren = false);

View File

@ -197,7 +197,7 @@ ZigbeeDeviceProfile::Adpu ZigbeeDeviceProfile::parseAdpu(const QByteArray &adpu)
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::Adpu &deviceAdpu)
{
debug.nospace() << "DeviceAdpu(SQN: " << deviceAdpu.transactionSequenceNumber << ", ";
debug.nospace() << "DeviceProfileAdpu(SQN: " << deviceAdpu.transactionSequenceNumber << ", ";
debug.nospace() << deviceAdpu.status << ", ";
debug.nospace() << ZigbeeUtils::convertUint16ToHexString(deviceAdpu.addressOfInterest) << ", ";
debug.nospace() << "Payload: " << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")";
@ -210,12 +210,12 @@ QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::NodeDescriptor &nodeD
debug.nospace() << " Complex descriptor available: " << nodeDescriptor.complexDescriptorAvailable << "\n";
debug.nospace() << " User descriptor available: " << nodeDescriptor.userDescriptorAvailable << "\n";
debug.nospace() << " " << nodeDescriptor.frequencyBand << "\n";
debug.nospace() << " " << nodeDescriptor.macCapabilities;
debug.nospace() << " " << nodeDescriptor.macCapabilities << "\n";
debug.nospace() << " Manufacturer code: " << ZigbeeUtils::convertUint16ToHexString(nodeDescriptor.manufacturerCode) << "(" << nodeDescriptor.manufacturerCode << ")" << "\n";
debug.nospace() << " Maximum buffer size: " << nodeDescriptor.maximumBufferSize << "\n";
debug.nospace() << " Maximum RX size: " << nodeDescriptor.maximumRxSize << "\n";
debug.nospace() << " Maximum TX size: " << nodeDescriptor.maximumTxSize << "\n";
debug.nospace() << " " << nodeDescriptor.serverMask;
debug.nospace() << " " << nodeDescriptor.serverMask << "\n";
debug.nospace() << " " << nodeDescriptor.descriptorCapabilities;
return debug;
}

View File

@ -292,7 +292,6 @@ public:
static MacCapabilities parseMacCapabilities(quint8 macCapabilitiesFlag);
static ServerMask parseServerMask(quint16 serverMaskFlag);
static DescriptorCapabilities parseDescriptorCapabilities(quint8 descriptorCapabilitiesFlag);
static PowerDescriptor parsePowerDescriptor(quint16 powerDescriptorFlag);
};

View File

@ -691,8 +691,9 @@ void ZigbeeNetwork::evaluateNodeReachableStates()
// Note: sleeping devices should send some message within 6 hours,
// otherwise the device might not be reachable any more
int msSinceLastSeen = node->lastSeen().msecsTo(QDateTime::currentDateTimeUtc());
qCDebug(dcZigbeeNetwork()) << node << "last seen" << QTime::fromMSecsSinceStartOfDay(msSinceLastSeen).toString();
if (msSinceLastSeen < 1000*60*60*6) {
qCDebug(dcZigbeeNetwork()) << node << "has been seen the last time" << QTime::fromMSecsSinceStartOfDay(msSinceLastSeen).toString() << "ago.";
// 6 Hours = 6 * 60 * 60 * 1000 = 21600000 ms
if (msSinceLastSeen < 21600000) {
setNodeReachable(node, true);
} else {
setNodeReachable(node, false);