Start implementing clusters

This commit is contained in:
Simon Stürz 2020-05-06 12:33:26 +02:00
parent 3e8da8ee26
commit 7cdf772b1a
36 changed files with 627 additions and 215 deletions

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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;
} }

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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;

View File

@ -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)}

View File

@ -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")

View File

@ -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

View 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)
{
}

View 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

View File

@ -0,0 +1,9 @@
#include "zigbeedeviceobject.h"
#include "zigbeenetwork.h"
ZigbeeDeviceObject::ZigbeeDeviceObject(ZigbeeNetwork *network, QObject *parent) :
QObject(parent),
m_network(network)
{
}

View 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

View File

@ -0,0 +1,6 @@
#include "zigbeedeviceobjectreply.h"
ZigbeeDeviceObjectReply::ZigbeeDeviceObjectReply(QObject *parent) : QObject(parent)
{
}

View 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

View File

@ -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 */

View File

@ -0,0 +1,6 @@
#include "zigbeedeviceprofilehandler.h"
ZigbeeDeviceProfileHandler::ZigbeeDeviceProfileHandler(QObject *parent) : QObject(parent)
{
}

View 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

View File

@ -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("

View File

@ -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);

View File

@ -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();

View File

@ -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);
}; };

View 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)
{
}

View 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

View File

@ -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);
} }

View File

@ -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);

View 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;
}
}

View 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

View File

@ -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()

View File

@ -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()

View File

@ -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);

View File

@ -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);