Start implementing clusters
This commit is contained in:
parent
3e8da8ee26
commit
7cdf772b1a
14
README.md
14
README.md
@ -18,3 +18,17 @@ Depending on your available hardware following gateway modules are supported
|
|||||||
* RaspBee
|
* RaspBee
|
||||||
* ConBee II
|
* ConBee II
|
||||||
* RaspBee II
|
* RaspBee II
|
||||||
|
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
ZigbeeNetwork
|
||||||
|
- ZDO handler
|
||||||
|
- ZCL handler
|
||||||
|
- ZHA handler
|
||||||
|
- ZLL handler
|
||||||
|
- GP handler
|
||||||
|
|
||||||
|
- [ZigbeeNode]
|
||||||
|
- [ZigbeeNodeEndpoints]
|
||||||
|
- Profile
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
QT += gui serialport
|
QT += gui serialport sql
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += -Werror -std=c++11
|
QMAKE_CXXFLAGS += -Werror -std=c++11
|
||||||
QMAKE_LFLAGS += -std=c++11
|
QMAKE_LFLAGS += -std=c++11
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
#include "zigbeechannelmask.h"
|
#include "zigbeechannelmask.h"
|
||||||
#include "zigbeedeviceprofile.h"
|
#include "zdo/zigbeedeviceprofile.h"
|
||||||
#include "zigbeebridgecontrollerdeconz.h"
|
#include "zigbeebridgecontrollerdeconz.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
|||||||
@ -25,8 +25,8 @@
|
|||||||
*
|
*
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "zdo/zigbeedeviceprofile.h"
|
||||||
#include "zigbeenetworkdeconz.h"
|
#include "zigbeenetworkdeconz.h"
|
||||||
#include "zigbeedeviceprofile.h"
|
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
|
||||||
@ -109,11 +109,6 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::setPermitJoin(quint16 shortAddress, qui
|
|||||||
return sendRequest(request);
|
return sendRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 ZigbeeNetworkDeconz::generateSequenceNumber()
|
|
||||||
{
|
|
||||||
return m_sequenceNumber++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state)
|
void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state)
|
||||||
{
|
{
|
||||||
if (m_createState == state)
|
if (m_createState == state)
|
||||||
@ -322,8 +317,8 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is a response for a ZDO request
|
|
||||||
foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) {
|
foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) {
|
||||||
|
// Check if this is a response for a ZDO request
|
||||||
if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) {
|
if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) {
|
||||||
// We have a reply which is waiting for a ZDO response, lets check if they match
|
// We have a reply which is waiting for a ZDO response, lets check if they match
|
||||||
// Check if this is the response to the sent request command
|
// Check if this is the response to the sent request command
|
||||||
@ -347,6 +342,16 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "FIXME: Unhandled ZDO indication" << indication;
|
qCWarning(dcZigbeeNetwork()) << "FIXME: Unhandled ZDO indication" << indication;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetworkDeconz::handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication)
|
||||||
|
{
|
||||||
|
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(static_cast<Zigbee::ClusterId>(indication.clusterId), indication.asdu);
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "ZCL HA" << indication << frame;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent)
|
ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent)
|
||||||
@ -412,22 +417,8 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
|||||||
// Check if we have to create a pan ID and select the channel
|
// Check if we have to create a pan ID and select the channel
|
||||||
if (panId() == 0) {
|
if (panId() == 0) {
|
||||||
m_createNewNetwork = true;
|
m_createNewNetwork = true;
|
||||||
//setExtendedPanId(ZigbeeUtils::generateRandomPanId());
|
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Created new PAN ID:" << extendedPanId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: we cannot read or write the network key here.
|
|
||||||
|
|
||||||
// if (securityConfiguration().networkKey().isNull()) {
|
|
||||||
// m_createNewNetwork = true;
|
|
||||||
// qCDebug(dcZigbeeNetwork()) << "Create a new network key";
|
|
||||||
// ZigbeeNetworkKey key = ZigbeeNetworkKey::generateKey();
|
|
||||||
// m_securityConfiguration.setNetworkKey(key);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().networkKey() << "network link key";
|
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().globalTrustCenterLinkKey() << "global trust center link key";
|
|
||||||
|
|
||||||
// - Read the firmware version
|
// - Read the firmware version
|
||||||
// - Read the network configuration parameters
|
// - Read the network configuration parameters
|
||||||
// - Read the network state
|
// - Read the network state
|
||||||
@ -630,6 +621,15 @@ void ZigbeeNetworkDeconz::onAspDataIndicationReceived(const DeconzApsDataIndicat
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (indication.profileId == Zigbee::ZigbeeProfileLightLink) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indication.profileId == Zigbee::ZigbeeProfileHomeAutomation) {
|
||||||
|
handleZigbeeHomeAutomationIndication(indication);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: handle it
|
// FIXME: handle it
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Unhandled indication" << indication;
|
qCDebug(dcZigbeeNetwork()) << "Unhandled indication" << indication;
|
||||||
@ -660,7 +660,7 @@ void ZigbeeNetworkDeconz::startNetwork()
|
|||||||
m_permitJoining = false;
|
m_permitJoining = false;
|
||||||
emit permitJoiningChanged(m_permitJoining);
|
emit permitJoiningChanged(m_permitJoining);
|
||||||
setState(StateOffline);
|
setState(StateOffline);
|
||||||
//setStartingState(StartingStateNone);
|
setCreateNetworkState(CreateNetworkStateIdle);
|
||||||
setError(ErrorHardwareUnavailable);
|
setError(ErrorHardwareUnavailable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
#include "zigbeenetwork.h"
|
#include "zigbeenetwork.h"
|
||||||
#include "zigbeenodedeconz.h"
|
#include "zigbeenodedeconz.h"
|
||||||
#include "zigbeechannelmask.h"
|
#include "zigbeechannelmask.h"
|
||||||
|
#include "zigbeeclusterlibrary.h"
|
||||||
#include "zigbeebridgecontrollerdeconz.h"
|
#include "zigbeebridgecontrollerdeconz.h"
|
||||||
|
|
||||||
class ZigbeeNetworkDeconz : public ZigbeeNetwork
|
class ZigbeeNetworkDeconz : public ZigbeeNetwork
|
||||||
@ -57,8 +58,6 @@ public:
|
|||||||
|
|
||||||
ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress, quint8 duration);
|
ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress, quint8 duration);
|
||||||
|
|
||||||
quint8 generateSequenceNumber();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
||||||
bool m_networkRunning = false;
|
bool m_networkRunning = false;
|
||||||
@ -69,8 +68,6 @@ private:
|
|||||||
|
|
||||||
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
|
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
|
||||||
|
|
||||||
quint8 m_sequenceNumber = 0;
|
|
||||||
|
|
||||||
QTimer *m_pollNetworkStateTimer = nullptr;
|
QTimer *m_pollNetworkStateTimer = nullptr;
|
||||||
void setCreateNetworkState(CreateNetworkState state);
|
void setCreateNetworkState(CreateNetworkState state);
|
||||||
|
|
||||||
@ -80,6 +77,7 @@ private:
|
|||||||
// ZZL
|
// ZZL
|
||||||
|
|
||||||
// HA
|
// HA
|
||||||
|
void handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication);
|
||||||
|
|
||||||
// GP
|
// GP
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
#include "zigbeenodedeconz.h"
|
#include "zigbeenodedeconz.h"
|
||||||
#include "zigbeedeviceprofile.h"
|
#include "zdo/zigbeedeviceprofile.h"
|
||||||
#include "zigbeenetworkdeconz.h"
|
#include "zigbeenetworkdeconz.h"
|
||||||
#include "zigbeenodeendpointdeconz.h"
|
#include "zigbeenodeendpointdeconz.h"
|
||||||
|
|
||||||
@ -36,7 +36,7 @@
|
|||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
|
||||||
ZigbeeNodeDeconz::ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent) :
|
ZigbeeNodeDeconz::ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent) :
|
||||||
ZigbeeNode(parent),
|
ZigbeeNode(network, parent),
|
||||||
m_network(network)
|
m_network(network)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -138,10 +138,45 @@ ZigbeeNetworkReply *ZigbeeNodeDeconz::requestSimpleDescriptor(quint8 endpoint)
|
|||||||
return m_network->sendRequest(request);
|
return m_network->sendRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *ZigbeeNodeDeconz::requestLeaveNetwork(bool rejoin, bool removeChildren)
|
||||||
|
{
|
||||||
|
ZigbeeNetworkRequest request;
|
||||||
|
request.setRequestId(m_network->generateSequenceNumber());
|
||||||
|
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||||
|
request.setDestinationShortAddress(shortAddress());
|
||||||
|
request.setDestinationEndpoint(0); // ZDO
|
||||||
|
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||||
|
request.setClusterId(ZigbeeDeviceProfile::MgmtLeaveRequest);
|
||||||
|
request.setSourceEndpoint(0); // ZDO
|
||||||
|
|
||||||
|
// Build ASDU
|
||||||
|
QByteArray asdu;
|
||||||
|
quint8 leaveFlag = 0;
|
||||||
|
if (rejoin) {
|
||||||
|
leaveFlag |= 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeChildren) {
|
||||||
|
leaveFlag |= 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << request.requestId() << extendedAddress().toUInt64() << leaveFlag;
|
||||||
|
request.setAsdu(asdu);
|
||||||
|
|
||||||
|
// We expect an indication with the response and the confirmation
|
||||||
|
request.setExpectIndication(true);
|
||||||
|
return m_network->sendRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNodeDeconz::leaveNetworkRequest(bool rejoin, bool removeChildren)
|
void ZigbeeNodeDeconz::leaveNetworkRequest(bool rejoin, bool removeChildren)
|
||||||
{
|
{
|
||||||
Q_UNUSED(rejoin)
|
ZigbeeNetworkReply *reply = requestLeaveNetwork(rejoin, removeChildren);
|
||||||
Q_UNUSED(removeChildren)
|
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||||
|
// TODO: check reply error
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNodeDeconz::initNodeDescriptor()
|
void ZigbeeNodeDeconz::initNodeDescriptor()
|
||||||
@ -309,7 +344,7 @@ void ZigbeeNodeDeconz::initEndpoints()
|
|||||||
// Create endpoint
|
// Create endpoint
|
||||||
ZigbeeNodeEndpointDeconz *endpoint = nullptr;
|
ZigbeeNodeEndpointDeconz *endpoint = nullptr;
|
||||||
if (!hasEndpoint(endpointId)) {
|
if (!hasEndpoint(endpointId)) {
|
||||||
ZigbeeNodeEndpointDeconz *endpoint = qobject_cast<ZigbeeNodeEndpointDeconz *>(createNodeEndpoint(endpointId, this));
|
endpoint = qobject_cast<ZigbeeNodeEndpointDeconz *>(createNodeEndpoint(endpointId, this));
|
||||||
m_endpoints.append(endpoint);
|
m_endpoints.append(endpoint);
|
||||||
} else {
|
} else {
|
||||||
endpoint = qobject_cast<ZigbeeNodeEndpointDeconz *>(getEndpoint(endpointId));
|
endpoint = qobject_cast<ZigbeeNodeEndpointDeconz *>(getEndpoint(endpointId));
|
||||||
@ -323,7 +358,7 @@ void ZigbeeNodeDeconz::initEndpoints()
|
|||||||
quint16 clusterId = 0;
|
quint16 clusterId = 0;
|
||||||
stream >> clusterId;
|
stream >> clusterId;
|
||||||
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||||
endpoint->addInputCluster(new ZigbeeCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input, endpoint));
|
endpoint->addInputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input, endpoint));
|
||||||
}
|
}
|
||||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
|
|
||||||
@ -335,7 +370,7 @@ void ZigbeeNodeDeconz::initEndpoints()
|
|||||||
quint16 clusterId = 0;
|
quint16 clusterId = 0;
|
||||||
stream >> clusterId;
|
stream >> clusterId;
|
||||||
if (!endpoint->hasOutputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
if (!endpoint->hasOutputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||||
endpoint->addOutputCluster(new ZigbeeCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
endpoint->addOutputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
||||||
}
|
}
|
||||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
}
|
}
|
||||||
@ -354,10 +389,9 @@ void ZigbeeNodeDeconz::initEndpoints()
|
|||||||
void ZigbeeNodeDeconz::initBasicCluster()
|
void ZigbeeNodeDeconz::initBasicCluster()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
setState(StateInitialized);
|
setState(StateInitialized);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNodeDeconz::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report)
|
void ZigbeeNodeDeconz::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report)
|
||||||
|
|||||||
@ -50,6 +50,8 @@ public:
|
|||||||
ZigbeeNetworkReply *requestActiveEndpoints();
|
ZigbeeNetworkReply *requestActiveEndpoints();
|
||||||
ZigbeeNetworkReply *requestSimpleDescriptor(quint8 endpoint);
|
ZigbeeNetworkReply *requestSimpleDescriptor(quint8 endpoint);
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *requestLeaveNetwork(bool rejoin = false, bool removeChildren = false);
|
||||||
|
|
||||||
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
|
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -36,20 +36,6 @@ ZigbeeNodeEndpointDeconz::ZigbeeNodeEndpointDeconz(ZigbeeNetworkDeconz *network,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeNetworkReply *ZigbeeNodeEndpointDeconz::readAttribute(ZigbeeCluster *cluster, QList<quint16> attributes)
|
|
||||||
{
|
|
||||||
Q_UNUSED(cluster)
|
|
||||||
Q_UNUSED(attributes)
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeNetworkReply *ZigbeeNodeEndpointDeconz::configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations)
|
|
||||||
{
|
|
||||||
Q_UNUSED(cluster)
|
|
||||||
Q_UNUSED(reportConfigurations)
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNodeEndpointDeconz::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute)
|
void ZigbeeNodeEndpointDeconz::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
Q_UNUSED(clusterId)
|
Q_UNUSED(clusterId)
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "zigbeenodeendpoint.h"
|
#include "zigbeenodeendpoint.h"
|
||||||
|
#include "zigbeeclusterlibrary.h"
|
||||||
|
|
||||||
class ZigbeeNodeDeconz;
|
class ZigbeeNodeDeconz;
|
||||||
class ZigbeeNetworkDeconz;
|
class ZigbeeNetworkDeconz;
|
||||||
@ -43,9 +44,6 @@ class ZigbeeNodeEndpointDeconz : public ZigbeeNodeEndpoint
|
|||||||
public:
|
public:
|
||||||
explicit ZigbeeNodeEndpointDeconz(ZigbeeNetworkDeconz *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
explicit ZigbeeNodeEndpointDeconz(ZigbeeNetworkDeconz *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
||||||
|
|
||||||
ZigbeeNetworkReply *readAttribute(ZigbeeCluster *cluster, QList<quint16> attributes) override;
|
|
||||||
ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Cluster commands
|
// Cluster commands
|
||||||
void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) override;
|
void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) override;
|
||||||
|
|||||||
@ -10,23 +10,29 @@ SOURCES += \
|
|||||||
deconz/zigbeenetworkdeconz.cpp \
|
deconz/zigbeenetworkdeconz.cpp \
|
||||||
deconz/zigbeenodedeconz.cpp \
|
deconz/zigbeenodedeconz.cpp \
|
||||||
deconz/zigbeenodeendpointdeconz.cpp \
|
deconz/zigbeenodeendpointdeconz.cpp \
|
||||||
nxp/interface/zigbeeinterface.cpp \
|
# nxp/interface/zigbeeinterface.cpp \
|
||||||
nxp/interface/zigbeeinterfacemessage.cpp \
|
# nxp/interface/zigbeeinterfacemessage.cpp \
|
||||||
nxp/interface/zigbeeinterfacerequest.cpp \
|
# nxp/interface/zigbeeinterfacerequest.cpp \
|
||||||
nxp/interface/zigbeeinterfacereply.cpp \
|
# nxp/interface/zigbeeinterfacereply.cpp \
|
||||||
nxp/zigbeenetworknxp.cpp \
|
# nxp/zigbeenetworknxp.cpp \
|
||||||
nxp/zigbeebridgecontrollernxp.cpp \
|
# nxp/zigbeebridgecontrollernxp.cpp \
|
||||||
nxp/zigbeenodeendpointnxp.cpp \
|
# nxp/zigbeenodeendpointnxp.cpp \
|
||||||
nxp/zigbeenodenxp.cpp \
|
# nxp/zigbeenodenxp.cpp \
|
||||||
|
zcl/zigbeeclusterbasic.cpp \
|
||||||
|
zdo/zigbeedeviceobject.cpp \
|
||||||
|
zdo/zigbeedeviceobjectreply.cpp \
|
||||||
|
zdo/zigbeedeviceprofilehandler.cpp \
|
||||||
|
zdo/zigbeedeviceprofile.cpp \
|
||||||
zigbeeadpu.cpp \
|
zigbeeadpu.cpp \
|
||||||
zigbeebridgecontroller.cpp \
|
zigbeebridgecontroller.cpp \
|
||||||
zigbeechannelmask.cpp \
|
zigbeechannelmask.cpp \
|
||||||
zigbeecluster.cpp \
|
zigbeecluster.cpp \
|
||||||
zigbeeclusterattribute.cpp \
|
zigbeeclusterattribute.cpp \
|
||||||
zigbeeclusterlibrary.cpp \
|
zigbeeclusterlibrary.cpp \
|
||||||
zigbeedeviceprofile.cpp \
|
zigbeeclusterlibraryreply.cpp \
|
||||||
zigbeemanufacturer.cpp \
|
zigbeemanufacturer.cpp \
|
||||||
zigbeenetwork.cpp \
|
zigbeenetwork.cpp \
|
||||||
|
zigbeenetworkdatabase.cpp \
|
||||||
zigbeenetworkkey.cpp \
|
zigbeenetworkkey.cpp \
|
||||||
zigbeenetworkmanager.cpp \
|
zigbeenetworkmanager.cpp \
|
||||||
zigbee.cpp \
|
zigbee.cpp \
|
||||||
@ -39,6 +45,7 @@ SOURCES += \
|
|||||||
zigbeenode.cpp \
|
zigbeenode.cpp \
|
||||||
zigbeeaddress.cpp \
|
zigbeeaddress.cpp \
|
||||||
|
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
deconz/interface/deconz.h \
|
deconz/interface/deconz.h \
|
||||||
deconz/interface/zigbeeinterfacedeconz.h \
|
deconz/interface/zigbeeinterfacedeconz.h \
|
||||||
@ -47,23 +54,29 @@ HEADERS += \
|
|||||||
deconz/zigbeenetworkdeconz.h \
|
deconz/zigbeenetworkdeconz.h \
|
||||||
deconz/zigbeenodedeconz.h \
|
deconz/zigbeenodedeconz.h \
|
||||||
deconz/zigbeenodeendpointdeconz.h \
|
deconz/zigbeenodeendpointdeconz.h \
|
||||||
nxp/interface/zigbeeinterface.h \
|
# nxp/interface/zigbeeinterface.h \
|
||||||
nxp/interface/zigbeeinterfacemessage.h \
|
# nxp/interface/zigbeeinterfacemessage.h \
|
||||||
nxp/interface/zigbeeinterfacerequest.h \
|
# nxp/interface/zigbeeinterfacerequest.h \
|
||||||
nxp/interface/zigbeeinterfacereply.h \
|
# nxp/interface/zigbeeinterfacereply.h \
|
||||||
nxp/zigbeenetworknxp.h \
|
# nxp/zigbeenetworknxp.h \
|
||||||
nxp/zigbeebridgecontrollernxp.h \
|
# nxp/zigbeebridgecontrollernxp.h \
|
||||||
nxp/zigbeenodeendpointnxp.h \
|
# nxp/zigbeenodeendpointnxp.h \
|
||||||
nxp/zigbeenodenxp.h \
|
# nxp/zigbeenodenxp.h \
|
||||||
|
zcl/zigbeeclusterbasic.h \
|
||||||
|
zdo/zigbeedeviceobject.h \
|
||||||
|
zdo/zigbeedeviceobjectreply.h \
|
||||||
|
zdo/zigbeedeviceprofilehandler.h \
|
||||||
|
zdo/zigbeedeviceprofile.h \
|
||||||
zigbeeadpu.h \
|
zigbeeadpu.h \
|
||||||
zigbeebridgecontroller.h \
|
zigbeebridgecontroller.h \
|
||||||
zigbeechannelmask.h \
|
zigbeechannelmask.h \
|
||||||
zigbeecluster.h \
|
zigbeecluster.h \
|
||||||
zigbeeclusterattribute.h \
|
zigbeeclusterattribute.h \
|
||||||
zigbeeclusterlibrary.h \
|
zigbeeclusterlibrary.h \
|
||||||
zigbeedeviceprofile.h \
|
zigbeeclusterlibraryreply.h \
|
||||||
zigbeemanufacturer.h \
|
zigbeemanufacturer.h \
|
||||||
zigbeenetwork.h \
|
zigbeenetwork.h \
|
||||||
|
zigbeenetworkdatabase.h \
|
||||||
zigbeenetworkkey.h \
|
zigbeenetworkkey.h \
|
||||||
zigbeenetworkmanager.h \
|
zigbeenetworkmanager.h \
|
||||||
zigbee.h \
|
zigbee.h \
|
||||||
@ -76,6 +89,7 @@ HEADERS += \
|
|||||||
zigbeenode.h \
|
zigbeenode.h \
|
||||||
zigbeeaddress.h \
|
zigbeeaddress.h \
|
||||||
|
|
||||||
|
|
||||||
# install header file with relative subdirectory
|
# install header file with relative subdirectory
|
||||||
for (header, HEADERS) {
|
for (header, HEADERS) {
|
||||||
path = $$[QT_INSTALL_PREFIX]/include/nymea-zigbee/$${dirname(header)}
|
path = $$[QT_INSTALL_PREFIX]/include/nymea-zigbee/$${dirname(header)}
|
||||||
|
|||||||
@ -32,4 +32,5 @@ Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode")
|
|||||||
Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster")
|
Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
||||||
|
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
|
||||||
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
||||||
|
|||||||
@ -36,6 +36,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode)
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
||||||
|
|
||||||
#endif // LOGGINGCATEGORY_H
|
#endif // LOGGINGCATEGORY_H
|
||||||
|
|||||||
7
libnymea-zigbee/zcl/zigbeeclusterbasic.cpp
Normal file
7
libnymea-zigbee/zcl/zigbeeclusterbasic.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "zigbeeclusterbasic.h"
|
||||||
|
|
||||||
|
ZigbeeClusterBasic::ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) :
|
||||||
|
ZigbeeCluster(network, node, endpoint, Zigbee::ClusterIdBasic, direction, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
51
libnymea-zigbee/zcl/zigbeeclusterbasic.h
Normal file
51
libnymea-zigbee/zcl/zigbeeclusterbasic.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef ZIGBEECLUSTERBASIC_H
|
||||||
|
#define ZIGBEECLUSTERBASIC_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zigbeecluster.h"
|
||||||
|
|
||||||
|
class ZigbeeClusterBasic : public ZigbeeCluster
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Attribute {
|
||||||
|
AttributeZclVersion = 0x0000, // Mandatory
|
||||||
|
AttributeAppVersion = 0x0001,
|
||||||
|
AttributeStackVersion = 0x0002,
|
||||||
|
AttributeHardwareVersion = 0x0003,
|
||||||
|
AttributeManufacturerName = 0x0004,
|
||||||
|
AttributeModelIdentifier = 0x0005,
|
||||||
|
AttributeDateCode = 0x0006, // ISO 8601 YYYYMMDD
|
||||||
|
AttributePowerSource = 0x0007, // Mandatory
|
||||||
|
AttributeLocationDescription = 0x0010,
|
||||||
|
AttributePhysicalEnvironment = 0x0011,
|
||||||
|
AttributeDeviceEnabled = 0x0012, // 0: disabled, 1: enabled
|
||||||
|
AttributeAlarmMask = 0x0013,
|
||||||
|
AttributeDisableLocalConfig = 0x0014,
|
||||||
|
AttributeSwBuildId = 0x4000
|
||||||
|
};
|
||||||
|
Q_ENUM(Attribute)
|
||||||
|
|
||||||
|
// From attribute 0x0007 power source
|
||||||
|
enum AttributePowerSourceValue {
|
||||||
|
AttributePowerSourceValueUnknown = 0x00,
|
||||||
|
AttributePowerSourceValueMainsSinglePhase = 0x01,
|
||||||
|
AttributePowerSourceValueMainsThreePhase = 0x02,
|
||||||
|
AttributePowerSourceValueBattery = 0x03,
|
||||||
|
AttributePowerSourceValueDcSource = 0x04,
|
||||||
|
AttributePowerSourceValueEmergencyMainsConstantlyPowered = 0x05,
|
||||||
|
AttributePowerSourceValueEmergencyMainsTransferSwitch = 0x06
|
||||||
|
};
|
||||||
|
Q_ENUM(AttributePowerSourceValue)
|
||||||
|
|
||||||
|
|
||||||
|
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEECLUSTERBASIC_H
|
||||||
9
libnymea-zigbee/zdo/zigbeedeviceobject.cpp
Normal file
9
libnymea-zigbee/zdo/zigbeedeviceobject.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "zigbeedeviceobject.h"
|
||||||
|
#include "zigbeenetwork.h"
|
||||||
|
|
||||||
|
ZigbeeDeviceObject::ZigbeeDeviceObject(ZigbeeNetwork *network, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_network(network)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
21
libnymea-zigbee/zdo/zigbeedeviceobject.h
Normal file
21
libnymea-zigbee/zdo/zigbeedeviceobject.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef ZIGBEEDEVICEOBJECT_H
|
||||||
|
#define ZIGBEEDEVICEOBJECT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ZigbeeNetwork;
|
||||||
|
|
||||||
|
class ZigbeeDeviceObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ZigbeeDeviceObject(ZigbeeNetwork *network, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ZigbeeNetwork *m_network = nullptr;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEEDEVICEOBJECT_H
|
||||||
6
libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp
Normal file
6
libnymea-zigbee/zdo/zigbeedeviceobjectreply.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "zigbeedeviceobjectreply.h"
|
||||||
|
|
||||||
|
ZigbeeDeviceObjectReply::ZigbeeDeviceObjectReply(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
16
libnymea-zigbee/zdo/zigbeedeviceobjectreply.h
Normal file
16
libnymea-zigbee/zdo/zigbeedeviceobjectreply.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ZIGBEEDEVICEOBJECTREPLY_H
|
||||||
|
#define ZIGBEEDEVICEOBJECTREPLY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ZigbeeDeviceObjectReply : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ZigbeeDeviceObjectReply(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEEDEVICEOBJECTREPLY_H
|
||||||
@ -45,6 +45,13 @@ class ZigbeeDeviceProfile
|
|||||||
Q_GADGET
|
Q_GADGET
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum Status {
|
||||||
|
StatusSuccess = 0x00,
|
||||||
|
StatusInvalidRequestType = 0x01,
|
||||||
|
StatusDeviceNotFound = 0x02
|
||||||
|
};
|
||||||
|
Q_ENUM(Status)
|
||||||
|
|
||||||
enum ZdoCommand {
|
enum ZdoCommand {
|
||||||
/* Requests */
|
/* Requests */
|
||||||
/*Device and service discovery */
|
/*Device and service discovery */
|
||||||
6
libnymea-zigbee/zdo/zigbeedeviceprofilehandler.cpp
Normal file
6
libnymea-zigbee/zdo/zigbeedeviceprofilehandler.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "zigbeedeviceprofilehandler.h"
|
||||||
|
|
||||||
|
ZigbeeDeviceProfileHandler::ZigbeeDeviceProfileHandler(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
16
libnymea-zigbee/zdo/zigbeedeviceprofilehandler.h
Normal file
16
libnymea-zigbee/zdo/zigbeedeviceprofilehandler.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ZIGBEEDEVICEPROFILEHANDLER_H
|
||||||
|
#define ZIGBEEDEVICEPROFILEHANDLER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class ZigbeeDeviceProfileHandler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ZigbeeDeviceProfileHandler(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEEDEVICEPROFILEHANDLER_H
|
||||||
@ -26,11 +26,20 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
#include "zigbeenetwork.h"
|
||||||
#include "zigbeecluster.h"
|
#include "zigbeecluster.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
|
#include "zigbeenetworkreply.h"
|
||||||
|
#include "zigbeeclusterlibrary.h"
|
||||||
|
#include "zigbeenetworkrequest.h"
|
||||||
|
|
||||||
ZigbeeCluster::ZigbeeCluster(Zigbee::ClusterId clusterId, Direction direction, QObject *parent) :
|
#include <QDataStream>
|
||||||
|
|
||||||
|
ZigbeeCluster::ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Zigbee::ClusterId clusterId, Direction direction, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
|
m_network(network),
|
||||||
|
m_node(node),
|
||||||
|
m_endpoint(endpoint),
|
||||||
m_clusterId(clusterId),
|
m_clusterId(clusterId),
|
||||||
m_direction(direction)
|
m_direction(direction)
|
||||||
{
|
{
|
||||||
@ -83,6 +92,50 @@ void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
||||||
|
{
|
||||||
|
// Build the request
|
||||||
|
ZigbeeNetworkRequest request;
|
||||||
|
request.setRequestId(m_network->generateSequenceNumber());
|
||||||
|
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||||
|
request.setDestinationShortAddress(static_cast<quint16>(m_node->shortAddress()));
|
||||||
|
request.setProfileId(m_endpoint->profile());
|
||||||
|
request.setClusterId(m_clusterId);
|
||||||
|
request.setSourceEndpoint(m_endpoint->endpointId());
|
||||||
|
request.setRadius(10);
|
||||||
|
|
||||||
|
// Build ZCL frame
|
||||||
|
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||||
|
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeGlobal; // Note: for general commands always use global
|
||||||
|
frameControl.disableDefaultResponse = true;
|
||||||
|
|
||||||
|
// ZCL header
|
||||||
|
ZigbeeClusterLibrary::Header header;
|
||||||
|
header.frameControl = frameControl;
|
||||||
|
header.command = ZigbeeClusterLibrary::CommandReadAttributes;
|
||||||
|
header.transactionSequenceNumber = m_network->generateTranactionSequenceNumber();
|
||||||
|
|
||||||
|
// ZCL payload
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
foreach (quint16 attribute, attributes) {
|
||||||
|
stream << attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put them together
|
||||||
|
ZigbeeClusterLibrary::Frame frame;
|
||||||
|
frame.clusterId = m_clusterId;
|
||||||
|
frame.header = header;
|
||||||
|
frame.payload = payload;
|
||||||
|
|
||||||
|
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||||
|
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Send read attributes request" << m_node << m_endpoint << this << attributes;
|
||||||
|
return m_network->sendRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
||||||
{
|
{
|
||||||
debug.nospace().noquote() << "ZigbeeCluster("
|
debug.nospace().noquote() << "ZigbeeCluster("
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
|
#include "zigbeeclusterlibrary.h"
|
||||||
#include "zigbeeclusterattribute.h"
|
#include "zigbeeclusterattribute.h"
|
||||||
|
|
||||||
struct ZigbeeClusterReportConfigurationRecord {
|
struct ZigbeeClusterReportConfigurationRecord {
|
||||||
@ -53,6 +54,12 @@ typedef struct ZigbeeClusterAttributeReport {
|
|||||||
QByteArray data;
|
QByteArray data;
|
||||||
} ZigbeeClusterAttributeReport;
|
} ZigbeeClusterAttributeReport;
|
||||||
|
|
||||||
|
|
||||||
|
class ZigbeeNode;
|
||||||
|
class ZigbeeNetwork;
|
||||||
|
class ZigbeeNodeEndpoint;
|
||||||
|
class ZigbeeNetworkReply;
|
||||||
|
|
||||||
class ZigbeeCluster : public QObject
|
class ZigbeeCluster : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -189,7 +196,7 @@ public:
|
|||||||
Q_ENUM(ColorControlClusterColorMode)
|
Q_ENUM(ColorControlClusterColorMode)
|
||||||
|
|
||||||
|
|
||||||
explicit ZigbeeCluster(Zigbee::ClusterId clusterId, Direction direction, QObject *parent = nullptr);
|
explicit ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Zigbee::ClusterId clusterId, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
Direction direction() const;
|
Direction direction() const;
|
||||||
|
|
||||||
@ -204,13 +211,18 @@ public:
|
|||||||
// FIXME: this should not be public
|
// FIXME: this should not be public
|
||||||
void setAttribute(const ZigbeeClusterAttribute &attribute);
|
void setAttribute(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
private:
|
// ZCL global commands
|
||||||
|
ZigbeeNetworkReply *readAttributes(QList<quint16> attributes);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ZigbeeNetwork *m_network = nullptr;
|
||||||
|
ZigbeeNode *m_node = nullptr;
|
||||||
|
ZigbeeNodeEndpoint *m_endpoint= nullptr;
|
||||||
|
|
||||||
Zigbee::ClusterId m_clusterId = Zigbee::ClusterIdUnknown;
|
Zigbee::ClusterId m_clusterId = Zigbee::ClusterIdUnknown;
|
||||||
Direction m_direction = Input;
|
Direction m_direction = Input;
|
||||||
QHash<quint16, ZigbeeClusterAttribute> m_attributes;
|
QHash<quint16, ZigbeeClusterAttribute> m_attributes;
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void attributeChanged(const ZigbeeClusterAttribute &attribute);
|
void attributeChanged(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
|
|||||||
@ -93,7 +93,7 @@ QByteArray ZigbeeClusterLibrary::buildHeader(const ZigbeeClusterLibrary::Header
|
|||||||
return headerData;
|
return headerData;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArray &frameData)
|
ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(Zigbee::ClusterId clusterId, const QByteArray &frameData)
|
||||||
{
|
{
|
||||||
QDataStream stream(frameData);
|
QDataStream stream(frameData);
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
@ -116,7 +116,6 @@ ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArra
|
|||||||
stream >> header.transactionSequenceNumber;
|
stream >> header.transactionSequenceNumber;
|
||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
|
|
||||||
stream >> commandByte;
|
stream >> commandByte;
|
||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
@ -124,8 +123,9 @@ ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArra
|
|||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
Frame frame;
|
Frame frame;
|
||||||
|
frame.clusterId = clusterId;
|
||||||
frame.header = header;
|
frame.header = header;
|
||||||
frame.payload = frameData.right(frameData.length() - offset);
|
frame.payload = frameData.right(frameData.length() - offset - 1);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Header &header)
|
|||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame)
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame)
|
||||||
{
|
{
|
||||||
debug.nospace() << "Zigbee Cluster Library Frame(";
|
debug.nospace() << "Zigbee Cluster Library Frame(" << frame.clusterId << ", ";
|
||||||
debug.nospace() << frame.header;
|
debug.nospace() << frame.header;
|
||||||
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(frame.payload) << ")";
|
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(frame.payload) << ")";
|
||||||
return debug.space();
|
return debug.space();
|
||||||
|
|||||||
@ -31,10 +31,13 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "zigbee.h"
|
||||||
|
|
||||||
class ZigbeeClusterLibrary
|
class ZigbeeClusterLibrary
|
||||||
{
|
{
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
public:
|
public:
|
||||||
|
/* General ZCL commans */
|
||||||
enum Command {
|
enum Command {
|
||||||
CommandReadAttributes = 0x00,
|
CommandReadAttributes = 0x00,
|
||||||
CommandReadAttributesResponse = 0x01,
|
CommandReadAttributesResponse = 0x01,
|
||||||
@ -90,6 +93,7 @@ public:
|
|||||||
} ZclHeader;
|
} ZclHeader;
|
||||||
|
|
||||||
typedef struct Frame {
|
typedef struct Frame {
|
||||||
|
Zigbee::ClusterId clusterId;
|
||||||
Header header;
|
Header header;
|
||||||
QByteArray payload;
|
QByteArray payload;
|
||||||
} Frame;
|
} Frame;
|
||||||
@ -100,7 +104,7 @@ public:
|
|||||||
|
|
||||||
static QByteArray buildHeader(const Header &header);
|
static QByteArray buildHeader(const Header &header);
|
||||||
|
|
||||||
static Frame parseFrameData(const QByteArray &frameData);
|
static Frame parseFrameData(Zigbee::ClusterId clusterId, const QByteArray &frameData);
|
||||||
static QByteArray buildFrame(const Frame &frame);
|
static QByteArray buildFrame(const Frame &frame);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
24
libnymea-zigbee/zigbeeclusterlibraryreply.cpp
Normal file
24
libnymea-zigbee/zigbeeclusterlibraryreply.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "zigbeeclusterlibraryreply.h"
|
||||||
|
|
||||||
|
ZigbeeNetworkRequest ZigbeeClusterLibraryReply::request() const
|
||||||
|
{
|
||||||
|
return m_request;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterLibrary::Frame ZigbeeClusterLibraryReply::requestFrame() const
|
||||||
|
{
|
||||||
|
return m_requestFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8 ZigbeeClusterLibraryReply::transactionSequenceNumber() const
|
||||||
|
{
|
||||||
|
return m_requestFrame.header.transactionSequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterLibraryReply::ZigbeeClusterLibraryReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_request(request),
|
||||||
|
m_requestFrame(requestFrame)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
35
libnymea-zigbee/zigbeeclusterlibraryreply.h
Normal file
35
libnymea-zigbee/zigbeeclusterlibraryreply.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef ZIGBEECLUSTERLIBRARYREPLY_H
|
||||||
|
#define ZIGBEECLUSTERLIBRARYREPLY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zigbeenetworkrequest.h"
|
||||||
|
#include "zigbeeclusterlibrary.h"
|
||||||
|
|
||||||
|
class ZigbeeClusterLibraryReply : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ZigbeeCluster;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZigbeeNetworkRequest request() const;
|
||||||
|
ZigbeeClusterLibrary::Frame requestFrame() const;
|
||||||
|
|
||||||
|
quint8 transactionSequenceNumber() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ZigbeeClusterLibraryReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame requestFrame, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
ZigbeeNetworkRequest m_request;
|
||||||
|
ZigbeeClusterLibrary::Frame m_requestFrame;
|
||||||
|
ZigbeeClusterLibrary::Command m_expectedResponse;
|
||||||
|
|
||||||
|
ZigbeeClusterLibrary::Frame m_responseFrame;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEECLUSTERLIBRARYREPLY_H
|
||||||
@ -29,9 +29,16 @@
|
|||||||
#include "zigbeenetwork.h"
|
#include "zigbeenetwork.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
|
#include <QSqlQuery>
|
||||||
|
|
||||||
ZigbeeNetwork::ZigbeeNetwork(QObject *parent) :
|
ZigbeeNetwork::ZigbeeNetwork(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
|
m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), "zigbee");
|
||||||
|
m_db.setDatabaseName("");
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Opening zigbee network database" << m_db.databaseName();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +174,16 @@ void ZigbeeNetwork::setPermitJoining(bool permitJoining)
|
|||||||
setPermitJoiningInternal(permitJoining);
|
setPermitJoiningInternal(permitJoining);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint8 ZigbeeNetwork::generateSequenceNumber()
|
||||||
|
{
|
||||||
|
return m_sequenceNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8 ZigbeeNetwork::generateTranactionSequenceNumber()
|
||||||
|
{
|
||||||
|
return m_transactionSequenceNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
QList<ZigbeeNode *> ZigbeeNetwork::nodes() const
|
QList<ZigbeeNode *> ZigbeeNetwork::nodes() const
|
||||||
{
|
{
|
||||||
return m_nodes;
|
return m_nodes;
|
||||||
@ -329,7 +346,7 @@ void ZigbeeNetwork::loadNetwork()
|
|||||||
for (int n = 0; n < inputClustersCount; n ++) {
|
for (int n = 0; n < inputClustersCount; n ++) {
|
||||||
settings.setArrayIndex(n);
|
settings.setArrayIndex(n);
|
||||||
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
||||||
ZigbeeCluster *cluster = new ZigbeeCluster(clusterId, ZigbeeCluster::Input, endpoint);
|
ZigbeeCluster *cluster = new ZigbeeCluster(this, node, endpoint, clusterId, ZigbeeCluster::Input, endpoint);
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
||||||
endpoint->m_inputClusters.insert(clusterId, cluster);
|
endpoint->m_inputClusters.insert(clusterId, cluster);
|
||||||
}
|
}
|
||||||
@ -339,7 +356,7 @@ void ZigbeeNetwork::loadNetwork()
|
|||||||
for (int n = 0; n < outputClustersCount; n ++) {
|
for (int n = 0; n < outputClustersCount; n ++) {
|
||||||
settings.setArrayIndex(n);
|
settings.setArrayIndex(n);
|
||||||
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(settings.value("clusterId", 0).toUInt());
|
||||||
ZigbeeCluster *cluster = new ZigbeeCluster(clusterId, ZigbeeCluster::Output, endpoint);
|
ZigbeeCluster *cluster = new ZigbeeCluster(this, node, endpoint, clusterId, ZigbeeCluster::Output, endpoint);
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
//qCDebug(dcZigbeeNetwork()) << "Created" << cluster;
|
||||||
endpoint->m_outputClusters.insert(clusterId, cluster);
|
endpoint->m_outputClusters.insert(clusterId, cluster);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
|
||||||
#include "zigbeenode.h"
|
#include "zigbeenode.h"
|
||||||
#include "zigbeechannelmask.h"
|
#include "zigbeechannelmask.h"
|
||||||
#include "zigbeebridgecontroller.h"
|
#include "zigbeebridgecontroller.h"
|
||||||
@ -94,6 +96,8 @@ public:
|
|||||||
bool permitJoining() const;
|
bool permitJoining() const;
|
||||||
void setPermitJoining(bool permitJoining);
|
void setPermitJoining(bool permitJoining);
|
||||||
|
|
||||||
|
quint8 generateSequenceNumber();
|
||||||
|
quint8 generateTranactionSequenceNumber();
|
||||||
|
|
||||||
// Network nodes
|
// Network nodes
|
||||||
QList<ZigbeeNode *> nodes() const;
|
QList<ZigbeeNode *> nodes() const;
|
||||||
@ -106,6 +110,8 @@ public:
|
|||||||
bool hasNode(quint16 shortAddress) const;
|
bool hasNode(quint16 shortAddress) const;
|
||||||
bool hasNode(const ZigbeeAddress &address) const;
|
bool hasNode(const ZigbeeAddress &address) const;
|
||||||
|
|
||||||
|
virtual ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
State m_state = StateUninitialized;
|
State m_state = StateUninitialized;
|
||||||
|
|
||||||
@ -113,6 +119,9 @@ private:
|
|||||||
QString m_serialPortName = "/dev/ttyUSB0";
|
QString m_serialPortName = "/dev/ttyUSB0";
|
||||||
qint32 m_serialBaudrate = 115200;
|
qint32 m_serialBaudrate = 115200;
|
||||||
|
|
||||||
|
quint8 m_sequenceNumber = 0;
|
||||||
|
quint8 m_transactionSequenceNumber = 0;
|
||||||
|
|
||||||
// Network configurations
|
// Network configurations
|
||||||
quint16 m_panId = 0;
|
quint16 m_panId = 0;
|
||||||
quint64 m_extendedPanId = 0;
|
quint64 m_extendedPanId = 0;
|
||||||
@ -120,10 +129,16 @@ private:
|
|||||||
ZigbeeChannelMask m_channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels);
|
ZigbeeChannelMask m_channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels);
|
||||||
ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator;
|
ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator;
|
||||||
|
|
||||||
|
// Network storage
|
||||||
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
|
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
|
||||||
QList<ZigbeeNode *> m_nodes;
|
QList<ZigbeeNode *> m_nodes;
|
||||||
QList<ZigbeeNode *> m_uninitializedNodes;
|
QList<ZigbeeNode *> m_uninitializedNodes;
|
||||||
|
|
||||||
|
QSqlDatabase m_db;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool initDB();
|
||||||
|
|
||||||
void addNodeInternally(ZigbeeNode *node);
|
void addNodeInternally(ZigbeeNode *node);
|
||||||
void removeNodeInternally(ZigbeeNode *node);
|
void removeNodeInternally(ZigbeeNode *node);
|
||||||
|
|
||||||
@ -152,8 +167,6 @@ protected:
|
|||||||
|
|
||||||
bool networkConfigurationAvailable() const;
|
bool networkConfigurationAvailable() const;
|
||||||
|
|
||||||
virtual ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) = 0;
|
|
||||||
|
|
||||||
// Network reply methods
|
// Network reply methods
|
||||||
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
||||||
void setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData);
|
void setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData);
|
||||||
|
|||||||
42
libnymea-zigbee/zigbeenetworkdatabase.cpp
Normal file
42
libnymea-zigbee/zigbeenetworkdatabase.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 "zigbeenetworkdatabase.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
|
ZigbeeNetworkDatabase::ZigbeeNetworkDatabase(const QString &databaseName, QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), "zigbee");
|
||||||
|
m_db.setDatabaseName(databaseName);
|
||||||
|
qCDebug(dcZigbeeNetworkDatabase()) << "Opening zigbee network database" << m_db.databaseName();
|
||||||
|
|
||||||
|
if (!m_db.isValid()) {
|
||||||
|
qCWarning(dcZigbeeNetworkDatabase()) << "The zigbee network database is not valid" << m_db.databaseName();
|
||||||
|
// FIXME: create a new one
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
49
libnymea-zigbee/zigbeenetworkdatabase.h
Normal file
49
libnymea-zigbee/zigbeenetworkdatabase.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 ZIGBEENETWORKDATABASE_H
|
||||||
|
#define ZIGBEENETWORKDATABASE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
|
||||||
|
|
||||||
|
class ZigbeeNetworkDatabase : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ZigbeeNetworkDatabase(const QString &databaseName, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSqlDatabase m_db;
|
||||||
|
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEENETWORKDATABASE_H
|
||||||
@ -26,7 +26,7 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "zigbeenetworkrequest.h"
|
#include "zigbeenetworkrequest.h"
|
||||||
#include "zigbeedeviceprofile.h"
|
#include "zdo/zigbeedeviceprofile.h"
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
|
||||||
ZigbeeNetworkRequest::ZigbeeNetworkRequest()
|
ZigbeeNetworkRequest::ZigbeeNetworkRequest()
|
||||||
|
|||||||
@ -27,14 +27,16 @@
|
|||||||
|
|
||||||
#include "zigbeenode.h"
|
#include "zigbeenode.h"
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
#include "zigbeenetwork.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
|
||||||
ZigbeeNode::ZigbeeNode(QObject *parent) :
|
ZigbeeNode::ZigbeeNode(ZigbeeNetwork *network, QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent),
|
||||||
|
m_network(network)
|
||||||
{
|
{
|
||||||
|
m_deviceObject = new ZigbeeDeviceObject(m_network, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeNode::State ZigbeeNode::state() const
|
ZigbeeNode::State ZigbeeNode::state() const
|
||||||
@ -47,6 +49,11 @@ bool ZigbeeNode::connected() const
|
|||||||
return m_connected;
|
return m_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeDeviceObject *ZigbeeNode::deviceObject() const
|
||||||
|
{
|
||||||
|
return m_deviceObject;
|
||||||
|
}
|
||||||
|
|
||||||
quint16 ZigbeeNode::shortAddress() const
|
quint16 ZigbeeNode::shortAddress() const
|
||||||
{
|
{
|
||||||
return m_shortAddress;
|
return m_shortAddress;
|
||||||
@ -248,95 +255,90 @@ void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &extendedAddress)
|
|||||||
m_extendedAddress = extendedAddress;
|
m_extendedAddress = extendedAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray ZigbeeNode::nodeDescriptorRawData() const
|
//void ZigbeeNode::setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData)
|
||||||
{
|
//{
|
||||||
return m_nodeDescriptorRawData;
|
// m_nodeDescriptorRawData = nodeDescriptorRawData;
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNode::setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData)
|
// // Parse the raw data
|
||||||
{
|
// quint8 sequenceNumber = 0;
|
||||||
m_nodeDescriptorRawData = nodeDescriptorRawData;
|
// quint8 status = 0;
|
||||||
|
// quint16 shortAddress = 0;
|
||||||
|
// quint16 manufacturerCode = 0;
|
||||||
|
// quint16 maximalRxSize = 0;
|
||||||
|
// quint16 maximalTxSize = 0;
|
||||||
|
// quint16 serverMask = 0;
|
||||||
|
// quint8 descriptorFlag = 0;
|
||||||
|
// quint8 macFlags = 0;
|
||||||
|
// quint8 maxBufferSize = 0;
|
||||||
|
// quint16 bitField = 0;
|
||||||
|
|
||||||
// Parse the raw data
|
// QDataStream stream(&m_nodeDescriptorRawData, QIODevice::ReadOnly);
|
||||||
quint8 sequenceNumber = 0;
|
// stream >> sequenceNumber;
|
||||||
quint8 status = 0;
|
// stream >> status;
|
||||||
quint16 shortAddress = 0;
|
// stream >> shortAddress;
|
||||||
quint16 manufacturerCode = 0;
|
// stream >> manufacturerCode;
|
||||||
quint16 maximalRxSize = 0;
|
// stream >> maximalRxSize;
|
||||||
quint16 maximalTxSize = 0;
|
// stream >> maximalTxSize;
|
||||||
quint16 serverMask = 0;
|
// stream >> serverMask;
|
||||||
quint8 descriptorFlag = 0;
|
// stream >> descriptorFlag;
|
||||||
quint8 macFlags = 0;
|
// stream >> macFlags;
|
||||||
quint8 maxBufferSize = 0;
|
// stream >> maxBufferSize;
|
||||||
quint16 bitField = 0;
|
// stream >> bitField;
|
||||||
|
|
||||||
QDataStream stream(&m_nodeDescriptorRawData, QIODevice::ReadOnly);
|
// // Set node data
|
||||||
stream >> sequenceNumber;
|
// m_manufacturerCode = manufacturerCode;
|
||||||
stream >> status;
|
// m_maximumRxSize = maximalRxSize;
|
||||||
stream >> shortAddress;
|
// m_maximumTxSize = maximalTxSize;
|
||||||
stream >> manufacturerCode;
|
// m_maximumBufferSize = maxBufferSize;
|
||||||
stream >> maximalRxSize;
|
|
||||||
stream >> maximalTxSize;
|
|
||||||
stream >> serverMask;
|
|
||||||
stream >> descriptorFlag;
|
|
||||||
stream >> macFlags;
|
|
||||||
stream >> maxBufferSize;
|
|
||||||
stream >> bitField;
|
|
||||||
|
|
||||||
// Set node data
|
// setServerMask(serverMask);
|
||||||
m_manufacturerCode = manufacturerCode;
|
// setMacCapabilitiesFlag(macFlags);
|
||||||
m_maximumRxSize = maximalRxSize;
|
// setDescriptorFlag(descriptorFlag);
|
||||||
m_maximumTxSize = maximalTxSize;
|
|
||||||
m_maximumBufferSize = maxBufferSize;
|
|
||||||
|
|
||||||
setServerMask(serverMask);
|
// // Parse bit field
|
||||||
setMacCapabilitiesFlag(macFlags);
|
// // 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
|
||||||
setDescriptorFlag(descriptorFlag);
|
// if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
|
// m_nodeType = NodeTypeCoordinator;
|
||||||
|
// } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
|
// m_nodeType = NodeTypeRouter;
|
||||||
|
// } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||||
|
// m_nodeType = NodeTypeEndDevice;
|
||||||
|
// }
|
||||||
|
|
||||||
// Parse bit field
|
// m_complexDescriptorAvailable = (bitField >> 3) & 0x0001;
|
||||||
// 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
|
// m_userDescriptorAvailable = (bitField >> 4) & 0x0001;
|
||||||
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
|
||||||
m_nodeType = NodeTypeCoordinator;
|
|
||||||
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
|
||||||
m_nodeType = NodeTypeRouter;
|
|
||||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
|
||||||
m_nodeType = NodeTypeEndDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_complexDescriptorAvailable = (bitField >> 3) & 0x0001;
|
// qCDebug(dcZigbeeNode()) << "Node descriptor:";
|
||||||
m_userDescriptorAvailable = (bitField >> 4) & 0x0001;
|
// qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||||
|
// qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
||||||
qCDebug(dcZigbeeNode()) << "Node descriptor:";
|
// qCDebug(dcZigbeeNode()) << " Node type:" << nodeType();
|
||||||
qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
// qCDebug(dcZigbeeNode()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||||
qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
// qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
||||||
qCDebug(dcZigbeeNode()) << " Node type:" << nodeType();
|
// qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximumRxSize());
|
||||||
qCDebug(dcZigbeeNode()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
// qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximumTxSize());
|
||||||
qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
// qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maximumBufferSize());
|
||||||
qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximumRxSize());
|
// qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
|
||||||
qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximumTxSize());
|
// qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter();
|
||||||
qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maximumBufferSize());
|
// qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter();
|
||||||
qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
|
// qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache();
|
||||||
qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter();
|
// qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache();
|
||||||
qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter();
|
// qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache();
|
||||||
qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache();
|
// qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache();
|
||||||
qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache();
|
// qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager();
|
||||||
qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache();
|
// qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
|
||||||
qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache();
|
// qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable();
|
||||||
qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager();
|
// qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable();
|
||||||
qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
|
// qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
|
||||||
qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable();
|
// qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator();
|
||||||
qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable();
|
// qCDebug(dcZigbeeNode()) << " Device type:" << deviceType();
|
||||||
qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
|
// qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower();
|
||||||
qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator();
|
// qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle();
|
||||||
qCDebug(dcZigbeeNode()) << " Device type:" << deviceType();
|
// qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability();
|
||||||
qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower();
|
// qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress();
|
||||||
qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle();
|
// qCDebug(dcZigbeeNode()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
|
||||||
qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability();
|
// qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable();
|
||||||
qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress();
|
// qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable();
|
||||||
qCDebug(dcZigbeeNode()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
|
//}
|
||||||
qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable();
|
|
||||||
qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
quint16 ZigbeeNode::serverMask() const
|
quint16 ZigbeeNode::serverMask() const
|
||||||
{
|
{
|
||||||
@ -448,14 +450,14 @@ void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
|
|||||||
m_powerLevel = PowerLevelFull;
|
m_powerLevel = PowerLevelFull;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):";
|
// qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):";
|
||||||
qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode;
|
// qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode;
|
||||||
qCDebug(dcZigbeeNode()) << " Available power sources:";
|
// qCDebug(dcZigbeeNode()) << " Available power sources:";
|
||||||
foreach (const PowerSource &source, m_availablePowerSources) {
|
// foreach (const PowerSource &source, m_availablePowerSources) {
|
||||||
qCDebug(dcZigbeeNode()) << " " << source;
|
// qCDebug(dcZigbeeNode()) << " " << source;
|
||||||
}
|
// }
|
||||||
qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource;
|
// qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource;
|
||||||
qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel;
|
// qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNode::startInitialization()
|
void ZigbeeNode::startInitialization()
|
||||||
|
|||||||
@ -33,6 +33,9 @@
|
|||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
#include "zigbeeaddress.h"
|
#include "zigbeeaddress.h"
|
||||||
#include "zigbeenodeendpoint.h"
|
#include "zigbeenodeendpoint.h"
|
||||||
|
#include "zdo/zigbeedeviceobject.h"
|
||||||
|
|
||||||
|
class ZigbeeNetwork;
|
||||||
|
|
||||||
class ZigbeeNode : public QObject
|
class ZigbeeNode : public QObject
|
||||||
{
|
{
|
||||||
@ -100,6 +103,8 @@ public:
|
|||||||
State state() const;
|
State state() const;
|
||||||
bool connected() const;
|
bool connected() const;
|
||||||
|
|
||||||
|
ZigbeeDeviceObject *deviceObject() const;
|
||||||
|
|
||||||
quint16 shortAddress() const;
|
quint16 shortAddress() const;
|
||||||
ZigbeeAddress extendedAddress() const;
|
ZigbeeAddress extendedAddress() const;
|
||||||
|
|
||||||
@ -190,8 +195,10 @@ private:
|
|||||||
virtual void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) = 0;
|
virtual void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ZigbeeNode(QObject *parent = nullptr);
|
ZigbeeNode(ZigbeeNetwork *network, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
ZigbeeNetwork *m_network;
|
||||||
|
ZigbeeDeviceObject *m_deviceObject = nullptr;
|
||||||
QList<ZigbeeNodeEndpoint *> m_endpoints;
|
QList<ZigbeeNodeEndpoint *> m_endpoints;
|
||||||
|
|
||||||
// Node descriptor information
|
// Node descriptor information
|
||||||
@ -214,10 +221,6 @@ protected:
|
|||||||
void setShortAddress(const quint16 &shortAddress);
|
void setShortAddress(const quint16 &shortAddress);
|
||||||
void setExtendedAddress(const ZigbeeAddress &extendedAddress);
|
void setExtendedAddress(const ZigbeeAddress &extendedAddress);
|
||||||
|
|
||||||
// Note: node descriptor properties (raw data for settings)
|
|
||||||
QByteArray nodeDescriptorRawData() const;
|
|
||||||
void setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData);
|
|
||||||
|
|
||||||
quint16 serverMask() const;
|
quint16 serverMask() const;
|
||||||
void setServerMask(quint16 serverMask);
|
void setServerMask(quint16 serverMask);
|
||||||
|
|
||||||
|
|||||||
@ -73,36 +73,6 @@ public:
|
|||||||
ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const;
|
ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
|
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
|
||||||
|
|
||||||
// Attribute methods
|
|
||||||
virtual ZigbeeNetworkReply *readAttribute(ZigbeeCluster *cluster, QList<quint16> attributes) = 0;
|
|
||||||
virtual ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations) = 0;
|
|
||||||
|
|
||||||
// Identify
|
|
||||||
virtual ZigbeeNetworkReply *identify(quint16 seconds);
|
|
||||||
|
|
||||||
// Reset
|
|
||||||
virtual ZigbeeNetworkReply *factoryReset();
|
|
||||||
|
|
||||||
// Binding
|
|
||||||
virtual ZigbeeNetworkReply *bindGroup(Zigbee::ClusterId clusterId, quint16 destinationAddress, quint8 destinationEndpoint);
|
|
||||||
virtual ZigbeeNetworkReply *bindUnicast(Zigbee::ClusterId clusterId, const ZigbeeAddress &destinationAddress, quint8 destinationEndpoint);
|
|
||||||
|
|
||||||
// Cluster commands
|
|
||||||
virtual ZigbeeNetworkReply *sendOnOffClusterCommand(ZigbeeCluster::OnOffClusterCommand command);
|
|
||||||
|
|
||||||
// Group commands
|
|
||||||
virtual ZigbeeNetworkReply *addGroup(quint8 destinationEndpoint, quint16 groupAddress);
|
|
||||||
|
|
||||||
// Level commands
|
|
||||||
virtual ZigbeeNetworkReply *sendLevelCommand(ZigbeeCluster::LevelClusterCommand command, quint8 level, bool triggersOnOff, quint16 transitionTime);
|
|
||||||
|
|
||||||
// Color commands
|
|
||||||
virtual ZigbeeNetworkReply *sendMoveToColorTemperature(quint16 colourTemperature, quint16 transitionTime);
|
|
||||||
virtual ZigbeeNetworkReply *sendMoveToColor(double x, double y, quint16 transitionTime);
|
|
||||||
virtual ZigbeeNetworkReply *sendMoveToHueSaturation(quint8 hue, quint8 saturation, quint16 transitionTime);
|
|
||||||
virtual ZigbeeNetworkReply *sendMoveToHue(quint8 hue, quint16 transitionTime);
|
|
||||||
virtual ZigbeeNetworkReply *sendMoveToSaturation(quint8 saturation, quint16 transitionTime);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZigbeeNode *m_node = nullptr;
|
ZigbeeNode *m_node = nullptr;
|
||||||
quint8 m_endpointId = 0;
|
quint8 m_endpointId = 0;
|
||||||
@ -139,6 +109,7 @@ signals:
|
|||||||
void manufacturerNameChanged(const QString &manufacturerName);
|
void manufacturerNameChanged(const QString &manufacturerName);
|
||||||
void modelIdentifierChanged(const QString &modelIdentifier);
|
void modelIdentifierChanged(const QString &modelIdentifier);
|
||||||
void softwareBuildIdChanged(const QString &softwareBuildId);
|
void softwareBuildIdChanged(const QString &softwareBuildId);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeNodeEndpoint *endpoint);
|
QDebug operator<<(QDebug debug, ZigbeeNodeEndpoint *endpoint);
|
||||||
|
|||||||
Reference in New Issue
Block a user