Implement color control cluster and improve uart communication

pull/7/head
Simon Stürz 2020-06-05 18:58:11 +02:00
parent b3f5a13548
commit 275e4c8b97
13 changed files with 549 additions and 72 deletions

View File

@ -224,9 +224,9 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestQuerySendDataCo
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(const ZigbeeNetworkRequest &request)
{
// Send the request only if there are free slots on the device, otherwise enque request
// if (m_apsFreeSlotsAvailable) {
// if (m_apsFreeSlotsAvailable) {
// }
// }
qCDebug(dcZigbeeAps()) << "APSDE-DATA.request" << request;
ZigbeeInterfaceDeconzReply *interfaceReply = nullptr;
@ -253,14 +253,14 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(con
quint8 ZigbeeBridgeControllerDeconz::generateSequenceNumber()
{
return m_sequenceNumber++;
m_sequenceNumber += 3;
return m_sequenceNumber;
}
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent)
{
// Create the reply
ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(command, sequenceNumber, parent);
connect(reply, &ZigbeeInterfaceDeconzReply::timeout, this, [this, reply](){
qCWarning(dcZigbeeController()) << "Reply timeout" << reply->command() << "SQN:" << reply->sequenceNumber();
if (m_pendingReplies.contains(reply->sequenceNumber())) {
@ -414,7 +414,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
// If read request failes, this mehtod returns the status code of the failed request.
// Create an independent reply for finishing the entire read sequence
ZigbeeInterfaceDeconzReply *readNetworkParametersReply = new ZigbeeInterfaceDeconzReply(Deconz::CommandReadParameter, m_sequenceNumber, this);
ZigbeeInterfaceDeconzReply *readNetworkParametersReply = new ZigbeeInterfaceDeconzReply(Deconz::CommandReadParameter, generateSequenceNumber(), this);
connect(readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::finished, readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::deleteLater, Qt::QueuedConnection);
// Read MAC address of the bridge
@ -934,22 +934,28 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &
<< status << "Frame length:" << frameLength << ZigbeeUtils::convertByteArrayToHexString(data);
// Check if this is an interface response for a pending reply
if (m_pendingReplies.contains(sequenceNumber) && m_pendingReplies.value(sequenceNumber)->command() == command) {
ZigbeeInterfaceDeconzReply *reply = m_pendingReplies.take(sequenceNumber);
if (!reply) {
qCWarning(dcZigbeeController()) << "Received message but the corresponding reply does not exist any more.";
if (m_pendingReplies.contains(sequenceNumber)) {
if (m_pendingReplies.value(sequenceNumber)->command() == command) {
// SQN and command maches
ZigbeeInterfaceDeconzReply *reply = m_pendingReplies.take(sequenceNumber);
if (!reply) {
qCWarning(dcZigbeeController()) << "Received message but the corresponding reply does not exist any more.";
return;
}
reply->m_responseData = data;
reply->m_statusCode = status;
reply->finished();
return;
} else {
qCWarning(dcZigbeeController()) << "Received message with a pending request SQN but the command does not match. SQN mismatch.";
qCWarning(dcZigbeeController()) << "The SQN matches" << m_pendingReplies.value(sequenceNumber)->command() << "but command" << command << "received for SQN" << sequenceNumber;
}
reply->m_responseData = data;
reply->m_statusCode = status;
reply->finished();
return;
}
// Note: we got a notification, lets set the current sequence number to the notification id,
// so the next request will be a continuouse increase
m_sequenceNumber = sequenceNumber + 1;
//m_sequenceNumber = sequenceNumber + 10;
// No request for this data, lets check which notification and process the data
switch (command) {

View File

@ -110,6 +110,8 @@ private:
Deconz::NetworkState m_networkState = Deconz::NetworkStateOffline;
QTimer *m_watchdogTimer = nullptr;
// Interface queue, send all requests sequentially and always wait for the interface response
// APS request queue
bool m_apsFreeSlotsAvailable = false;
QQueue<ZigbeeNetworkRequest> m_requestQueue;
@ -120,6 +122,7 @@ private:
ZigbeeInterfaceDeconzReply *createReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent);
// Send data depending on the request destination address mode
QByteArray buildRequestEnqueueSendDataGroupMessage(quint8 requestId, quint16 groupAddress, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);

View File

@ -284,6 +284,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
case CreateNetworkStateInitializeCoordinatorNode: {
if (m_coordinatorNode) {
qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done.";
m_database->saveNode(m_coordinatorNode);
m_initializing = false;
setState(StateRunning);
setPermitJoiningInternal(false);
@ -417,7 +418,7 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
m_createNewNetwork = false;
// Check if we have to create a pan ID and select the channel
if (panId() == 0) {
if (panId() == 0 || !m_coordinatorNode) {
m_createNewNetwork = true;
}
@ -497,8 +498,25 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
if (m_controller->networkState() == Deconz::NetworkStateConnected) {
qCDebug(dcZigbeeNetwork()) << "The network is already running.";
m_initializing = false;
setState(StateRunning);
setPermitJoiningInternal(false);
setPermitJoining(false);
// Set the permit joining timeout network configuration parameter
QByteArray parameterData;
QDataStream stream(&parameterData, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(0);
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterPermitJoin, parameterData);
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Request" << reply->command() << "finished with error" << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Set permit join configuration request finished" << reply->statusCode();
setState(StateRunning);
});
} else if (m_controller->networkState() == Deconz::NetworkStateOffline) {
m_initializing = true;
qCDebug(dcZigbeeNetwork()) << "The network is offline. Lets start it";

View File

@ -11,6 +11,7 @@ SOURCES += \
zcl/general/zigbeeclusteridentify.cpp \
zcl/general/zigbeeclusterlevelcontrol.cpp \
zcl/general/zigbeeclusteronoff.cpp \
zcl/lighting/zigbeeclustercolorcontrol.cpp \
zcl/measurement/zigbeeclusterilluminancemeasurment.cpp \
zcl/measurement/zigbeeclusteroccupancysensing.cpp \
zcl/measurement/zigbeeclusterrelativehumiditymeasurement.cpp \
@ -60,6 +61,7 @@ HEADERS += \
zcl/general/zigbeeclusteridentify.h \
zcl/general/zigbeeclusterlevelcontrol.h \
zcl/general/zigbeeclusteronoff.h \
zcl/lighting/zigbeeclustercolorcontrol.h \
zcl/measurement/zigbeeclusterilluminancemeasurment.h \
zcl/measurement/zigbeeclusteroccupancysensing.h \
zcl/measurement/zigbeeclusterrelativehumiditymeasurement.h \

View File

@ -38,12 +38,12 @@ ZigbeeClusterLevelControl::ZigbeeClusterLevelControl(ZigbeeNetwork *network, Zig
}
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveToLevel(quint8 level, quint16 transistionTime)
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveToLevel(quint8 level, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << level << transistionTime;
stream << level << transitionTime;
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMoveToLevel, payload);
}
@ -56,12 +56,12 @@ ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMove(ZigbeeClusterLevelCon
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMove, payload);
}
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStep(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transistionTime)
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStep(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(fadeMode) << stepSize << transistionTime;
stream << static_cast<quint8>(fadeMode) << stepSize << transitionTime;
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStep, payload);
}
@ -70,12 +70,12 @@ ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStop()
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStop);
}
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveToLevelWithOnOff(quint8 level, quint16 transistionTime)
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveToLevelWithOnOff(quint8 level, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << level << transistionTime;
stream << level << transitionTime;
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMoveToLevelWithOnOff, payload);
}
@ -88,12 +88,12 @@ ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveWithOnOff(ZigbeeCluste
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMoveWithOnOff, payload);
}
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStepWithOnOff(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transistionTime)
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStepWithOnOff(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(fadeMode) << stepSize << transistionTime;
stream << static_cast<quint8>(fadeMode) << stepSize << transitionTime;
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStepWithOnOff, payload);
}

View File

@ -83,15 +83,15 @@ public:
explicit ZigbeeClusterLevelControl(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
ZigbeeClusterReply *commandMoveToLevel(quint8 level, quint16 transistionTime = 0xffff);
ZigbeeClusterReply *commandMoveToLevel(quint8 level, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandMove(MoveMode moveMode, quint8 rate = 0xff);
ZigbeeClusterReply *commandStep(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transistionTime = 0xffff);
ZigbeeClusterReply *commandStep(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandStop();
// With on/off
ZigbeeClusterReply *commandMoveToLevelWithOnOff(quint8 level, quint16 transistionTime = 0xffff);
ZigbeeClusterReply *commandMoveToLevelWithOnOff(quint8 level, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandMoveWithOnOff(MoveMode moveMode, quint8 rate = 0xff);
ZigbeeClusterReply *commandStepWithOnOff(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transistionTime = 0xffff);
ZigbeeClusterReply *commandStepWithOnOff(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandStopWithOnOff();
private:

View File

@ -0,0 +1,233 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 "zigbeeclustercolorcontrol.h"
#include "zigbeenetworkreply.h"
#include "loggingcategory.h"
#include "zigbeenetwork.h"
#include <QDataStream>
ZigbeeClusterColorControl::ZigbeeClusterColorControl(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, ZigbeeCluster::Direction direction, QObject *parent) :
ZigbeeCluster(network, node, endpoint, Zigbee::ClusterIdColorControl, direction, parent)
{
}
/*! Send the move to \a hue command with the given \a direction and \a transitionTime. The transition time has the unit 1/10 seconds. */
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveToHue(quint8 hue, ZigbeeClusterColorControl::MoveDirection direction, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << hue << static_cast<quint8>(direction) << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveToHue, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveHue(ZigbeeClusterColorControl::MoveMode moveMode, quint8 rate)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(moveMode) << rate;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveHue, payload);
}
/*! Send the step hue command with the given \a stepMode, \a stepSize and \a transitionTime. The transition time has the unit 1/10 seconds. */
ZigbeeClusterReply *ZigbeeClusterColorControl::commandStepHue(ZigbeeClusterColorControl::StepMode stepMode, quint8 stepSize, quint8 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(stepMode) << stepSize << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandStepHue, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveToSaturation(quint8 saturation, ZigbeeClusterColorControl::MoveDirection direction, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << saturation << static_cast<quint8>(direction) << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveToSaturation, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveSaturation(ZigbeeClusterColorControl::MoveMode moveMode, quint8 rate)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(moveMode) << rate;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveSaturation, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandStepSaturation(ZigbeeClusterColorControl::StepMode stepMode, quint8 stepSize, quint8 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(stepMode) << stepSize << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandStepSaturation, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveToHueAndSaturation(quint8 hue, quint8 saturation, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << hue << saturation << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveToHueAndSaturation, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveToColor(quint16 colorX, quint16 colorY, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << colorX << colorY << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveToColor, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveColor(quint16 colorXRate, quint16 colorYRate)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << colorXRate << colorYRate;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveColor, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandStepColor(quint16 stepX, quint16 stepY, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << stepX << stepY << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandStepColor, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveToColorTemperature(quint16 colorTemperatureMireds, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << colorTemperatureMireds << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveToColorTemperature, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandEnhancedMoveToHue(quint16 enhancedHue, ZigbeeClusterColorControl::MoveDirection direction, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << enhancedHue << static_cast<quint8>(direction) << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandEnhancedMoveHue, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandEnhancedMoveHue(ZigbeeClusterColorControl::MoveMode moveMode, quint16 rate)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(moveMode) << rate;
return executeClusterCommand(ZigbeeClusterColorControl::CommandEnhancedMoveHue, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandEnhancedStepHue(ZigbeeClusterColorControl::StepMode stepMode, quint16 stepSize, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(stepMode) << stepSize << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandEnhancedStepHue, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandEnhancedMoveToHueAndSaturation(quint16 enhancedHue, quint8 saturation, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << enhancedHue << saturation << transitionTime;
return executeClusterCommand(ZigbeeClusterColorControl::CommandEnhancedMoveToHueAndSaturation, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandColorLoopSet(ColorLoopUpdateFlags updateFlag, ZigbeeClusterColorControl::ColorLoopAction action, ZigbeeClusterColorControl::ColorLoopDirection direction, quint16 time, quint16 startHue)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(updateFlag);
stream << static_cast<quint8>(action);
stream << static_cast<quint8>(direction);
stream << time << startHue;
return executeClusterCommand(ZigbeeClusterColorControl::CommandColorLoopSet, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandStopMoveStep()
{
return executeClusterCommand(ZigbeeClusterColorControl::CommandStopMoveStep);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandMoveColorTemperature(ZigbeeClusterColorControl::MoveMode moveMode, quint16 rate, quint16 minColorTemperature, quint16 maxColorTemperature)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(moveMode) << rate << minColorTemperature << maxColorTemperature;
return executeClusterCommand(ZigbeeClusterColorControl::CommandMoveColorTemperature, payload);
}
ZigbeeClusterReply *ZigbeeClusterColorControl::commandStepColorTemperature(ZigbeeClusterColorControl::StepMode stepMode, quint16 stepSize, quint16 transitionTime, quint16 minColorTemperature, quint16 maxColorTemperature)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(stepMode) << stepSize << transitionTime << minColorTemperature << maxColorTemperature;
return executeClusterCommand(ZigbeeClusterColorControl::CommandStepColorTemperature, payload);
}
void ZigbeeClusterColorControl::setAttribute(const ZigbeeClusterAttribute &attribute)
{
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
if (hasAttribute(attribute.id())) {
m_attributes[attribute.id()] = attribute;
emit attributeChanged(attribute);
} else {
m_attributes.insert(attribute.id(), attribute);
emit attributeChanged(attribute);
}
}
void ZigbeeClusterColorControl::processDataIndication(ZigbeeClusterLibrary::Frame frame)
{
qCDebug(dcZigbeeCluster()) << "Processing cluster frame" << m_node << m_endpoint << this << frame;
// Increase the tsn for continuouse id increasing on both sides
m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
}

View File

@ -0,0 +1,246 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 ZIGBEECLUSTERCOLORCONTROL_H
#define ZIGBEECLUSTERCOLORCONTROL_H
#include <QObject>
#include "zcl/zigbeecluster.h"
#include "zcl/zigbeeclusterreply.h"
class ZigbeeNode;
class ZigbeeNetwork;
class ZigbeeNodeEndpoint;
class ZigbeeNetworkReply;
class ZigbeeClusterColorControl : public ZigbeeCluster
{
Q_OBJECT
friend class ZigbeeNode;
friend class ZigbeeNetwork;
public:
enum Attribute {
// Color information
AttributeCurrentHue = 0x0000,
AttributeCurrentSaturation = 0x0001,
AttributeRemainingTime = 0x0002,
AttributeCurrentX = 0x0003,
AttributeCurrentY = 0x0004,
AttributeDriftCompensation = 0x0005,
AttributeCompensationText = 0x0006,
AttributeColorTemperatureMireds = 0x0007,
AttributeColorMode = 0x0008,
AttributeEnhancedCurrentHue = 0x4000,
AttributeEnhancedColorMode = 0x4001,
AttributeColorLoopActive = 0x4002,
AttributeColorLoopDirection = 0x4003,
AttributeColorLoopTime = 0x4004,
AttributeColorLoopStartEnhancedHue = 0x4005,
AttributeColorLoopStoredEnhancedHue = 0x4006,
AttributeColorCapabilities = 0x400a,
AttributeColorTempPhysicalMinMireds = 0x400b,
AttributeColorTempPhysicalMaxMireds = 0x400c,
// Primaries information
AttributeNumberOfPrimaries = 0x0010,
AttributePrimary1X = 0x0011,
AttributePrimary1Y = 0x0012,
AttributePrimary1Intensity = 0x0013,
AttributePrimary2X = 0x0015,
AttributePrimary2Y = 0x0016,
AttributePrimary2Intensity = 0x0017,
AttributePrimary3X = 0x0019,
AttributePrimary3Y = 0x001a,
AttributePrimary3Intensity = 0x001b,
// Additional primaries information
AttributePrimary4X = 0x0020,
AttributePrimary4Y = 0x0021,
AttributePrimary4Intensity = 0x0022,
AttributePrimary5X = 0x0024,
AttributePrimary5Y = 0x0025,
AttributePrimary5Intensity = 0x0026,
AttributePrimary6X = 0x0028,
AttributePrimary6Y = 0x0029,
AttributePrimary6Intensity = 0x002a,
// Defined color points settings
AttributeWhitePointX = 0x0030,
AttributeWhitePointY = 0x0031,
AttributeColorPointRX = 0x0032,
AttributeColorPointRY = 0x0033,
AttributeColorPointRIntensity = 0x0034,
AttributeColorPointGX = 0x0036,
AttributeColorPointGY = 0x0037,
AttributeColorPointGIntensity = 0x0038,
AttributeColorPointBX = 0x003a,
AttributeColorPointBY = 0x003b,
AttributeColorPointBIntensity = 0x003c
};
Q_ENUM(Attribute)
enum DriftCompensation {
DriftCompensationNone = 0x00,
DriftCompensationOther = 0x01,
DriftCompensationTemperatureMonitoring = 0x02,
DriftCompensationOpticalLuminanceMonitoring = 0x03,
DriftCompensationOpticalColorMonitoring = 0x04
};
Q_ENUM(DriftCompensation)
enum ColorMode {
ColorModeHueSaturation = 0x00,
ColorModeXY = 0x01,
ColorModeColorTemperatureMired = 0x02
};
Q_ENUM(ColorMode)
enum EnhancedColorMode {
EnhancedColorModeCurrentHueSaturation = 0x00,
EnhancedColorModeCurrentXY = 0x01,
EnhancedColorModeColorTemperatureMireds = 0x02,
EnhancedColorModeEnhancedCurrentHueSaturation = 0x03
};
Q_ENUM(EnhancedColorMode)
enum ColorCapability {
ColorCapabilityHueSaturation = 0x01,
ColorCapabilityEnhancedHue = 0x02,
ColorCapabilityColorLoop = 0x04,
ColorCapabilityXY = 0x08,
ColorCapabilityColorTemperature = 0x10
};
Q_ENUM(ColorCapability)
Q_DECLARE_FLAGS(ColorCapabilities, ColorCapability)
enum Command {
CommandMoveToHue = 0x00,
CommandMoveHue = 0x01,
CommandStepHue = 0x02,
CommandMoveToSaturation = 0x03,
CommandMoveSaturation = 0x04,
CommandStepSaturation = 0x05,
CommandMoveToHueAndSaturation = 0x06,
CommandMoveToColor = 0x07,
CommandMoveColor = 0x08,
CommandStepColor = 0x09,
CommandMoveToColorTemperature = 0x0a,
CommandEnhancedMoveToHue = 0x40,
CommandEnhancedMoveHue = 0x41,
CommandEnhancedStepHue = 0x42,
CommandEnhancedMoveToHueAndSaturation = 0x43,
CommandColorLoopSet = 0x44,
CommandStopMoveStep = 0x47,
CommandMoveColorTemperature = 0x4b,
CommandStepColorTemperature = 0x4c
};
Q_ENUM(Command)
enum MoveDirection {
MoveDirectionShortestDistance = 0x00,
MoveDirectionLongestDistance = 0x01,
MoveDirectionUp = 0x02,
MoveDirectionDown = 0x03
};
Q_ENUM(MoveDirection)
enum MoveMode {
MoveModeStop = 0x00,
MoveModeUp = 0x01,
MoveModeDown = 0x02
};
Q_ENUM(MoveMode)
enum StepMode {
StepModeUp = 0x01,
StepModeDown = 0x03
};
Q_ENUM(StepMode)
// For the color loop command
enum ColorLoopUpdate {
ColorLoopUpdateAction = 0x01,
ColorLoopUpdateDirection = 0x02,
ColorLoopUpdateTime = 0x04,
ColorLoopUpdateStartHue = 0x08
};
Q_ENUM(ColorLoopUpdate)
Q_DECLARE_FLAGS(ColorLoopUpdateFlags, ColorLoopUpdate)
enum ColorLoopAction {
ColorLoopActionDeactivate = 0x00,
ColorLoopActionActivateColorLoopStartEnhancedHue = 0x01,
ColorLoopActionActivateEnhancedCurrentHue = 0x02
};
Q_ENUM(ColorLoopAction)
enum ColorLoopDirection {
ColorLoopDirectionDecrementHue = 0x00,
ColorLoopDirectionIncrementHue = 0x01
};
Q_ENUM(ColorLoopDirection)
explicit ZigbeeClusterColorControl(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
ZigbeeClusterReply *commandMoveToHue(quint8 hue, MoveDirection direction, quint16 transitionTime);
ZigbeeClusterReply *commandMoveHue(MoveMode moveMode, quint8 rate);
ZigbeeClusterReply *commandStepHue(StepMode stepMode, quint8 stepSize, quint8 transitionTime);
ZigbeeClusterReply *commandMoveToSaturation(quint8 saturation, MoveDirection direction, quint16 transitionTime);
ZigbeeClusterReply *commandMoveSaturation(MoveMode moveMode, quint8 rate);
ZigbeeClusterReply *commandStepSaturation(StepMode stepMode, quint8 stepSize, quint8 transitionTime);
ZigbeeClusterReply *commandMoveToHueAndSaturation(quint8 hue, quint8 saturation, quint16 transitionTime);
ZigbeeClusterReply *commandMoveToColor(quint16 colorX, quint16 colorY, quint16 transitionTime);
ZigbeeClusterReply *commandMoveColor(quint16 colorXRate, quint16 colorYRate);
ZigbeeClusterReply *commandStepColor(quint16 stepX, quint16 stepY, quint16 transitionTime);
ZigbeeClusterReply *commandEnhancedMoveToHue(quint16 enhancedHue, MoveDirection direction, quint16 transitionTime);
ZigbeeClusterReply *commandEnhancedMoveHue(MoveMode moveMode, quint16 rate);
ZigbeeClusterReply *commandEnhancedStepHue(StepMode stepMode, quint16 stepSize, quint16 transitionTime);
ZigbeeClusterReply *commandEnhancedMoveToHueAndSaturation(quint16 enhancedHue, quint8 saturation, quint16 transitionTime);
ZigbeeClusterReply *commandColorLoopSet(ColorLoopUpdateFlags updateFlag, ColorLoopAction action, ColorLoopDirection direction, quint16 time, quint16 startHue);
ZigbeeClusterReply *commandStopMoveStep();
ZigbeeClusterReply *commandMoveToColorTemperature(quint16 colorTemperatureMireds, quint16 transitionTime);
ZigbeeClusterReply *commandMoveColorTemperature(MoveMode moveMode, quint16 rate, quint16 minColorTemperature, quint16 maxColorTemperature);
ZigbeeClusterReply *commandStepColorTemperature(StepMode stepMode, quint16 stepSize, quint16 transitionTime, quint16 minColorTemperature, quint16 maxColorTemperature);
private:
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
protected:
void processDataIndication(ZigbeeClusterLibrary::Frame frame) override;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(ZigbeeClusterColorControl::ColorCapabilities)
Q_DECLARE_OPERATORS_FOR_FLAGS(ZigbeeClusterColorControl::ColorLoopUpdateFlags)
#endif // ZIGBEECLUSTERCOLORCONTROL_H

View File

@ -90,39 +90,6 @@ public:
// };
// Q_ENUM(PowerConfigurationAttribute)
// // Color cluster 0x0300
// enum ColorControlClusterAttribute {
// ColorControlClusterAttributeCurrentHue = 0x0000,
// ColorControlClusterAttributeCurrentSaturation = 0x0001,
// ColorControlClusterAttributeRemainingTime = 0x0002,
// ColorControlClusterAttributeCurrentX = 0x0003,
// ColorControlClusterAttributeCurrentY = 0x0004,
// ColorControlClusterAttributeDriftCompensation = 0x0005,
// ColorControlClusterAttributeCompensationText = 0x0006,
// ColorControlClusterAttributeColorTemperatureMireds = 0x0007,
// ColorControlClusterAttributeColorMode = 0x0008,
// ColorControlClusterAttributeEnhancedCurrentHue = 0x4000,
// ColorControlClusterAttributeEnhancedColorMode = 0x4001,
// ColorControlClusterAttributeColorLoopActive = 0x4002,
// ColorControlClusterAttributeColorLoopDirection = 0x4003,
// ColorControlClusterAttributeColorLoopTime = 0x4004,
// ColorControlClusterAttributeColorLoopStartEnhancedHue = 0x4005,
// ColorControlClusterAttributeColorLoopStoredEnhancedHue = 0x4006,
// ColorControlClusterAttributeColorCapabilities = 0x400a,
// ColorControlClusterAttributeColorTempPhysicalMinMireds = 0x400b,
// ColorControlClusterAttributeColorTempPhysicalMaxMireds = 0x400c
// };
// Q_ENUM(ColorControlClusterAttribute)
// enum ColorControlClusterColorMode {
// ColorControlClusterColorModeHueSaturation = 0x00,
// ColorControlClusterColorModeXY = 0x01,
// ColorControlClusterColorModeColorTemperatureMired = 0x02
// };
// Q_ENUM(ColorControlClusterColorMode)
explicit ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Zigbee::ClusterId clusterId, Direction direction, QObject *parent = nullptr);
ZigbeeNode *node() const;

View File

@ -309,10 +309,6 @@ void ZigbeeNetwork::saveNetwork()
settings.setValue("networkKey", securityConfiguration().networkKey().toString());
settings.setValue("trustCenterLinkKey", securityConfiguration().globalTrustCenterLinkKey().toString());
settings.endGroup();
foreach (ZigbeeNode *node, nodes()) {
m_database->saveNode(node);
}
}
void ZigbeeNetwork::loadNetwork()
@ -458,12 +454,12 @@ void ZigbeeNetwork::setState(ZigbeeNetwork::State state)
qCDebug(dcZigbeeNetwork()) << "State changed" << state;
m_state = state;
emit stateChanged(m_state);
if (state == StateRunning) {
saveNetwork();
qCDebug(dcZigbeeNetwork()) << this;
}
emit stateChanged(m_state);
}
void ZigbeeNetwork::setError(ZigbeeNetwork::Error error)
@ -478,7 +474,7 @@ void ZigbeeNetwork::setError(ZigbeeNetwork::Error error)
bool ZigbeeNetwork::networkConfigurationAvailable() const
{
return m_extendedPanId != 0 && m_channel != 0;
return m_extendedPanId != 0 && m_channel != 0 && m_coordinatorNode;
}
ZigbeeNetworkReply *ZigbeeNetwork::createNetworkReply(const ZigbeeNetworkRequest &request)
@ -545,7 +541,7 @@ void ZigbeeNetwork::onNodeClusterAttributeChanged(ZigbeeCluster *cluster, const
QDebug operator<<(QDebug debug, ZigbeeNetwork *network)
{
debug.nospace().noquote() << "ZigbeeNetwork (" << ZigbeeUtils::convertUint64ToHexString(network->extendedPanId())
debug.nospace().noquote() << "ZigbeeNetwork (" << ZigbeeUtils::convertUint16ToHexString(network->panId())
<< ", Channel " << network->channel()
<< ")" << endl;
foreach (ZigbeeNode *node, network->nodes()) {

View File

@ -133,7 +133,6 @@ private:
ZigbeeDeviceProfile::NodeType m_nodeType = ZigbeeDeviceProfile::NodeTypeCoordinator;
// Network storage
ZigbeeNetworkDatabase *m_database = nullptr;
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
QList<ZigbeeNode *> m_nodes;
QList<ZigbeeNode *> m_uninitializedNodes;
@ -147,6 +146,7 @@ protected:
ZigbeeNode *m_coordinatorNode = nullptr;
bool m_permitJoining = false;
ZigbeeSecurityConfiguration m_securityConfiguration;
ZigbeeNetworkDatabase *m_database = nullptr;
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent);
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, quint8 macCapabilities, QObject *parent);
@ -157,7 +157,6 @@ protected:
void clearSettings();
void saveNode(ZigbeeNode *node);
void addNode(ZigbeeNode *node);
void addUnitializedNode(ZigbeeNode *node);
void removeNode(ZigbeeNode *node);
@ -187,8 +186,8 @@ signals:
void nodeRemoved(ZigbeeNode *node);
void permitJoiningChanged(bool permitJoining);
void stateChanged(State state);
void errorOccured(Error error);
void stateChanged(State state);
private slots:
void onNodeStateChanged(ZigbeeNode::State state);

View File

@ -194,6 +194,11 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(Zigbee::ClusterId clusterId, Zi
return new ZigbeeClusterIlluminanceMeasurment(m_network, m_node, this, direction, this);
break;
// Lighting
case Zigbee::ClusterIdColorControl:
return new ZigbeeClusterColorControl(m_network, m_node, this, direction, this);
break;
// Security
case Zigbee::ClusterIdIasZone:
return new ZigbeeClusterIasZone(m_network, m_node, this, direction, this);

View File

@ -47,6 +47,8 @@
#include "zcl/measurement/zigbeeclustertemperaturemeasurement.h"
#include "zcl/measurement/zigbeeclusterrelativehumiditymeasurement.h"
#include "zcl/lighting/zigbeeclustercolorcontrol.h"
#include "zcl/security/zigbeeclusteriaszone.h"
class ZigbeeNode;