More work on OnOff, LevelControl and ScenesCluster

This alignes the OnOff cluster with the LevelControl cluster in terms
of signal behavior: Previously, the OnOff cluster would fire a generic
commandSent() signal for some commands and specific signals for others.
Effectively forcing the user to connect multiple signals even if only
the command would be of interest.

The LevelControl cluster instead always fired a generic commandSent()
signal and *additionally* more specific signals for parsed parameters.

This changes the OnOff cluster to be in line with the LevelCluster
as and making the API a bit simpler to use when parameters are not of
interest.

Also it completes the specific parsing for all 3 clusters.
This commit is contained in:
Michael Zanetti 2021-11-08 00:58:55 +01:00
parent c5d9b119af
commit 6afc214202
6 changed files with 52 additions and 37 deletions

View File

@ -29,6 +29,7 @@
#include "zigbeenetworkreply.h"
#include "loggingcategory.h"
#include "zigbeenetwork.h"
#include "zigbeeutils.h"
#include <QDataStream>
@ -56,12 +57,12 @@ ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMove(ZigbeeClusterLevelCon
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMove, payload);
}
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStep(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transitionTime)
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStep(StepMode stepMode, quint8 stepSize, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(fadeMode) << stepSize << transitionTime;
stream << static_cast<quint8>(stepMode) << stepSize << transitionTime;
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStep, payload);
}
@ -88,12 +89,12 @@ ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveWithOnOff(ZigbeeCluste
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMoveWithOnOff, payload);
}
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStepWithOnOff(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transitionTime)
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStepWithOnOff(StepMode stepMode, quint8 stepSize, quint16 transitionTime)
{
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(fadeMode) << stepSize << transitionTime;
stream << static_cast<quint8>(stepMode) << stepSize << transitionTime;
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStepWithOnOff, payload);
}
@ -128,8 +129,6 @@ void ZigbeeClusterLevelControl::setAttribute(const ZigbeeClusterAttribute &attri
void ZigbeeClusterLevelControl::processDataIndication(ZigbeeClusterLibrary::Frame frame)
{
qCDebug(dcZigbeeCluster()) << "Processing cluster frame" << m_node << m_endpoint << this << frame;
// Increase the tsn for continuous id increasing on both sides
m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
@ -139,30 +138,48 @@ void ZigbeeClusterLevelControl::processDataIndication(ZigbeeClusterLibrary::Fram
if (frame.header.frameControl.direction == ZigbeeClusterLibrary::DirectionClientToServer) {
// Read the payload which is
Command command = static_cast<Command>(frame.header.command);
qCDebug(dcZigbeeCluster()) << "Command sent from" << m_node << m_endpoint << this << command;
emit commandSent(command, frame.payload);
bool withOnOff = false;
switch (command) {
case CommandMoveToLevelWithOnOff:
case CommandMoveToLevel: {
QByteArray payload = frame.payload;
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint8 level; quint16 transitionTime;
payloadStream >> level >> transitionTime;
withOnOff = command == CommandMoveToLevelWithOnOff;
qCDebug(dcZigbeeCluster()).noquote().nospace() << "Command received from " << m_node << " " << m_endpoint << " " << this << " " << command << " withOnOff: " << withOnOff << " level: 0x" << QString::number(level, 16) << " transitionTime: 0x" << QString::number(transitionTime, 16);
emit commandMoveToLevelSent(withOnOff, level, transitionTime);
break;
}
case CommandStepWithOnOff:
case CommandStep: {
QByteArray payload = frame.payload;
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint8 fadeModeValue = 0; quint8 stepSize; quint16 transitionTime;
payloadStream >> fadeModeValue >> stepSize >> transitionTime;
emit commandStepSent(static_cast<FadeMode>(fadeModeValue), stepSize, transitionTime);
quint8 stepModeValue = 0; quint8 stepSize; quint16 transitionTime;
payloadStream >> stepModeValue >> stepSize >> transitionTime;
withOnOff = command == CommandMoveToLevelWithOnOff;
qCDebug(dcZigbeeCluster()).noquote().nospace() << "Command received from " << m_node << " " << m_endpoint << " " << this << " " << command << " withOnOff: " << withOnOff << " stepModeValue: 0x" << QString::number(stepModeValue, 16) << " stepSize: 0x" << QString::number(stepSize, 16) << " transitionTime: 0x" << QString::number(transitionTime, 16);
emit commandStepSent(withOnOff, static_cast<StepMode>(stepModeValue), stepSize, transitionTime);
break;
}
case CommandMoveWithOnOff:
case CommandMove: {
QByteArray payload = frame.payload;
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint8 moveModeValue = 0; quint8 rate;;
payloadStream >> moveModeValue >> rate;
emit commandMoveSent(static_cast<MoveMode>(moveModeValue), rate);
withOnOff = command == CommandMoveToLevelWithOnOff;
qCDebug(dcZigbeeCluster()).noquote().nospace() << "Command received from " << m_node << " " << m_endpoint << " " << this << " " << command << " withOnOff:" << withOnOff << " moveModeValue: 0x" << QString::number(moveModeValue, 16) << " rate: 0x" << QString::number(rate, 16);
emit commandMoveSent(withOnOff, static_cast<MoveMode>(moveModeValue), rate);
break;
}
default:
qCDebug(dcZigbeeCluster()) << "Command received without special implementation";
qCDebug(dcZigbeeCluster()).noquote().nospace() << "Command received from " << m_node << " " << m_endpoint << " " << this << " " << command << " payload: 0x" << ZigbeeUtils::convertByteArrayToHexString(frame.payload);
break;
}

View File

@ -75,23 +75,23 @@ public:
};
Q_ENUM(MoveMode)
enum FadeMode {
FadeModeUp = 0x00,
FadeModeDown = 0x01
enum StepMode {
StepModeUp = 0x00,
StepModeDown = 0x01
};
Q_ENUM(FadeMode)
Q_ENUM(StepMode)
explicit ZigbeeClusterLevelControl(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
ZigbeeClusterReply *commandMoveToLevel(quint8 level, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandMove(MoveMode moveMode, quint8 rate = 0xff);
ZigbeeClusterReply *commandStep(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandStep(StepMode stepMode, quint8 stepSize = 0x01, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandStop();
// With on/off
ZigbeeClusterReply *commandMoveToLevelWithOnOff(quint8 level, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandMoveWithOnOff(MoveMode moveMode, quint8 rate = 0xff);
ZigbeeClusterReply *commandStepWithOnOff(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandStepWithOnOff(StepMode stepMode, quint8 stepSize = 0x01, quint16 transitionTime = 0xffff);
ZigbeeClusterReply *commandStopWithOnOff();
quint8 currentLevel() const;
@ -107,8 +107,10 @@ protected:
signals:
void currentLevelChanged(quint8 level);
void commandSent(ZigbeeClusterLevelControl::Command command, const QByteArray &parameter = QByteArray());
void commandMoveSent(MoveMode moveMode, quint8 rate = 0xff);
void commandStepSent(FadeMode fadeMode, quint8 stepSize, quint16 transitionTime);
void commandMoveToLevelSent(bool withOnOff, quint8 level, quint16 transitionTime);
void commandMoveSent(bool withOnOff, MoveMode moveMode, quint8 rate = 0xff);
void commandStepSent(bool withOnOff, StepMode stepMode, quint8 stepSize, quint16 transitionTime);
void commandStopSent();
};

View File

@ -114,23 +114,15 @@ void ZigbeeClusterOnOff::processDataIndication(ZigbeeClusterLibrary::Frame frame
if (frame.header.frameControl.direction == ZigbeeClusterLibrary::DirectionClientToServer) {
// Read the payload which is
Command command = static_cast<Command>(frame.header.command);
qCDebug(dcZigbeeCluster()) << "Received" << command << "from" << m_node << m_endpoint << this;
emit commandSent(command, frame.payload);
switch (command) {
case CommandOn:
emit commandSent(CommandOn);
break;
case CommandOff:
emit commandSent(CommandOff);
break;
case CommandToggle:
emit commandSent(CommandToggle);
break;
case CommandOffWithEffect: {
QByteArray payload = frame.payload;
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint8 effectValue = 0; quint16 effectVariant;
payloadStream >> effectValue >> effectVariant;
qCDebug(dcZigbeeCluster()) << "Command received from" << m_node << m_endpoint << this << command << "effect:" << effectValue << "effectVariant:" << effectVariant;
emit commandOffWithEffectSent(static_cast<Effect>(effectValue), effectVariant);
break;
}
@ -140,11 +132,12 @@ void ZigbeeClusterOnOff::processDataIndication(ZigbeeClusterLibrary::Frame frame
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint8 acceptOnlyWhenOnInt = 0; quint16 onTime; quint16 offTime;
payloadStream >> acceptOnlyWhenOnInt >> onTime >> offTime;
qCDebug(dcZigbeeCluster()) << "Command received from" << m_node << m_endpoint << this << command << "accentOnlyWhenOnInt:" << acceptOnlyWhenOnInt << "onTime:" << onTime << "offTime:" << offTime;
emit commandOnWithTimedOffSent(static_cast<bool>(acceptOnlyWhenOnInt), onTime, offTime);
break;
}
default:
qCWarning(dcZigbeeCluster()) << "Unhandled command sent from" << m_node << m_endpoint << this << command << ZigbeeUtils::convertByteArrayToHexString(frame.payload);
qCDebug(dcZigbeeCluster()) << "Command received from" << m_node << m_endpoint << this << command << ZigbeeUtils::convertByteArrayToHexString(frame.payload);
break;
}
}

View File

@ -94,7 +94,7 @@ signals:
void powerChanged(bool power);
// Client cluster signals
void commandSent(Command command);
void commandSent(Command command, const QByteArray &parameters = QByteArray());
// On and off time is in 1/10 seconds
void commandOnWithTimedOffSent(bool acceptOnlyWhenOn, quint16 onTime, quint16 offTime);

View File

@ -45,8 +45,6 @@ void ZigbeeClusterScenes::setAttribute(const ZigbeeClusterAttribute &attribute)
void ZigbeeClusterScenes::processDataIndication(ZigbeeClusterLibrary::Frame frame)
{
qCDebug(dcZigbeeCluster()) << "Processing cluster frame" << m_node << m_endpoint << this << frame;
// Increase the tsn for continuous id increasing on both sides
m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
@ -54,8 +52,13 @@ void ZigbeeClusterScenes::processDataIndication(ZigbeeClusterLibrary::Frame fram
case Client: {
// Read the payload which is
Command command = static_cast<Command>(frame.header.command);
qCDebug(dcZigbeeCluster()) << "Received" << command << "from" << m_node << m_endpoint << this << ZigbeeUtils::convertByteArrayToHexString(frame.payload);
emit commandSent(frame.header.command, frame.payload);
QByteArray payload = frame.payload;
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint16 groupId = 0; quint8 sceneId;
payloadStream >> groupId >> sceneId;
qCDebug(dcZigbeeCluster()).noquote() << "Received" << command << "for group" << "0x" + QString::number(groupId, 16) << "and scene" << sceneId << "from" << m_node << m_endpoint << this;
emit commandSent(command, groupId, sceneId);
break;
}
case Server:

View File

@ -63,7 +63,7 @@ public:
explicit ZigbeeClusterScenes(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
signals:
void commandSent(quint8 command, const QByteArray &payload);
void commandSent(Command command, quint16 groupId, quint8 sceneId);
private:
void setAttribute(const ZigbeeClusterAttribute &attribute) override;