From 73956951736a40ad9db6c9526830015918b6da61 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 27 Mar 2023 00:40:25 +0200 Subject: [PATCH] Add window covering cluster --- libnymea-zigbee/libnymea-zigbee.pro | 2 + .../closures/zigbeeclusterwindowcovering.cpp | 119 ++++++++++++++ .../closures/zigbeeclusterwindowcovering.h | 147 ++++++++++++++++++ libnymea-zigbee/zcl/zigbeeclusterlibrary.h | 3 +- libnymea-zigbee/zigbeenodeendpoint.cpp | 3 + 5 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.cpp create mode 100644 libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.h diff --git a/libnymea-zigbee/libnymea-zigbee.pro b/libnymea-zigbee/libnymea-zigbee.pro index 5bdaf9f..0ee1210 100644 --- a/libnymea-zigbee/libnymea-zigbee.pro +++ b/libnymea-zigbee/libnymea-zigbee.pro @@ -29,6 +29,7 @@ SOURCES += \ backends/ti/zigbeebridgecontrollerti.cpp \ backends/ti/zigbeenetworkti.cpp \ zcl/closures/zigbeeclusterdoorlock.cpp \ + zcl/closures/zigbeeclusterwindowcovering.cpp \ zcl/general/zigbeeclusteranaloginput.cpp \ zcl/general/zigbeeclusteranalogoutput.cpp \ zcl/general/zigbeeclusteranalogvalue.cpp \ @@ -107,6 +108,7 @@ HEADERS += \ backends/ti/zigbeebridgecontrollerti.h \ backends/ti/zigbeenetworkti.h \ zcl/closures/zigbeeclusterdoorlock.h \ + zcl/closures/zigbeeclusterwindowcovering.h \ zcl/general/zigbeeclusteranaloginput.h \ zcl/general/zigbeeclusteranalogoutput.h \ zcl/general/zigbeeclusteranalogvalue.h \ diff --git a/libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.cpp b/libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.cpp new file mode 100644 index 0000000..99c1877 --- /dev/null +++ b/libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.cpp @@ -0,0 +1,119 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2023, 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 . +* +* 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 "zigbeeclusterwindowcovering.h" +#include "zigbeenetworkreply.h" +#include "loggingcategory.h" +#include "zigbeenetwork.h" +#include "zigbeeutils.h" + +#include + +ZigbeeClusterWindowCovering::ZigbeeClusterWindowCovering(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) : + ZigbeeCluster(network, node, endpoint, ZigbeeClusterLibrary::ClusterIdWindowCovering, direction, parent) +{ + +} + +ZigbeeClusterReply *ZigbeeClusterWindowCovering::open() +{ + return executeClusterCommand(Command::CommandOpen); +} + +ZigbeeClusterReply *ZigbeeClusterWindowCovering::close() +{ + return executeClusterCommand(Command::CommandClose); +} + +ZigbeeClusterReply *ZigbeeClusterWindowCovering::stop() +{ + return executeClusterCommand(Command::CommandStop); +} + +ZigbeeClusterReply *ZigbeeClusterWindowCovering::goToLiftValue(quint16 liftValue) +{ + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << liftValue; + return executeClusterCommand(Command::CommandGoToLiftValue, payload); +} + +ZigbeeClusterReply *ZigbeeClusterWindowCovering::goToLiftPercentage(quint8 liftPercentage) +{ + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << liftPercentage; + return executeClusterCommand(Command::CommandGoToLiftPercentage, payload); +} + +ZigbeeClusterReply *ZigbeeClusterWindowCovering::goToTiltValue(quint16 tiltValue) +{ + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << tiltValue; + return executeClusterCommand(Command::CommandGoToTiltValue, payload); +} + +ZigbeeClusterReply *ZigbeeClusterWindowCovering::goToTiltPercentage(quint8 tiltPercentage) +{ + QByteArray payload; + QDataStream stream(&payload, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << tiltPercentage; + return executeClusterCommand(Command::CommandGoToTiltPercentage, payload); +} + +quint8 ZigbeeClusterWindowCovering::currentLiftPercentage() const +{ + return m_currentLiftPercentage; +} + +quint8 ZigbeeClusterWindowCovering::currentTiltPercentage() const +{ + return m_currentTiltPercentage; +} + +void ZigbeeClusterWindowCovering::setAttribute(const ZigbeeClusterAttribute &attribute) +{ + ZigbeeCluster::setAttribute(attribute); + + switch (attribute.id()) { + case AttributeCurrentPositionLiftPercentage: + m_currentLiftPercentage = static_cast(attribute.dataType().toUInt8()); + emit currentLiftPercentageChanged(m_currentLiftPercentage); + break; + case AttributeCurrentPositionTiltPercentage: + m_currentTiltPercentage = static_cast(attribute.dataType().toUInt8()); + emit currentTiltPercentageChanged(m_currentTiltPercentage); + break; + default: + qCDebug(dcZigbeeCluster()) << "Unhandled WindowCovering cluster attribute change:" << static_cast(attribute.id()); + } +} diff --git a/libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.h b/libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.h new file mode 100644 index 0000000..8140428 --- /dev/null +++ b/libnymea-zigbee/zcl/closures/zigbeeclusterwindowcovering.h @@ -0,0 +1,147 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2023, 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 . +* +* 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 ZIGBEECLUSTERWINDOWCOVERING_H +#define ZIGBEECLUSTERWINDOWCOVERING_H + +#include +#include "zcl/zigbeecluster.h" +#include "zcl/zigbeeclusterreply.h" + +class ZigbeeNode; +class ZigbeeNetwork; +class ZigbeeNodeEndpoint; +class ZigbeeNetworkReply; + +class ZigbeeClusterWindowCovering : public ZigbeeCluster +{ + Q_OBJECT + + friend class ZigbeeNode; + friend class ZigbeeNetwork; + +public: + enum Attribute { + // Window covering information + AttributeWindowCoveringType = 0x0000, + AttributeLockPhysicalClosedLimitLift = 0x0001, + AttributePhysicalClosedLimitTilt = 0x0002, + AttributeCurrentPositionLift = 0x0003, + AttributeCurrentPositionTilt = 0x0004, + AttributeNumberOfActuationsLift = 0x0005, + AttributeNumberOfActuationsTilt = 0x0006, + AttributeConfigStatus = 0x0007, + AttributeCurrentPositionLiftPercentage = 0x0008, + AttributeCurrentPositionTiltPercentage = 0x0009, + + // Window covering settings + AttributeInstalledOpenLimitLift = 0x0100, + AttributeInstalledClosedLimitLift = 0x0101, + AttributeInstalledOpenLimitTilt = 0x0102, + AttributeInstalledClosedLimitTilt = 0x0103, + AttributeVelocityLift = 0x0104, + AttributeAccelerationTileLift = 0x0105, + AttributeDecelerationTimeLift = 0x0106, + AttributeMode = 0x0107, + AttributeIntermediateSetpointsLift = 0x0108, + AttributeIntermediateSetpointsTilt = 0x0109 + }; + Q_ENUM(Attribute) + + enum WindowCoveringType { + WindowCoveringTypeRollerShade = 0x00, + WindowCoveringTypeRollerShade2Motor = 0x01, + WindowCoveringTypeRollerShadeExterior = 0x02, + WindowCoveringTypeRollerShadeExterior2Motor = 0x03, + WindowCoveringTypeDrapery = 0x04, + WindowCoveringTypeAwning = 0x05, + WindowCoveringTypeShutter = 0x06, + WindowCoveringTypeTiltBlindTiltOnly = 0x07, + WindowCoveringTypeTiltBlindLiftAndTilt = 0x08, + WindowCoveringTypeProjectorScreen = 0x09 + }; + Q_ENUM(WindowCoveringType) + + enum ConfigStatusFlag { + ConfigStatusFlagOperational = 0x01, + ConfigStatusFlagOnline = 0x02, + ConfigStatusFlagReversed = 0x04, + ConfigStatusFlagLiftControlClosedLoop = 0x08, + ConfigStatusFlagTiltControlClosedLoop = 0x10, + ConfigStatusFlagLiftEncoderControlled = 0x20, + ConfigStatusFlagTiltEncoderControlled = 0x40 + }; + Q_ENUM(ConfigStatusFlag) + Q_DECLARE_FLAGS(ConfigStatus, ConfigStatusFlag) + Q_FLAG(ConfigStatus) + + enum ModeFlag { + ModeFlagReversed = 0x01, + ModeFlagCalibration = 0x02, + ModeFlagMaintenance = 0x04, + ModeFlagLEDsOn = 0x08 + }; + Q_ENUM(ModeFlag) + Q_DECLARE_FLAGS(Mode, ModeFlag) + Q_FLAG(Mode) + + enum Command { + CommandOpen = 0x00, // M + CommandClose = 0x01, // M + CommandStop = 0x02, // M + CommandGoToLiftValue = 0x04, + CommandGoToLiftPercentage = 0x05, + CommandGoToTiltValue = 0x07, + CommandGoToTiltPercentage = 0x08 + }; + Q_ENUM(Command) + + explicit ZigbeeClusterWindowCovering(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr); + + ZigbeeClusterReply *open(); + ZigbeeClusterReply *close(); + ZigbeeClusterReply *stop(); + ZigbeeClusterReply *goToLiftValue(quint16 liftValue); + ZigbeeClusterReply *goToLiftPercentage(quint8 liftPercentage); + ZigbeeClusterReply *goToTiltValue(quint16 tiltValue); + ZigbeeClusterReply *goToTiltPercentage(quint8 tiltPercentage); + + quint8 currentLiftPercentage() const; + quint8 currentTiltPercentage() const; + +private: + quint8 m_currentLiftPercentage = 0; + quint8 m_currentTiltPercentage = 0; + + void setAttribute(const ZigbeeClusterAttribute &attribute) override; + +signals: + void currentLiftPercentageChanged(quint8 liftPercentage); + void currentTiltPercentageChanged(quint8 tiltPercentage); +}; + +#endif // ZIGBEECLUSTERWINDOWCOVERING_H diff --git a/libnymea-zigbee/zcl/zigbeeclusterlibrary.h b/libnymea-zigbee/zcl/zigbeeclusterlibrary.h index 9d80074..0085f92 100644 --- a/libnymea-zigbee/zcl/zigbeeclusterlibrary.h +++ b/libnymea-zigbee/zcl/zigbeeclusterlibrary.h @@ -140,9 +140,8 @@ public: // Closures ClusterIdShadeConfiguration = 0x0100, - - // Door Lock ClusterIdDoorLock = 0x0101, + ClusterIdWindowCovering = 0x0102, // Heating, Ventilation and Air-Conditioning (HVAC) ClusterIdPumpConfigurationControl = 0x0200, diff --git a/libnymea-zigbee/zigbeenodeendpoint.cpp b/libnymea-zigbee/zigbeenodeendpoint.cpp index 5808013..c087406 100644 --- a/libnymea-zigbee/zigbeenodeendpoint.cpp +++ b/libnymea-zigbee/zigbeenodeendpoint.cpp @@ -49,6 +49,7 @@ #include "zcl/general/zigbeeclustermultistatevalue.h" #include "zcl/closures/zigbeeclusterdoorlock.h" +#include "zcl/closures/zigbeeclusterwindowcovering.h" #include "zcl/measurement/zigbeeclusteroccupancysensing.h" #include "zcl/measurement/zigbeeclusterilluminancemeasurement.h" @@ -258,6 +259,8 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(ZigbeeClusterLibrary::ClusterId // Colsures case ZigbeeClusterLibrary::ClusterIdDoorLock: return new ZigbeeClusterDoorLock(m_network, m_node, this, direction, this); + case ZigbeeClusterLibrary::ClusterIdWindowCovering: + return new ZigbeeClusterWindowCovering(m_network, m_node, this, direction, this); // Lighting case ZigbeeClusterLibrary::ClusterIdColorControl: