Add group cluster and fix reply handling in NXP backend
parent
66637cc389
commit
0768903b07
|
|
@ -76,8 +76,14 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re
|
|||
{
|
||||
ZigbeeNetworkReply *reply = createNetworkReply(request);
|
||||
// Send the request, and keep the reply until transposrt, zigbee trasmission and response arrived
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, request](){
|
||||
m_pendingReplies.remove(request.requestId());
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||
if (!m_pendingReplies.values().contains(reply)) {
|
||||
qCWarning(dcZigbeeNetwork()) << "Reply finished but not in the pending replies list" << reply;
|
||||
return;
|
||||
}
|
||||
quint8 requestId = m_pendingReplies.key(reply);
|
||||
m_pendingReplies.remove(requestId);
|
||||
//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
|
||||
|
|
@ -104,8 +110,8 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re
|
|||
quint8 networkRequestId = interfaceReply->responseData().at(0);
|
||||
//qCDebug(dcZigbeeNetwork()) << "Request has network SQN" << networkRequestId;
|
||||
reply->request().setRequestId(networkRequestId);
|
||||
//qCWarning(dcZigbeeNetwork()) << "#### Insert network reply" << reply << "ID:" << networkRequestId << "Current reply count" << m_pendingReplies.count();
|
||||
m_pendingReplies.insert(networkRequestId, reply);
|
||||
|
||||
// The request has been sent successfully to the device, start the timeout timer now
|
||||
startWaitingReply(reply);
|
||||
});
|
||||
|
|
@ -404,6 +410,23 @@ 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;
|
||||
// }
|
||||
|
||||
// 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);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ SOURCES += \
|
|||
backends/nxp/zigbeebridgecontrollernxp.cpp \
|
||||
backends/nxp/zigbeenetworknxp.cpp \
|
||||
zcl/closures/zigbeeclusterdoorlock.cpp \
|
||||
zcl/general/zigbeeclustergroups.cpp \
|
||||
zcl/general/zigbeeclusteridentify.cpp \
|
||||
zcl/general/zigbeeclusterlevelcontrol.cpp \
|
||||
zcl/general/zigbeeclusteronoff.cpp \
|
||||
|
|
@ -72,6 +73,7 @@ HEADERS += \
|
|||
backends/nxp/zigbeebridgecontrollernxp.h \
|
||||
backends/nxp/zigbeenetworknxp.h \
|
||||
zcl/closures/zigbeeclusterdoorlock.h \
|
||||
zcl/general/zigbeeclustergroups.h \
|
||||
zcl/general/zigbeeclusteridentify.h \
|
||||
zcl/general/zigbeeclusterlevelcontrol.h \
|
||||
zcl/general/zigbeeclusteronoff.h \
|
||||
|
|
|
|||
|
|
@ -187,14 +187,14 @@ public:
|
|||
AlarmMaskGeneralHardwareFault = 0x01,
|
||||
AlarmMaskGeneralSoftwareFault = 0x02
|
||||
};
|
||||
Q_ENUM(AlarmMask)
|
||||
Q_FLAG(AlarmMask)
|
||||
Q_DECLARE_FLAGS(AlarmMasks, AlarmMask)
|
||||
|
||||
enum DiableLocalConfig {
|
||||
DiableLocalConfigReset = 0x01,
|
||||
DiableLocalConfigDeviceConfiguration = 0x02
|
||||
};
|
||||
Q_ENUM(DiableLocalConfig)
|
||||
Q_FLAG(DiableLocalConfig)
|
||||
Q_DECLARE_FLAGS(DiableLocalConfigs, DiableLocalConfig)
|
||||
|
||||
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||
|
|
@ -206,7 +206,4 @@ private:
|
|||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(ZigbeeClusterBasic::AlarmMasks)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(ZigbeeClusterBasic::DiableLocalConfigs)
|
||||
|
||||
#endif // ZIGBEECLUSTERBASIC_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 "zigbeeclustergroups.h"
|
||||
#include "loggingcategory.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeClusterGroups::ZigbeeClusterGroups(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) :
|
||||
ZigbeeCluster(network, node, endpoint, ZigbeeClusterLibrary::ClusterIdGroups, direction, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterGroups::addGroup(quint16 groupId, const QString &groupName)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << groupId << static_cast<quint8>(Zigbee::CharString);
|
||||
for (int i = 0; i < groupName.length(); i++) {
|
||||
stream << static_cast<quint8>(groupName.toUtf8().at(i));
|
||||
}
|
||||
return executeClusterCommand(ZigbeeClusterGroups::CommandAddGroup, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterGroups::viewGroup(quint16 groupId)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << groupId;
|
||||
return executeClusterCommand(ZigbeeClusterGroups::CommandViewGroup, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterGroups::getGroupMembership(quint8 groupCount, const QList<quint16> &groupList)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << groupCount;
|
||||
for (int i = 0; i < groupList.length(); i++) {
|
||||
stream << groupList.at(i);
|
||||
}
|
||||
return executeClusterCommand(ZigbeeClusterGroups::CommandGetGroupMembership, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterGroups::removeGroup(quint16 groupId)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << groupId;
|
||||
return executeClusterCommand(ZigbeeClusterGroups::CommandRemoveGroup, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterGroups::removeAllGroups()
|
||||
{
|
||||
return executeClusterCommand(ZigbeeClusterGroups::CommandRemoveAllGroups);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterGroups::addGroupIfIdentifying(quint16 groupId, const QString &groupName)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << groupId << static_cast<quint8>(Zigbee::CharString);
|
||||
for (int i = 0; i < groupName.length(); i++) {
|
||||
stream << static_cast<quint8>(groupName.toUtf8().at(i));
|
||||
}
|
||||
return executeClusterCommand(ZigbeeClusterGroups::CommandAddGroup, payload);
|
||||
}
|
||||
|
||||
void ZigbeeClusterGroups::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||
updateOrAddAttribute(attribute);
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 ZIGBEECLUSTERGROUPS_H
|
||||
#define ZIGBEECLUSTERGROUPS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "zcl/zigbeecluster.h"
|
||||
|
||||
class ZigbeeClusterGroups : public ZigbeeCluster
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Attribute {
|
||||
// 1 supported, 0 not supported
|
||||
AttributeNameSupport = 0x0000
|
||||
};
|
||||
Q_ENUM(Attribute)
|
||||
|
||||
enum Command {
|
||||
CommandAddGroup = 0x00,
|
||||
CommandViewGroup = 0x01,
|
||||
CommandGetGroupMembership = 0x02,
|
||||
CommandRemoveGroup = 0x03,
|
||||
CommandRemoveAllGroups = 0x04,
|
||||
CommandAddGroupIfIdentifying = 0x05
|
||||
};
|
||||
Q_ENUM(Command)
|
||||
|
||||
explicit ZigbeeClusterGroups(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeClusterReply *addGroup(quint16 groupId, const QString &groupName);
|
||||
ZigbeeClusterReply *viewGroup(quint16 groupId);
|
||||
ZigbeeClusterReply *getGroupMembership(quint8 groupCount, const QList<quint16> &groupList);
|
||||
ZigbeeClusterReply *removeGroup(quint16 groupId);
|
||||
ZigbeeClusterReply *removeAllGroups();
|
||||
ZigbeeClusterReply *addGroupIfIdentifying(quint16 groupId, const QString &groupName);
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // ZIGBEECLUSTERGROUPS_H
|
||||
|
|
@ -611,6 +611,7 @@ void ZigbeeNetwork::setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::Zig
|
|||
|
||||
void ZigbeeNetwork::finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error)
|
||||
{
|
||||
qCDebug(dcZigbeeNetwork()) << "Finish network reply" << reply << error;
|
||||
reply->m_error = error;
|
||||
switch(reply->error()) {
|
||||
case ZigbeeNetworkReply::ErrorNoError:
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@ void ZigbeeNode::readManufacturerName(ZigbeeClusterBasic *basicCluster)
|
|||
if (m_requestRetry < 3) {
|
||||
m_requestRetry++;
|
||||
qCDebug(dcZigbeeNode()) << "Retry to read manufacturer name from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
||||
readManufacturerName(basicCluster);
|
||||
QTimer::singleShot(1000, this, [=](){readManufacturerName(basicCluster);});
|
||||
} else {
|
||||
qCWarning(dcZigbeeNode()) << "Failed to read manufacturer name from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
||||
m_requestRetry = 0;
|
||||
|
|
@ -564,7 +564,7 @@ void ZigbeeNode::readModelIdentifier(ZigbeeClusterBasic *basicCluster)
|
|||
if (m_requestRetry < 3) {
|
||||
m_requestRetry++;
|
||||
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
||||
readModelIdentifier(basicCluster);
|
||||
QTimer::singleShot(1000, this, [=](){readModelIdentifier(basicCluster);});
|
||||
} else {
|
||||
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
||||
m_requestRetry = 0;
|
||||
|
|
@ -605,11 +605,11 @@ void ZigbeeNode::readSoftwareBuildId(ZigbeeClusterBasic *basicCluster)
|
|||
if (m_requestRetry < 3) {
|
||||
m_requestRetry++;
|
||||
qCDebug(dcZigbeeNode()) << "Retry to read model identifier from" << this << basicCluster << m_requestRetry << "/" << "3 attempts.";
|
||||
readModelIdentifier(basicCluster);
|
||||
QTimer::singleShot(1000, this, [=](){readSoftwareBuildId(basicCluster);});
|
||||
} else {
|
||||
qCWarning(dcZigbeeNode()) << "Failed to read model identifier from" << this << basicCluster << "after 3 attempts. Giving up and continue...";
|
||||
m_requestRetry = 0;
|
||||
readSoftwareBuildId(basicCluster);
|
||||
setState(StateInitialized);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,6 +175,8 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(ZigbeeClusterLibrary::ClusterId
|
|||
return new ZigbeeClusterOnOff(m_network, m_node, this, direction, this);
|
||||
case ZigbeeClusterLibrary::ClusterIdLevelControl:
|
||||
return new ZigbeeClusterLevelControl(m_network, m_node, this, direction, this);
|
||||
case ZigbeeClusterLibrary::ClusterIdGroups:
|
||||
return new ZigbeeClusterGroups(m_network, m_node, this, direction, this);
|
||||
|
||||
// Measurement
|
||||
case ZigbeeClusterLibrary::ClusterIdIlluminanceMeasurement:
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "zcl/general/zigbeeclusteridentify.h"
|
||||
#include "zcl/general/zigbeeclusterlevelcontrol.h"
|
||||
#include "zcl/general/zigbeeclusterpowerconfiguration.h"
|
||||
#include "zcl/general/zigbeeclustergroups.h"
|
||||
|
||||
#include "zcl/closures/zigbeeclusterdoorlock.h"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue