diff --git a/libnymea-zigbee/zdo/zigbeedeviceobject.cpp b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp index 53e6714..cf638b0 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobject.cpp +++ b/libnymea-zigbee/zdo/zigbeedeviceobject.cpp @@ -332,6 +332,63 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLeaveNetwork(bool rejoin return zdoReply; } +ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLqi(quint8 startIndex) +{ + qCDebug(dcZigbeeDeviceObject()) << "Request lqi table from" << m_node << "start index" << startIndex; + + // Build APS request + ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::MgmtLqiRequest); + + // Generate a new transaction sequence number for this device object + quint8 transactionSequenceNumber = m_transactionSequenceNumber++; + + QByteArray asdu; + QDataStream stream(&asdu, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << startIndex; + + // 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)) { + qCWarning(dcZigbeeDeviceObject()) << "Failed to send request" + << static_cast(networkReply->request().clusterId()) + << m_node << networkReply->error() + << networkReply->zigbeeApsStatus(); + finishZdoReply(zdoReply); + return; + } + + // The request was successfully sent to the device + // Now check if the expected indication response received already + if (zdoReply->isComplete()) { + qCDebug(dcZigbeeDeviceObject()) << "Successfully received response for" << static_cast(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; + } + // We received the confirmation but not yet the indication + }); + + return zdoReply; +} + ZigbeeNetworkRequest ZigbeeDeviceObject::buildZdoRequest(quint16 zdoRequest) { ZigbeeNetworkRequest request; diff --git a/libnymea-zigbee/zdo/zigbeedeviceobject.h b/libnymea-zigbee/zdo/zigbeedeviceobject.h index ba938e0..42cc681 100644 --- a/libnymea-zigbee/zdo/zigbeedeviceobject.h +++ b/libnymea-zigbee/zdo/zigbeedeviceobject.h @@ -57,6 +57,8 @@ public: // Management request ZigbeeDeviceObjectReply *requestMgmtLeaveNetwork(bool rejoin = false, bool removeChildren = false); + ZigbeeDeviceObjectReply *requestMgmtLqi(quint8 startIndex = 0x00); + // TODO: write all requests diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index d4b14e4..82a7b6f 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -51,6 +51,16 @@ ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) : setPermitJoiningRemaining(m_permitJoiningRemaining); } }); + + + connect(this, &ZigbeeNetwork::stateChanged, this, [this](ZigbeeNetwork::State state){ + if (state != ZigbeeNetwork::StateRunning) { + foreach (ZigbeeNode *node, m_nodes) { + node->setReachable(false); + } + } + + }); } QUuid ZigbeeNetwork::networkUuid() const diff --git a/libnymea-zigbee/zigbeenode.cpp b/libnymea-zigbee/zigbeenode.cpp index 2677833..48cac83 100644 --- a/libnymea-zigbee/zigbeenode.cpp +++ b/libnymea-zigbee/zigbeenode.cpp @@ -46,9 +46,9 @@ ZigbeeNode::State ZigbeeNode::state() const return m_state; } -bool ZigbeeNode::connected() const +bool ZigbeeNode::reachable() const { - return m_connected; + return m_reachable; } QUuid ZigbeeNode::networkUuid() const @@ -127,14 +127,14 @@ void ZigbeeNode::setState(ZigbeeNode::State state) emit stateChanged(m_state); } -void ZigbeeNode::setConnected(bool connected) +void ZigbeeNode::setReachable(bool reachable) { - if (m_connected == connected) + if (m_reachable == reachable) return; - qCDebug(dcZigbeeNode()) << "Connected changed" << this << connected; - m_connected = connected; - emit connectedChanged(m_connected); + qCDebug(dcZigbeeNode()) << "Reachable changed" << this << reachable; + m_reachable = reachable; + emit reachableChanged(m_reachable); } void ZigbeeNode::startInitialization() @@ -590,6 +590,9 @@ void ZigbeeNode::handleDataIndication(const Zigbee::ApsdeDataIndication &indicat emit lqiChanged(m_lqi); } + // Data received from this node, it is reachable for sure + setReachable(true); + // Update the UTC timestamp of last seen for reachable verification if (m_lastSeen != QDateTime::currentDateTimeUtc()) { m_lastSeen = QDateTime::currentDateTimeUtc(); @@ -602,7 +605,7 @@ void ZigbeeNode::handleDataIndication(const Zigbee::ApsdeDataIndication &indicat return; } - // Else let the node handle this indication + // Let the clusters handle this indication handleZigbeeClusterLibraryIndication(indication); } diff --git a/libnymea-zigbee/zigbeenode.h b/libnymea-zigbee/zigbeenode.h index ff8b57c..3839761 100644 --- a/libnymea-zigbee/zigbeenode.h +++ b/libnymea-zigbee/zigbeenode.h @@ -55,7 +55,7 @@ public: Q_ENUM(State) State state() const; - bool connected() const; + bool reachable() const; QUuid networkUuid() const; @@ -94,7 +94,7 @@ private: ZigbeeDeviceObject *m_deviceObject = nullptr; QList m_endpoints; - bool m_connected = false; + bool m_reachable = false; State m_state = StateUninitialized; quint8 m_lqi = 0; QDateTime m_lastSeen; @@ -105,7 +105,7 @@ private: ZigbeeDeviceProfile::PowerDescriptor m_powerDescriptor; void setState(State state); - void setConnected(bool connected); + void setReachable(bool reachable); // Init methods int m_requestRetry = 0; @@ -128,7 +128,7 @@ signals: void stateChanged(State state); void lqiChanged(quint8 lqi); void lastSeenChanged(const QDateTime &lastSeen); - void connectedChanged(bool connected); + void reachableChanged(bool reachable); void clusterAdded(ZigbeeCluster *cluster); void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);