Introduce binding management and cleaning
This commit is contained in:
parent
61114fc773
commit
e245f7c845
@ -78,12 +78,12 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re
|
|||||||
// Send the request, and keep the reply until transposrt, zigbee trasmission and response arrived
|
// Send the request, and keep the reply until transposrt, zigbee trasmission and response arrived
|
||||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||||
if (!m_pendingReplies.values().contains(reply)) {
|
if (!m_pendingReplies.values().contains(reply)) {
|
||||||
qCWarning(dcZigbeeNetwork()) << "#### Reply finished but not in the pending replies list" << reply;
|
//qCWarning(dcZigbeeNetwork()) << "#### Reply finished but not in the pending replies list" << reply;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
quint8 requestId = m_pendingReplies.key(reply);
|
quint8 requestId = m_pendingReplies.key(reply);
|
||||||
m_pendingReplies.remove(requestId);
|
m_pendingReplies.remove(requestId);
|
||||||
qCWarning(dcZigbeeNetwork()) << "#### Removed network reply" << reply << "ID:" << requestId << "Current reply count" << m_pendingReplies.count();
|
//qCWarning(dcZigbeeNetwork()) << "#### Removed network reply" << reply << "ID:" << requestId << "Current reply count" << m_pendingReplies.count();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Finish the reply right the way if the network is offline
|
// Finish the reply right the way if the network is offline
|
||||||
@ -110,7 +110,7 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re
|
|||||||
quint8 networkRequestId = interfaceReply->responseData().at(0);
|
quint8 networkRequestId = interfaceReply->responseData().at(0);
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Request has network SQN" << networkRequestId;
|
//qCDebug(dcZigbeeNetwork()) << "Request has network SQN" << networkRequestId;
|
||||||
reply->request().setRequestId(networkRequestId);
|
reply->request().setRequestId(networkRequestId);
|
||||||
qCWarning(dcZigbeeNetwork()) << "#### Insert network reply" << reply << "ID:" << networkRequestId << "Current reply count" << m_pendingReplies.count();
|
//qCWarning(dcZigbeeNetwork()) << "#### Insert network reply" << reply << "ID:" << networkRequestId << "Current reply count" << m_pendingReplies.count();
|
||||||
m_pendingReplies.insert(networkRequestId, reply);
|
m_pendingReplies.insert(networkRequestId, reply);
|
||||||
// The request has been sent successfully to the device, start the timeout timer now
|
// The request has been sent successfully to the device, start the timeout timer now
|
||||||
startWaitingReply(reply);
|
startWaitingReply(reply);
|
||||||
@ -550,7 +550,7 @@ void ZigbeeNetworkNxp::onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &
|
|||||||
{
|
{
|
||||||
ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId);
|
ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId);
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
qCWarning(dcZigbeeNetwork()) << "Received confirmation but could not find any reply. Ignoring the confirmation";
|
qCDebug(dcZigbeeNetwork()) << "Received confirmation but could not find any reply. Ignoring the confirmation";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,6 +53,7 @@ SOURCES += \
|
|||||||
zigbeenetworkreply.cpp \
|
zigbeenetworkreply.cpp \
|
||||||
zigbeenetworkrequest.cpp \
|
zigbeenetworkrequest.cpp \
|
||||||
zigbeenodeendpoint.cpp \
|
zigbeenodeendpoint.cpp \
|
||||||
|
zigbeereply.cpp \
|
||||||
zigbeesecurityconfiguration.cpp \
|
zigbeesecurityconfiguration.cpp \
|
||||||
zigbeeuartadapter.cpp \
|
zigbeeuartadapter.cpp \
|
||||||
zigbeeuartadaptermonitor.cpp \
|
zigbeeuartadaptermonitor.cpp \
|
||||||
@ -109,6 +110,7 @@ HEADERS += \
|
|||||||
zigbeenetworkreply.h \
|
zigbeenetworkreply.h \
|
||||||
zigbeenetworkrequest.h \
|
zigbeenetworkrequest.h \
|
||||||
zigbeenodeendpoint.h \
|
zigbeenodeendpoint.h \
|
||||||
|
zigbeereply.h \
|
||||||
zigbeesecurityconfiguration.h \
|
zigbeesecurityconfiguration.h \
|
||||||
zigbeeuartadapter.h \
|
zigbeeuartadapter.h \
|
||||||
zigbeeuartadaptermonitor.h \
|
zigbeeuartadaptermonitor.h \
|
||||||
|
|||||||
@ -36,6 +36,11 @@ ZigbeeClusterBasic::ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterBasic::resetToFactoryDefaults()
|
||||||
|
{
|
||||||
|
return executeClusterCommand(ZigbeeClusterBasic::CommandResetToFactoryDefaults);
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeClusterBasic::setAttribute(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeClusterBasic::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||||
|
|||||||
@ -58,6 +58,11 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(Attribute)
|
Q_ENUM(Attribute)
|
||||||
|
|
||||||
|
enum Command {
|
||||||
|
CommandResetToFactoryDefaults = 0x00
|
||||||
|
};
|
||||||
|
Q_ENUM(Command)
|
||||||
|
|
||||||
// Enum for AttributePowerSource(0x0007)
|
// Enum for AttributePowerSource(0x0007)
|
||||||
enum AttributePowerSourceValue {
|
enum AttributePowerSourceValue {
|
||||||
AttributePowerSourceValueUnknown = 0x00,
|
AttributePowerSourceValueUnknown = 0x00,
|
||||||
@ -199,7 +204,7 @@ public:
|
|||||||
|
|
||||||
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
// TODO: reset all clusters to factory defaults command 0x00, optional
|
ZigbeeClusterReply *resetToFactoryDefaults();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||||
|
|||||||
@ -306,6 +306,58 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindIeeeAddress(quint8 sourc
|
|||||||
return zdoReply;
|
return zdoReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestUnbind(const ZigbeeDeviceProfile::BindingTableListRecord &bindingRecord)
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeDeviceObject()) << "Request unbind" << m_node << bindingRecord;
|
||||||
|
|
||||||
|
// Build APS request
|
||||||
|
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::UnbindRequest);
|
||||||
|
|
||||||
|
// 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 << bindingRecord.sourceAddress.toUInt64();
|
||||||
|
stream << bindingRecord.sourceEndpoint;
|
||||||
|
stream << bindingRecord.clusterId;
|
||||||
|
stream << static_cast<quint8>(bindingRecord.destinationAddressMode);
|
||||||
|
if (bindingRecord.destinationAddressMode == Zigbee::DestinationAddressModeGroup) {
|
||||||
|
stream << bindingRecord.destinationAddressShort;
|
||||||
|
} else {
|
||||||
|
stream << bindingRecord.destinationAddress.toUInt64();
|
||||||
|
stream << bindingRecord.destinationEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLeaveNetwork(bool rejoin, bool removeChildren)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeDeviceObject()) << "Request management leave network from" << m_node << "rejoin" << rejoin << "remove children" << removeChildren;
|
qCDebug(dcZigbeeDeviceObject()) << "Request management leave network from" << m_node << "rejoin" << rejoin << "remove children" << removeChildren;
|
||||||
|
|||||||
@ -53,6 +53,7 @@ public:
|
|||||||
ZigbeeDeviceObjectReply *requestBindShortAddress(quint8 sourceEndpointId, quint16 clusterId, quint16 destinationAddress);
|
ZigbeeDeviceObjectReply *requestBindShortAddress(quint8 sourceEndpointId, quint16 clusterId, quint16 destinationAddress);
|
||||||
ZigbeeDeviceObjectReply *requestBindIeeeAddress(quint8 sourceEndpointId, quint16 clusterId, const ZigbeeAddress &destinationIeeeAddress, quint8 destinationEndpointId);
|
ZigbeeDeviceObjectReply *requestBindIeeeAddress(quint8 sourceEndpointId, quint16 clusterId, const ZigbeeAddress &destinationIeeeAddress, quint8 destinationEndpointId);
|
||||||
|
|
||||||
|
ZigbeeDeviceObjectReply *requestUnbind(const ZigbeeDeviceProfile::BindingTableListRecord &bindingRecord);
|
||||||
|
|
||||||
// Management request
|
// Management request
|
||||||
ZigbeeDeviceObjectReply *requestMgmtLeaveNetwork(bool rejoin = false, bool removeChildren = false);
|
ZigbeeDeviceObjectReply *requestMgmtLeaveNetwork(bool rejoin = false, bool removeChildren = false);
|
||||||
|
|||||||
@ -86,6 +86,11 @@ Zigbee::ZigbeeMacLayerStatus ZigbeeDeviceObjectReply::zigbeeMacStatus() const
|
|||||||
return m_zigbeeMacStatus;
|
return m_zigbeeMacStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeDeviceProfile::Status ZigbeeDeviceObjectReply::zigbeeDeviceObjectStatus() const
|
||||||
|
{
|
||||||
|
return m_zigbeeDeviceObjectStatus;
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeNetworkRequest ZigbeeDeviceObjectReply::request() const
|
ZigbeeNetworkRequest ZigbeeDeviceObjectReply::request() const
|
||||||
{
|
{
|
||||||
return m_request;
|
return m_request;
|
||||||
|
|||||||
@ -117,6 +117,11 @@ ZigbeeDeviceProfile::PowerDescriptor ZigbeeNode::powerDescriptor() const
|
|||||||
return m_powerDescriptor;
|
return m_powerDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<ZigbeeDeviceProfile::BindingTableListRecord> ZigbeeNode::bindingTableRecords() const
|
||||||
|
{
|
||||||
|
return m_bindingTableRecords;
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNode::setState(ZigbeeNode::State state)
|
void ZigbeeNode::setState(ZigbeeNode::State state)
|
||||||
{
|
{
|
||||||
if (m_state == state)
|
if (m_state == state)
|
||||||
@ -154,22 +159,42 @@ void ZigbeeNode::startInitialization()
|
|||||||
initNodeDescriptor();
|
initNodeDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNode::removeAllBindings()
|
ZigbeeReply *ZigbeeNode::removeAllBindings()
|
||||||
{
|
{
|
||||||
|
ZigbeeReply *reply = new ZigbeeReply(this);
|
||||||
|
|
||||||
}
|
ZigbeeReply *readBindingsReply = readBindingTableEntries();
|
||||||
|
connect(readBindingsReply, &ZigbeeReply::finished, reply, [=](){
|
||||||
void ZigbeeNode::readBindingTableEntries()
|
if (readBindingsReply->error()) {
|
||||||
{
|
qCWarning(dcZigbeeNode()) << "Failed to remove all bindings because the current bindings could not be fetched from node" << this;
|
||||||
ZigbeeDeviceObjectReply *reply = deviceObject()->requestMgmtBind();
|
reply->finishReply(readBindingsReply->error());
|
||||||
connect(reply, &ZigbeeDeviceObjectReply::finished, this, [=](){
|
|
||||||
if (reply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
|
||||||
qCWarning(dcZigbeeNode()) << "Failed to read binding table" << reply->error();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeDeviceObject()) << "Bind table payload" << ZigbeeUtils::convertByteArrayToHexString(reply->responseData());
|
qCDebug(dcZigbeeNode()) << "Current binding table records:";
|
||||||
QByteArray response = reply->responseData();
|
foreach (const ZigbeeDeviceProfile::BindingTableListRecord &binding, m_bindingTableRecords) {
|
||||||
|
qCDebug(dcZigbeeNode()) << binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove bindings sequentially and finish reply if error occures or all bindings removed
|
||||||
|
removeNextBinding(reply);
|
||||||
|
});
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeReply *ZigbeeNode::readBindingTableEntries()
|
||||||
|
{
|
||||||
|
ZigbeeReply *reply = new ZigbeeReply(this);
|
||||||
|
ZigbeeDeviceObjectReply *zdoReply = deviceObject()->requestMgmtBind();
|
||||||
|
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, this, [=](){
|
||||||
|
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||||
|
qCWarning(dcZigbeeNode()) << "Failed to read binding table" << zdoReply->error();
|
||||||
|
reply->finishReply(ZigbeeReply::ErrorZigbeeError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeDeviceObject()) << "Bind table payload" << ZigbeeUtils::convertByteArrayToHexString(zdoReply->responseData());
|
||||||
|
QByteArray response = zdoReply->responseData();
|
||||||
QDataStream stream(&response, QIODevice::ReadOnly);
|
QDataStream stream(&response, QIODevice::ReadOnly);
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint8 sqn; quint8 statusInt; quint8 entriesCount; quint8 startIndex; quint8 bindingTableListCount;
|
quint8 sqn; quint8 statusInt; quint8 entriesCount; quint8 startIndex; quint8 bindingTableListCount;
|
||||||
@ -177,7 +202,7 @@ void ZigbeeNode::readBindingTableEntries()
|
|||||||
ZigbeeDeviceProfile::Status status = static_cast<ZigbeeDeviceProfile::Status>(statusInt);
|
ZigbeeDeviceProfile::Status status = static_cast<ZigbeeDeviceProfile::Status>(statusInt);
|
||||||
qCDebug(dcZigbeeDeviceObject()) << "SQN:" << sqn << status << "entries:" << entriesCount << "index:" << startIndex << "list count:" << bindingTableListCount;
|
qCDebug(dcZigbeeDeviceObject()) << "SQN:" << sqn << status << "entries:" << entriesCount << "index:" << startIndex << "list count:" << bindingTableListCount;
|
||||||
|
|
||||||
QList<ZigbeeDeviceProfile::BindingTableListRecord> bindingTableRecords;
|
m_bindingTableRecords.clear();
|
||||||
for (int i = 0; i < bindingTableListCount; i++) {
|
for (int i = 0; i < bindingTableListCount; i++) {
|
||||||
quint64 sourceAddress; quint8 addressMode;
|
quint64 sourceAddress; quint8 addressMode;
|
||||||
ZigbeeDeviceProfile::BindingTableListRecord record;
|
ZigbeeDeviceProfile::BindingTableListRecord record;
|
||||||
@ -198,11 +223,15 @@ void ZigbeeNode::readBindingTableEntries()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
qCDebug(dcZigbeeDeviceObject()) << record;
|
qCDebug(dcZigbeeDeviceObject()) << record;
|
||||||
bindingTableRecords << record;
|
m_bindingTableRecords << record;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: continue reading if there are more entries
|
// TODO: continue reading if there are more entries
|
||||||
|
|
||||||
|
emit bindingTableRecordsChanged();
|
||||||
|
reply->finishReply();
|
||||||
});
|
});
|
||||||
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNode::initNodeDescriptor()
|
void ZigbeeNode::initNodeDescriptor()
|
||||||
@ -418,6 +447,31 @@ void ZigbeeNode::initEndpoint(quint8 endpointId)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNode::removeNextBinding(ZigbeeReply *reply)
|
||||||
|
{
|
||||||
|
// If we have no bindings left, finish the given reply
|
||||||
|
if (m_bindingTableRecords.isEmpty()) {
|
||||||
|
reply->finishReply();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeDeviceProfile::BindingTableListRecord record = m_bindingTableRecords.last();
|
||||||
|
ZigbeeDeviceObjectReply *zdoReply = m_deviceObject->requestUnbind(record);
|
||||||
|
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, reply, [=](){
|
||||||
|
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||||
|
qCWarning(dcZigbeeNode()) << "Failed to remove" << record << zdoReply->error();
|
||||||
|
reply->finishReply(ZigbeeReply::ErrorZigbeeError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully removed
|
||||||
|
m_bindingTableRecords.removeLast();
|
||||||
|
emit bindingTableRecordsChanged();
|
||||||
|
|
||||||
|
removeNextBinding(reply);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNode::initBasicCluster()
|
void ZigbeeNode::initBasicCluster()
|
||||||
{
|
{
|
||||||
// Get the first endpoint which implements the basic cluster
|
// Get the first endpoint which implements the basic cluster
|
||||||
@ -476,7 +530,7 @@ void ZigbeeNode::readManufacturerName(ZigbeeClusterBasic *basicCluster)
|
|||||||
if (m_requestRetry < 3) {
|
if (m_requestRetry < 3) {
|
||||||
m_requestRetry++;
|
m_requestRetry++;
|
||||||
qCDebug(dcZigbeeNode()) << "Retry to read manufacturer name from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
qCDebug(dcZigbeeNode()) << "Retry to read manufacturer name from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
||||||
QTimer::singleShot(1000, this, [=](){readManufacturerName(basicCluster);});
|
QTimer::singleShot(1000, this, [=](){ readManufacturerName(basicCluster); });
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcZigbeeNode()) << "Failed to read manufacturer name from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
qCWarning(dcZigbeeNode()) << "Failed to read manufacturer name from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
||||||
m_requestRetry = 0;
|
m_requestRetry = 0;
|
||||||
@ -535,7 +589,7 @@ void ZigbeeNode::readModelIdentifier(ZigbeeClusterBasic *basicCluster)
|
|||||||
if (m_requestRetry < 3) {
|
if (m_requestRetry < 3) {
|
||||||
m_requestRetry++;
|
m_requestRetry++;
|
||||||
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
||||||
QTimer::singleShot(1000, this, [=](){readModelIdentifier(basicCluster);});
|
QTimer::singleShot(1000, this, [=](){ readModelIdentifier(basicCluster); });
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
||||||
m_requestRetry = 0;
|
m_requestRetry = 0;
|
||||||
@ -576,7 +630,7 @@ void ZigbeeNode::readSoftwareBuildId(ZigbeeClusterBasic *basicCluster)
|
|||||||
if (m_requestRetry < 3) {
|
if (m_requestRetry < 3) {
|
||||||
m_requestRetry++;
|
m_requestRetry++;
|
||||||
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
||||||
QTimer::singleShot(1000, this, [=](){readSoftwareBuildId(basicCluster);});
|
QTimer::singleShot(1000, this, [=](){ readSoftwareBuildId(basicCluster); });
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
||||||
m_requestRetry = 0;
|
m_requestRetry = 0;
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
|
#include "zigbeereply.h"
|
||||||
#include "zigbeeaddress.h"
|
#include "zigbeeaddress.h"
|
||||||
#include "zigbeenodeendpoint.h"
|
#include "zigbeenodeendpoint.h"
|
||||||
#include "zdo/zigbeedeviceobject.h"
|
#include "zdo/zigbeedeviceobject.h"
|
||||||
@ -82,11 +83,14 @@ public:
|
|||||||
QList<ZigbeeDeviceProfile::PowerSource> availablePowerSources() const;
|
QList<ZigbeeDeviceProfile::PowerSource> availablePowerSources() const;
|
||||||
ZigbeeDeviceProfile::PowerLevel powerLevel() const;
|
ZigbeeDeviceProfile::PowerLevel powerLevel() const;
|
||||||
|
|
||||||
|
// Only available if fetched
|
||||||
|
QList<ZigbeeDeviceProfile::BindingTableListRecord> bindingTableRecords() const;
|
||||||
|
|
||||||
// This method starts the node initialization phase (read descriptors and endpoints)
|
// This method starts the node initialization phase (read descriptors and endpoints)
|
||||||
void startInitialization();
|
void startInitialization();
|
||||||
|
|
||||||
void removeAllBindings();
|
ZigbeeReply *removeAllBindings();
|
||||||
void readBindingTableEntries();
|
ZigbeeReply *readBindingTableEntries();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent = nullptr);
|
ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent = nullptr);
|
||||||
@ -107,6 +111,8 @@ private:
|
|||||||
ZigbeeDeviceProfile::MacCapabilities m_macCapabilities;
|
ZigbeeDeviceProfile::MacCapabilities m_macCapabilities;
|
||||||
ZigbeeDeviceProfile::PowerDescriptor m_powerDescriptor;
|
ZigbeeDeviceProfile::PowerDescriptor m_powerDescriptor;
|
||||||
|
|
||||||
|
QList<ZigbeeDeviceProfile::BindingTableListRecord> m_bindingTableRecords;
|
||||||
|
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
void setReachable(bool reachable);
|
void setReachable(bool reachable);
|
||||||
|
|
||||||
@ -118,6 +124,8 @@ private:
|
|||||||
void initEndpoints();
|
void initEndpoints();
|
||||||
void initEndpoint(quint8 endpointId);
|
void initEndpoint(quint8 endpointId);
|
||||||
|
|
||||||
|
void removeNextBinding(ZigbeeReply *reply);
|
||||||
|
|
||||||
// For convenience and having base information about the first endpoint
|
// For convenience and having base information about the first endpoint
|
||||||
void initBasicCluster();
|
void initBasicCluster();
|
||||||
void readManufacturerName(ZigbeeClusterBasic *basicCluster);
|
void readManufacturerName(ZigbeeClusterBasic *basicCluster);
|
||||||
@ -132,6 +140,7 @@ signals:
|
|||||||
void lqiChanged(quint8 lqi);
|
void lqiChanged(quint8 lqi);
|
||||||
void lastSeenChanged(const QDateTime &lastSeen);
|
void lastSeenChanged(const QDateTime &lastSeen);
|
||||||
void reachableChanged(bool reachable);
|
void reachableChanged(bool reachable);
|
||||||
|
void bindingTableRecordsChanged();
|
||||||
void clusterAdded(ZigbeeCluster *cluster);
|
void clusterAdded(ZigbeeCluster *cluster);
|
||||||
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
|||||||
45
libnymea-zigbee/zigbeereply.cpp
Normal file
45
libnymea-zigbee/zigbeereply.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea-zigbee.
|
||||||
|
* This project including source code and documentation is protected by copyright law, and
|
||||||
|
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||||
|
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||||
|
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||||
|
* of use of nymea GmbH, available under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||||
|
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||||
|
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||||
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under contact@nymea.io
|
||||||
|
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "zigbeereply.h"
|
||||||
|
|
||||||
|
ZigbeeReply::Error ZigbeeReply::error() const
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeReply::ZigbeeReply(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeReply::finishReply(ZigbeeReply::Error error)
|
||||||
|
{
|
||||||
|
m_error = error;
|
||||||
|
emit finished();
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
66
libnymea-zigbee/zigbeereply.h
Normal file
66
libnymea-zigbee/zigbeereply.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea-zigbee.
|
||||||
|
* This project including source code and documentation is protected by copyright law, and
|
||||||
|
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||||
|
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||||
|
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||||
|
* of use of nymea GmbH, available under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||||
|
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||||
|
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||||
|
* If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under contact@nymea.io
|
||||||
|
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef ZIGBEEREPLY_H
|
||||||
|
#define ZIGBEEREPLY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zigbee.h"
|
||||||
|
|
||||||
|
class ZigbeeReply : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ZigbeeNode;
|
||||||
|
friend class ZigbeeNetwork;
|
||||||
|
friend class ZigbeeNodeEndpoint;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Error {
|
||||||
|
ErrorNoError,
|
||||||
|
ErrorTimeout,
|
||||||
|
ErrorInterfaceError,
|
||||||
|
ErrorZigbeeError,
|
||||||
|
ErrorNetworkOffline
|
||||||
|
};
|
||||||
|
Q_ENUM(Error)
|
||||||
|
|
||||||
|
Error error() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit ZigbeeReply(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Error m_error = ErrorNoError;
|
||||||
|
|
||||||
|
void finishReply(Error error = ErrorNoError);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEEREPLY_H
|
||||||
Reference in New Issue
Block a user