Add on off cluster and use zigbedatatype for atributes
This commit is contained in:
parent
ab560a9c55
commit
7e5643a1cf
@ -250,7 +250,7 @@ bool ZigbeeInterfaceDeconz::enable(const QString &serialPort, qint32 baudrate)
|
|||||||
connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onError(QSerialPort::SerialPortError)));
|
connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onError(QSerialPort::SerialPortError)));
|
||||||
|
|
||||||
if (!m_serialPort->open(QSerialPort::ReadWrite)) {
|
if (!m_serialPort->open(QSerialPort::ReadWrite)) {
|
||||||
qCWarning(dcZigbeeInterface()) << "Could not open serial port" << serialPort << baudrate;
|
qCWarning(dcZigbeeInterface()) << "Could not open serial port" << serialPort << baudrate << m_serialPort->errorString();
|
||||||
m_reconnectTimer->start();
|
m_reconnectTimer->start();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ SOURCES += \
|
|||||||
backends/deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
backends/deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
||||||
backends/deconz/zigbeebridgecontrollerdeconz.cpp \
|
backends/deconz/zigbeebridgecontrollerdeconz.cpp \
|
||||||
backends/deconz/zigbeenetworkdeconz.cpp \
|
backends/deconz/zigbeenetworkdeconz.cpp \
|
||||||
|
zcl/general/zigbeeclusteronoff.cpp \
|
||||||
zcl/zigbeecluster.cpp \
|
zcl/zigbeecluster.cpp \
|
||||||
zcl/zigbeeclusterattribute.cpp \
|
zcl/zigbeeclusterattribute.cpp \
|
||||||
zcl/zigbeeclusterlibrary.cpp \
|
zcl/zigbeeclusterlibrary.cpp \
|
||||||
@ -49,6 +50,7 @@ HEADERS += \
|
|||||||
backends/deconz/interface/zigbeeinterfacedeconzreply.h \
|
backends/deconz/interface/zigbeeinterfacedeconzreply.h \
|
||||||
backends/deconz/zigbeebridgecontrollerdeconz.h \
|
backends/deconz/zigbeebridgecontrollerdeconz.h \
|
||||||
backends/deconz/zigbeenetworkdeconz.h \
|
backends/deconz/zigbeenetworkdeconz.h \
|
||||||
|
zcl/general/zigbeeclusteronoff.h \
|
||||||
zcl/zigbeecluster.h \
|
zcl/zigbeecluster.h \
|
||||||
zcl/zigbeeclusterattribute.h \
|
zcl/zigbeeclusterattribute.h \
|
||||||
zcl/zigbeeclusterlibrary.h \
|
zcl/zigbeeclusterlibrary.h \
|
||||||
|
|||||||
@ -1,3 +1,30 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 "zigbeeclusterbasic.h"
|
#include "zigbeeclusterbasic.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
@ -10,11 +37,11 @@ ZigbeeClusterBasic::ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node,
|
|||||||
void ZigbeeClusterBasic::setAttribute(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeClusterBasic::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
if (hasAttribute(attribute.id())) {
|
if (hasAttribute(attribute.id())) {
|
||||||
qCDebug(dcZigbeeCluster()) << this << "update attribute" << static_cast<Attribute>(attribute.id()) << attribute.dataType() << attribute.data();
|
qCDebug(dcZigbeeCluster()) << "Update attribute" << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||||
m_attributes[attribute.id()] = attribute;
|
m_attributes[attribute.id()] = attribute;
|
||||||
emit attributeChanged(attribute);
|
emit attributeChanged(attribute);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(dcZigbeeCluster()) << this << "add attribute" << static_cast<Attribute>(attribute.id()) << attribute.dataType() << attribute.data();
|
qCDebug(dcZigbeeCluster()) << "Add attribute" << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||||
m_attributes.insert(attribute.id(), attribute);
|
m_attributes.insert(attribute.id(), attribute);
|
||||||
emit attributeChanged(attribute);
|
emit attributeChanged(attribute);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,30 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 ZIGBEECLUSTERBASIC_H
|
#ifndef ZIGBEECLUSTERBASIC_H
|
||||||
#define ZIGBEECLUSTERBASIC_H
|
#define ZIGBEECLUSTERBASIC_H
|
||||||
|
|
||||||
@ -172,13 +199,9 @@ public:
|
|||||||
|
|
||||||
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(ZigbeeClusterBasic::AlarmMasks)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(ZigbeeClusterBasic::AlarmMasks)
|
||||||
|
|||||||
159
libnymea-zigbee/zcl/general/zigbeeclusteronoff.cpp
Normal file
159
libnymea-zigbee/zcl/general/zigbeeclusteronoff.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 "zigbeeclusteronoff.h"
|
||||||
|
#include "zigbeenetworkreply.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
#include "zigbeenetwork.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
ZigbeeClusterOnOff::ZigbeeClusterOnOff(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent) :
|
||||||
|
ZigbeeCluster(network, node, endpoint, Zigbee::ClusterIdOnOff, direction, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOnOff::commandOff()
|
||||||
|
{
|
||||||
|
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||||
|
|
||||||
|
// Build ZCL frame
|
||||||
|
|
||||||
|
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
||||||
|
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||||
|
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||||
|
frameControl.manufacturerSpecific = false;
|
||||||
|
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||||
|
frameControl.disableDefaultResponse = false;
|
||||||
|
|
||||||
|
// ZCL header
|
||||||
|
ZigbeeClusterLibrary::Header header;
|
||||||
|
header.frameControl = frameControl;
|
||||||
|
header.command = ZigbeeClusterOnOff::CommandOff;
|
||||||
|
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||||
|
|
||||||
|
// there is no ZCL payload
|
||||||
|
|
||||||
|
// Put them together
|
||||||
|
ZigbeeClusterLibrary::Frame frame;
|
||||||
|
frame.header = header;
|
||||||
|
|
||||||
|
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||||
|
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||||
|
|
||||||
|
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||||
|
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||||
|
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||||
|
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||||
|
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||||
|
<< m_node << networkReply->error()
|
||||||
|
<< networkReply->zigbeeApsStatus();
|
||||||
|
finishZclReply(zclReply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The request was successfully sent to the device
|
||||||
|
// Now check if the expected indication response received already
|
||||||
|
if (zclReply->isComplete()) {
|
||||||
|
finishZclReply(zclReply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return zclReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOnOff::commandOn()
|
||||||
|
{
|
||||||
|
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||||
|
|
||||||
|
// Build ZCL frame
|
||||||
|
|
||||||
|
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
||||||
|
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||||
|
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||||
|
frameControl.manufacturerSpecific = false;
|
||||||
|
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||||
|
frameControl.disableDefaultResponse = false;
|
||||||
|
|
||||||
|
// ZCL header
|
||||||
|
ZigbeeClusterLibrary::Header header;
|
||||||
|
header.frameControl = frameControl;
|
||||||
|
header.command = ZigbeeClusterOnOff::CommandOn;
|
||||||
|
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||||
|
|
||||||
|
// There is no ZCL payload
|
||||||
|
|
||||||
|
// Put them together
|
||||||
|
ZigbeeClusterLibrary::Frame frame;
|
||||||
|
frame.header = header;
|
||||||
|
|
||||||
|
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||||
|
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||||
|
|
||||||
|
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||||
|
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||||
|
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||||
|
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||||
|
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||||
|
<< m_node << networkReply->error()
|
||||||
|
<< networkReply->zigbeeApsStatus();
|
||||||
|
finishZclReply(zclReply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The request was successfully sent to the device
|
||||||
|
// Now check if the expected indication response received already
|
||||||
|
if (zclReply->isComplete()) {
|
||||||
|
finishZclReply(zclReply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return zclReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeClusterOnOff::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
|
{
|
||||||
|
if (hasAttribute(attribute.id())) {
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Update attribute" << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||||
|
m_attributes[attribute.id()] = attribute;
|
||||||
|
emit attributeChanged(attribute);
|
||||||
|
} else {
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Add attribute" << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||||
|
m_attributes.insert(attribute.id(), attribute);
|
||||||
|
emit attributeChanged(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeClusterOnOff::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
||||||
|
{
|
||||||
|
// Increase the tsn for continuouse id increasing on both sides
|
||||||
|
m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
|
||||||
|
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
|
||||||
|
}
|
||||||
87
libnymea-zigbee/zcl/general/zigbeeclusteronoff.h
Normal file
87
libnymea-zigbee/zcl/general/zigbeeclusteronoff.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 ZIGBEECLUSTERONOFF_H
|
||||||
|
#define ZIGBEECLUSTERONOFF_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zcl/zigbeecluster.h"
|
||||||
|
#include "zcl/zigbeeclusterreply.h"
|
||||||
|
|
||||||
|
class ZigbeeNode;
|
||||||
|
class ZigbeeNetwork;
|
||||||
|
class ZigbeeNodeEndpoint;
|
||||||
|
class ZigbeeNetworkReply;
|
||||||
|
|
||||||
|
class ZigbeeClusterOnOff : public ZigbeeCluster
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ZigbeeNode;
|
||||||
|
friend class ZigbeeNetwork;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Attribute {
|
||||||
|
AttributeOnOff = 0x0000,
|
||||||
|
AttributeGlobalSceneControl = 0x4000,
|
||||||
|
AttributeOnTime = 0x4001,
|
||||||
|
AttributeOffTime = 0x4002
|
||||||
|
};
|
||||||
|
Q_ENUM(Attribute)
|
||||||
|
|
||||||
|
enum Command {
|
||||||
|
CommandOff = 0x00,
|
||||||
|
CommandOn = 0x01,
|
||||||
|
CommandToggle = 0x02,
|
||||||
|
CommandOffWithEffect = 0x40,
|
||||||
|
CommandOnWithRecallGlobalScene = 0x41,
|
||||||
|
CommandOnWithTimedOff = 0x42
|
||||||
|
};
|
||||||
|
Q_ENUM(Command)
|
||||||
|
|
||||||
|
explicit ZigbeeClusterOnOff(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
ZigbeeClusterReply *commandOff();
|
||||||
|
ZigbeeClusterReply *commandOn();
|
||||||
|
// ZigbeeClusterReply *commandToggle();
|
||||||
|
// ZigbeeClusterReply *commandOffWithEffect();
|
||||||
|
// ZigbeeClusterReply *commandOnWithRecallGlobalScene();
|
||||||
|
// ZigbeeClusterReply *commandOnWithTimedOff();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void processDataIndication(ZigbeeClusterLibrary::Frame frame) override;
|
||||||
|
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ZIGBEECLUSTERONOFF_H
|
||||||
@ -82,11 +82,11 @@ ZigbeeClusterAttribute ZigbeeCluster::attribute(quint16 attributeId)
|
|||||||
void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
if (hasAttribute(attribute.id())) {
|
if (hasAttribute(attribute.id())) {
|
||||||
qCDebug(dcZigbeeCluster()) << this << "update attribute" << attribute;
|
qCDebug(dcZigbeeCluster()) << "Update attribute" << this << attribute;
|
||||||
m_attributes[attribute.id()] = attribute;
|
m_attributes[attribute.id()] = attribute;
|
||||||
emit attributeChanged(attribute);
|
emit attributeChanged(attribute);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(dcZigbeeCluster()) << this << "add attribute" << attribute;
|
qCDebug(dcZigbeeCluster()) << "Add attribute" << this << attribute;
|
||||||
m_attributes.insert(attribute.id(), attribute);
|
m_attributes.insert(attribute.id(), attribute);
|
||||||
emit attributeChanged(attribute);
|
emit attributeChanged(attribute);
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
|||||||
|
|
||||||
ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Read attributes from" << m_node << m_endpoint << this << attributes;
|
qCDebug(dcZigbeeCluster()) << "Read attributes from" << m_node << m_endpoint << this << attributes;
|
||||||
|
|
||||||
// Build the request
|
// Build the request
|
||||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||||
@ -139,7 +139,7 @@ ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
|||||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||||
<< m_node << networkReply->error()
|
<< m_node << m_endpoint << this << networkReply->error()
|
||||||
<< networkReply->zigbeeApsStatus();
|
<< networkReply->zigbeeApsStatus();
|
||||||
finishZclReply(zclReply);
|
finishZclReply(zclReply);
|
||||||
return;
|
return;
|
||||||
@ -211,14 +211,23 @@ bool ZigbeeCluster::verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetwo
|
|||||||
void ZigbeeCluster::finishZclReply(ZigbeeClusterReply *zclReply)
|
void ZigbeeCluster::finishZclReply(ZigbeeClusterReply *zclReply)
|
||||||
{
|
{
|
||||||
m_pendingReplies.remove(zclReply->transactionSequenceNumber());
|
m_pendingReplies.remove(zclReply->transactionSequenceNumber());
|
||||||
|
qCDebug(dcZigbeeCluster()) << "ZigbeeClusterReply finished" << zclReply->request() << zclReply->requestFrame() << zclReply->responseFrame();
|
||||||
zclReply->finished();
|
zclReply->finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeCluster::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
||||||
|
{
|
||||||
|
// Increase the tsn for continuouse id increasing on both sides
|
||||||
|
m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
|
||||||
|
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeCluster::processApsDataIndication(QByteArray payload)
|
void ZigbeeCluster::processApsDataIndication(QByteArray payload)
|
||||||
{
|
{
|
||||||
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(payload);
|
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(payload);
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << this << "received data indication" << frame;
|
qCDebug(dcZigbeeCluster()) << "Received data indication" << this << frame;
|
||||||
|
|
||||||
|
// Check if this indication is for a pending reply
|
||||||
if (m_pendingReplies.contains(frame.header.transactionSequenceNumber)) {
|
if (m_pendingReplies.contains(frame.header.transactionSequenceNumber)) {
|
||||||
ZigbeeClusterReply *reply = m_pendingReplies.value(frame.header.transactionSequenceNumber);
|
ZigbeeClusterReply *reply = m_pendingReplies.value(frame.header.transactionSequenceNumber);
|
||||||
reply->m_responseData = payload;
|
reply->m_responseData = payload;
|
||||||
@ -231,8 +240,8 @@ void ZigbeeCluster::processApsDataIndication(QByteArray payload)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: increase transaction sequence number
|
// Not for a reply, process the indication
|
||||||
qCWarning(dcZigbeeNode()) << m_node << m_endpoint << this << "Unhandled ZCL indication" << ZigbeeUtils::convertByteArrayToHexString(payload);
|
processDataIndication(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
||||||
@ -252,7 +261,7 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeRep
|
|||||||
<< attributeReport.attributeId << ", "
|
<< attributeReport.attributeId << ", "
|
||||||
<< attributeReport.attributeStatus << ", "
|
<< attributeReport.attributeStatus << ", "
|
||||||
<< attributeReport.dataType << ", "
|
<< attributeReport.dataType << ", "
|
||||||
<< attributeReport.data << ", "
|
<< ZigbeeUtils::convertByteArrayToHexString(attributeReport.data)
|
||||||
<< ")";
|
<< ")";
|
||||||
|
|
||||||
return debug.space();
|
return debug.space();
|
||||||
|
|||||||
@ -89,23 +89,6 @@ public:
|
|||||||
// };
|
// };
|
||||||
// Q_ENUM(PowerConfigurationAttribute)
|
// Q_ENUM(PowerConfigurationAttribute)
|
||||||
|
|
||||||
// // On Off Cluster 0x0006
|
|
||||||
|
|
||||||
// enum OnOffClusterAttribute {
|
|
||||||
// OnOffClusterAttributeOnOff = 0x0000,
|
|
||||||
// OnOffClusterAttributeGlobalSceneControl = 0x4000,
|
|
||||||
// OnOffClusterAttributeOnTime = 0x4001,
|
|
||||||
// OnOffClusterAttributeOffWaitTime = 0x4002
|
|
||||||
// };
|
|
||||||
// Q_ENUM(OnOffClusterAttribute)
|
|
||||||
|
|
||||||
// enum OnOffClusterCommand {
|
|
||||||
// OnOffClusterCommandOff = 0x00,
|
|
||||||
// OnOffClusterCommandOn = 0x01,
|
|
||||||
// OnOffClusterCommandToggle = 0x02
|
|
||||||
// };
|
|
||||||
// Q_ENUM(OnOffClusterCommand)
|
|
||||||
|
|
||||||
|
|
||||||
// // Level cluster 0x0008
|
// // Level cluster 0x0008
|
||||||
|
|
||||||
@ -195,6 +178,8 @@ protected:
|
|||||||
bool verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply);
|
bool verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply);
|
||||||
void finishZclReply(ZigbeeClusterReply *zclReply);
|
void finishZclReply(ZigbeeClusterReply *zclReply);
|
||||||
|
|
||||||
|
virtual void processDataIndication(ZigbeeClusterLibrary::Frame frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void setAttribute(const ZigbeeClusterAttribute &attribute);
|
virtual void setAttribute(const ZigbeeClusterAttribute &attribute);
|
||||||
|
|
||||||
@ -204,7 +189,6 @@ signals:
|
|||||||
public slots:
|
public slots:
|
||||||
void processApsDataIndication(QByteArray payload);
|
void processApsDataIndication(QByteArray payload);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster);
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster);
|
||||||
|
|||||||
@ -33,10 +33,9 @@ ZigbeeClusterAttribute::ZigbeeClusterAttribute()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterAttribute::ZigbeeClusterAttribute(quint16 id, Zigbee::DataType dataType, QByteArray data):
|
ZigbeeClusterAttribute::ZigbeeClusterAttribute(quint16 id, const ZigbeeDataType &dataType):
|
||||||
m_id(id),
|
m_id(id),
|
||||||
m_dataType(dataType),
|
m_dataType(dataType)
|
||||||
m_data(data)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -45,7 +44,6 @@ ZigbeeClusterAttribute::ZigbeeClusterAttribute(const ZigbeeClusterAttribute &oth
|
|||||||
{
|
{
|
||||||
m_id = other.id();
|
m_id = other.id();
|
||||||
m_dataType = other.dataType();
|
m_dataType = other.dataType();
|
||||||
m_data = other.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 ZigbeeClusterAttribute::id() const
|
quint16 ZigbeeClusterAttribute::id() const
|
||||||
@ -53,29 +51,21 @@ quint16 ZigbeeClusterAttribute::id() const
|
|||||||
return m_id;
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zigbee::DataType ZigbeeClusterAttribute::dataType() const
|
ZigbeeDataType ZigbeeClusterAttribute::dataType() const
|
||||||
{
|
{
|
||||||
return m_dataType;
|
return m_dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray ZigbeeClusterAttribute::data() const
|
|
||||||
{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeClusterAttribute &ZigbeeClusterAttribute::operator=(const ZigbeeClusterAttribute &other)
|
ZigbeeClusterAttribute &ZigbeeClusterAttribute::operator=(const ZigbeeClusterAttribute &other)
|
||||||
{
|
{
|
||||||
m_id = other.id();
|
m_id = other.id();
|
||||||
m_dataType = other.dataType();
|
m_dataType = other.dataType();
|
||||||
m_data = other.data();
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZigbeeClusterAttribute::operator==(const ZigbeeClusterAttribute &other) const
|
bool ZigbeeClusterAttribute::operator==(const ZigbeeClusterAttribute &other) const
|
||||||
{
|
{
|
||||||
return m_id == other.id() &&
|
return m_id == other.id() && m_dataType == other.dataType();
|
||||||
m_dataType == other.dataType() &&
|
|
||||||
m_data == other.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZigbeeClusterAttribute::operator!=(const ZigbeeClusterAttribute &other) const
|
bool ZigbeeClusterAttribute::operator!=(const ZigbeeClusterAttribute &other) const
|
||||||
@ -85,16 +75,14 @@ bool ZigbeeClusterAttribute::operator!=(const ZigbeeClusterAttribute &other) con
|
|||||||
|
|
||||||
bool ZigbeeClusterAttribute::isValid() const
|
bool ZigbeeClusterAttribute::isValid() const
|
||||||
{
|
{
|
||||||
return m_id != 0 ||
|
return m_id != 0xffff && m_dataType.isValid();
|
||||||
m_dataType != Zigbee::NoData ||
|
|
||||||
!m_data.isNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute)
|
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
debug.nospace().noquote() << "ZigbeeClusterAttribute("
|
debug.nospace().noquote() << "ZigbeeClusterAttribute("
|
||||||
<< ZigbeeUtils::convertUint16ToHexString(attribute.id()) << ", "
|
<< ZigbeeUtils::convertUint16ToHexString(attribute.id()) << ", "
|
||||||
<< attribute.dataType() << ", "
|
<< attribute.dataType()
|
||||||
<< ZigbeeUtils::convertByteArrayToHexString(attribute.data()) << ")";
|
<< ")";
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,17 +31,17 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
|
#include "zigbeedatatype.h"
|
||||||
|
|
||||||
class ZigbeeClusterAttribute
|
class ZigbeeClusterAttribute
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZigbeeClusterAttribute();
|
ZigbeeClusterAttribute();
|
||||||
ZigbeeClusterAttribute(quint16 id, Zigbee::DataType dataType, QByteArray data);
|
ZigbeeClusterAttribute(quint16 id, const ZigbeeDataType &dataType);
|
||||||
ZigbeeClusterAttribute(const ZigbeeClusterAttribute &other);
|
ZigbeeClusterAttribute(const ZigbeeClusterAttribute &other);
|
||||||
|
|
||||||
quint16 id() const;
|
quint16 id() const;
|
||||||
Zigbee::DataType dataType() const;
|
ZigbeeDataType dataType() const;
|
||||||
QByteArray data() const;
|
|
||||||
|
|
||||||
ZigbeeClusterAttribute &operator=(const ZigbeeClusterAttribute &other);
|
ZigbeeClusterAttribute &operator=(const ZigbeeClusterAttribute &other);
|
||||||
bool operator==(const ZigbeeClusterAttribute &other) const;
|
bool operator==(const ZigbeeClusterAttribute &other) const;
|
||||||
@ -50,9 +50,8 @@ public:
|
|||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint16 m_id = 0;
|
quint16 m_id = 0xffff;
|
||||||
Zigbee::DataType m_dataType = Zigbee::NoData;
|
ZigbeeDataType m_dataType;
|
||||||
QByteArray m_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute);
|
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute);
|
||||||
|
|||||||
@ -104,13 +104,11 @@ QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> ZigbeeClusterLibrary::par
|
|||||||
|
|
||||||
QDataStream stream(payload);
|
QDataStream stream(payload);
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint16 attributeId; quint8 statusInt; quint8 dataTypeInt; quint16 numberOfElenemts; quint8 elementType;
|
quint16 attributeId; quint8 statusInt; quint8 dataTypeInt;
|
||||||
QByteArray data;
|
|
||||||
|
|
||||||
while (!stream.atEnd()) {
|
while (!stream.atEnd()) {
|
||||||
// Reset variables
|
// Reset variables
|
||||||
attributeId = 0; statusInt = 0; dataTypeInt = 0; numberOfElenemts = 0; elementType = 0;
|
attributeId = 0; statusInt = 0; dataTypeInt = 0;
|
||||||
data.clear();
|
|
||||||
|
|
||||||
// Read attribute id and status
|
// Read attribute id and status
|
||||||
stream >> attributeId >> statusInt;
|
stream >> attributeId >> statusInt;
|
||||||
@ -126,72 +124,15 @@ QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> ZigbeeClusterLibrary::par
|
|||||||
stream >> dataTypeInt;
|
stream >> dataTypeInt;
|
||||||
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(dataTypeInt);
|
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(dataTypeInt);
|
||||||
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse:" << dataType;
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse data type:" << dataType;
|
||||||
|
ZigbeeDataType type = readDataType(&stream, dataType);
|
||||||
// Parse data depending on the type
|
if (!type.isValid())
|
||||||
if (dataType == Zigbee::Array || dataType == Zigbee::Set || dataType == Zigbee::Bag) {
|
continue;
|
||||||
stream >> elementType >> numberOfElenemts;
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse (array, set, bag): Element type" << ZigbeeUtils::convertByteToHexString(elementType) << "Number of elements:" << numberOfElenemts;
|
|
||||||
if (numberOfElenemts == 0xffff) {
|
|
||||||
qCWarning(dcZigbeeCluster()) << "ZigbeeStatusRecord contains invalid elements" << ZigbeeUtils::convertUint16ToHexString(attributeId) << dataType;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < numberOfElenemts; i++) {
|
|
||||||
quint8 element = 0;
|
|
||||||
stream >> element;
|
|
||||||
data.append(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (dataType == Zigbee::Structure) {
|
|
||||||
stream >> numberOfElenemts;
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Number of elements:" << numberOfElenemts;
|
|
||||||
if (numberOfElenemts == 0xffff) {
|
|
||||||
qCWarning(dcZigbeeCluster()) << "ZigbeeStatusRecord contains invalid elements" << ZigbeeUtils::convertUint16ToHexString(attributeId) << dataType;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
stream >> elementType;
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Element type:" << ZigbeeUtils::convertByteToHexString(elementType);
|
|
||||||
for (int i = 0; i < numberOfElenemts; i++) {
|
|
||||||
quint8 element = 0;
|
|
||||||
stream >> element;
|
|
||||||
//qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Element value:" << ZigbeeUtils::convertByteToHexString(element);
|
|
||||||
data.append(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (dataType == Zigbee::OctetString || dataType == Zigbee::CharString) {
|
|
||||||
quint8 length = 0;
|
|
||||||
stream >> length;
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse (octet string, character string)" << "Length:" << length;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
quint8 element = 0;
|
|
||||||
stream >> element;
|
|
||||||
data.append(element);
|
|
||||||
}
|
|
||||||
} else if (dataType == Zigbee::LongOctetString || dataType == Zigbee::LongCharString) {
|
|
||||||
quint16 length = 0;
|
|
||||||
stream >> length;
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse (long octet string, long character string)" << "Length:" << length;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
quint8 element = 0;
|
|
||||||
stream >> element;
|
|
||||||
data.append(element);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Normal data type
|
|
||||||
int length = ZigbeeDataType::typeLength(dataType);
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse (normal data type)" << "Number of elements:" << length;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
quint8 element = 0;
|
|
||||||
stream >> element;
|
|
||||||
data.append(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadAttributeStatusRecord attributeRecord;
|
ReadAttributeStatusRecord attributeRecord;
|
||||||
attributeRecord.attributeId = attributeId;
|
attributeRecord.attributeId = attributeId;
|
||||||
attributeRecord.attributeStatus = status;
|
attributeRecord.attributeStatus = status;
|
||||||
attributeRecord.dataType = dataType;
|
attributeRecord.dataType = type;
|
||||||
attributeRecord.data = data;
|
|
||||||
qCDebug(dcZigbeeClusterLibrary()) << attributeRecord;
|
qCDebug(dcZigbeeClusterLibrary()) << attributeRecord;
|
||||||
attributeStatusRecords.append(attributeRecord);
|
attributeStatusRecords.append(attributeRecord);
|
||||||
}
|
}
|
||||||
@ -200,6 +141,82 @@ QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> ZigbeeClusterLibrary::par
|
|||||||
return attributeStatusRecords;
|
return attributeStatusRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeDataType ZigbeeClusterLibrary::readDataType(QDataStream *stream, Zigbee::DataType dataType)
|
||||||
|
{
|
||||||
|
|
||||||
|
QByteArray data; quint16 numberOfElenemts = 0; quint8 elementType = 0;
|
||||||
|
QDataStream dataStream(&data, QIODevice::WriteOnly);
|
||||||
|
dataStream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
|
// Parse data depending on the type
|
||||||
|
if (dataType == Zigbee::Array || dataType == Zigbee::Set || dataType == Zigbee::Bag) {
|
||||||
|
*stream >> elementType >> numberOfElenemts;
|
||||||
|
dataStream << elementType << numberOfElenemts;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (array, set, bag): Element type" << ZigbeeUtils::convertByteToHexString(elementType) << "Number of elements:" << numberOfElenemts;
|
||||||
|
if (numberOfElenemts == 0xffff) {
|
||||||
|
qCWarning(dcZigbeeClusterLibrary()) << "ZigbeeStatusRecord contains invalid data elements" << dataType;
|
||||||
|
return ZigbeeDataType(dataType);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < numberOfElenemts; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
*stream >> element;
|
||||||
|
dataStream << element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dataType == Zigbee::Structure) {
|
||||||
|
*stream >> numberOfElenemts;
|
||||||
|
dataStream << numberOfElenemts;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Number of elements:" << numberOfElenemts;
|
||||||
|
if (numberOfElenemts == 0xffff) {
|
||||||
|
qCWarning(dcZigbeeClusterLibrary()) << "ZigbeeStatusRecord contains invalid data elements" << dataType;
|
||||||
|
return ZigbeeDataType(dataType);
|
||||||
|
} else {
|
||||||
|
*stream >> elementType;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Element type:" << ZigbeeUtils::convertByteToHexString(elementType);
|
||||||
|
for (int i = 0; i < numberOfElenemts; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
*stream >> element;
|
||||||
|
//qCDebug(dcZigbeeClusterLibrary()) << "Parse (structure)" << "Element value:" << ZigbeeUtils::convertByteToHexString(element);
|
||||||
|
dataStream << element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dataType == Zigbee::OctetString || dataType == Zigbee::CharString) {
|
||||||
|
quint8 length = 0;
|
||||||
|
*stream >> length;
|
||||||
|
dataStream << length;
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (octet string, character string)" << "Length:" << length;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
*stream >> element;
|
||||||
|
dataStream << element;
|
||||||
|
}
|
||||||
|
} else if (dataType == Zigbee::LongOctetString || dataType == Zigbee::LongCharString) {
|
||||||
|
quint16 length = 0;
|
||||||
|
*stream >> length;
|
||||||
|
dataStream << length;
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (long octet string, long character string)" << "Length:" << length;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
*stream >> element;
|
||||||
|
data.append(element);
|
||||||
|
dataStream << element;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal data type
|
||||||
|
int length = ZigbeeDataType::typeLength(dataType);
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parse (normal data type)" << "Number of elements:" << length;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
quint8 element = 0;
|
||||||
|
*stream >> element;
|
||||||
|
dataStream << element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeClusterLibrary()) << "Parsed data:" << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||||
|
return ZigbeeDataType(dataType, data);
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArray &frameData)
|
ZigbeeClusterLibrary::Frame ZigbeeClusterLibrary::parseFrameData(const QByteArray &frameData)
|
||||||
{
|
{
|
||||||
QDataStream stream(frameData);
|
QDataStream stream(frameData);
|
||||||
@ -281,12 +298,11 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame)
|
|||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::ReadAttributeStatusRecord &attributeStatusRecord)
|
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::ReadAttributeStatusRecord &attributeStatusRecord)
|
||||||
{
|
{
|
||||||
debug.nospace().noquote() << "ReadAttributeStatusRecord("
|
debug.nospace() << "ReadAttributeStatusRecord("
|
||||||
<< ZigbeeUtils::convertUint16ToHexString(attributeStatusRecord.attributeId) << ", "
|
<< ZigbeeUtils::convertUint16ToHexString(attributeStatusRecord.attributeId) << ", "
|
||||||
<< attributeStatusRecord.attributeStatus << ", "
|
<< attributeStatusRecord.attributeStatus << ", "
|
||||||
<< attributeStatusRecord.dataType << ", "
|
<< attributeStatusRecord.dataType
|
||||||
<< attributeStatusRecord.data
|
<< ")";
|
||||||
<< ")";
|
|
||||||
|
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
|
#include "zigbeedatatype.h"
|
||||||
|
|
||||||
class ZigbeeClusterLibrary
|
class ZigbeeClusterLibrary
|
||||||
{
|
{
|
||||||
@ -101,7 +102,7 @@ public:
|
|||||||
FrameControl frameControl;
|
FrameControl frameControl;
|
||||||
quint16 manufacturerCode = 0;
|
quint16 manufacturerCode = 0;
|
||||||
quint8 transactionSequenceNumber = 0;
|
quint8 transactionSequenceNumber = 0;
|
||||||
Command command;
|
quint8 command;
|
||||||
} ZclHeader;
|
} ZclHeader;
|
||||||
|
|
||||||
typedef struct Frame {
|
typedef struct Frame {
|
||||||
@ -114,8 +115,7 @@ public:
|
|||||||
typedef struct ReadAttributeStatusRecord {
|
typedef struct ReadAttributeStatusRecord {
|
||||||
quint16 attributeId;
|
quint16 attributeId;
|
||||||
Zigbee::ZigbeeStatus attributeStatus;
|
Zigbee::ZigbeeStatus attributeStatus;
|
||||||
Zigbee::DataType dataType;
|
ZigbeeDataType dataType;
|
||||||
QByteArray data;
|
|
||||||
} ReadAttributeStatusRecord;
|
} ReadAttributeStatusRecord;
|
||||||
|
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ public:
|
|||||||
static QList<ReadAttributeStatusRecord> parseAttributeStatusRecords(const QByteArray &payload);
|
static QList<ReadAttributeStatusRecord> parseAttributeStatusRecords(const QByteArray &payload);
|
||||||
|
|
||||||
//static QByteArray readAttributeData(const QDataStream &stream, Zigbee::DataType dataType);
|
//static QByteArray readAttributeData(const QDataStream &stream, Zigbee::DataType dataType);
|
||||||
|
static ZigbeeDataType readDataType(QDataStream *stream, Zigbee::DataType dataType);
|
||||||
|
|
||||||
static Frame parseFrameData(const QByteArray &frameData);
|
static Frame parseFrameData(const QByteArray &frameData);
|
||||||
static QByteArray buildFrame(const Frame &frame);
|
static QByteArray buildFrame(const Frame &frame);
|
||||||
|
|||||||
@ -1,3 +1,30 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 "zigbeeclusterreply.h"
|
#include "zigbeeclusterreply.h"
|
||||||
|
|
||||||
ZigbeeClusterReply::Error ZigbeeClusterReply::error() const
|
ZigbeeClusterReply::Error ZigbeeClusterReply::error() const
|
||||||
|
|||||||
@ -1,3 +1,30 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 ZIGBEECLUSTERREPLY_H
|
#ifndef ZIGBEECLUSTERREPLY_H
|
||||||
#define ZIGBEECLUSTERREPLY_H
|
#define ZIGBEECLUSTERREPLY_H
|
||||||
|
|
||||||
|
|||||||
@ -356,5 +356,5 @@ void ZigbeeDeviceObject::processApsDataIndication(quint8 destinationEndpoint, qu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCWarning(dcZigbeeDeviceObject()) << m_node << "unhandled ZDO indication";
|
qCWarning(dcZigbeeDeviceObject()) << "Unhandled ZDO indication" << m_node << asdu;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,46 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 "zigbeedatatype.h"
|
#include "zigbeedatatype.h"
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
|
||||||
|
ZigbeeDataType::ZigbeeDataType()
|
||||||
|
{
|
||||||
|
setDataType(Zigbee::NoData);
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeDataType::ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data):
|
ZigbeeDataType::ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data):
|
||||||
m_data(data)
|
m_data(data)
|
||||||
{
|
{
|
||||||
setDataType(dataType);
|
setDataType(dataType);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: verify data length and consistency
|
// TODO: verify data length and consistency
|
||||||
|
|
||||||
|
|
||||||
@ -414,6 +444,12 @@ int ZigbeeDataType::dataLength() const
|
|||||||
return typeLength(m_dataType);
|
return typeLength(m_dataType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ZigbeeDataType::isValid() const
|
||||||
|
{
|
||||||
|
// FIXME: implement validate data depending on the type
|
||||||
|
return m_dataType != Zigbee::NoData && !m_data.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
int ZigbeeDataType::typeLength(Zigbee::DataType dataType)
|
int ZigbeeDataType::typeLength(Zigbee::DataType dataType)
|
||||||
{
|
{
|
||||||
int length = 0;
|
int length = 0;
|
||||||
@ -597,6 +633,23 @@ int ZigbeeDataType::typeLength(Zigbee::DataType dataType)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeDataType &ZigbeeDataType::operator=(const ZigbeeDataType &other)
|
||||||
|
{
|
||||||
|
setDataType(other.dataType());
|
||||||
|
m_data = other.data();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeDataType::operator==(const ZigbeeDataType &other) const
|
||||||
|
{
|
||||||
|
return m_dataType == other.dataType() && m_data == other.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZigbeeDataType::operator!=(const ZigbeeDataType &other) const
|
||||||
|
{
|
||||||
|
return !operator==(other);
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeDataType::setDataType(Zigbee::DataType dataType)
|
void ZigbeeDataType::setDataType(Zigbee::DataType dataType)
|
||||||
{
|
{
|
||||||
m_dataType = dataType;
|
m_dataType = dataType;
|
||||||
@ -885,6 +938,7 @@ void ZigbeeDataType::setDataType(Zigbee::DataType dataType)
|
|||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeDataType &dataType)
|
QDebug operator<<(QDebug debug, const ZigbeeDataType &dataType)
|
||||||
{
|
{
|
||||||
|
// FIXME: print data depending on the datatype
|
||||||
debug.nospace() << "ZigbeeDataType(" << dataType.name();
|
debug.nospace() << "ZigbeeDataType(" << dataType.name();
|
||||||
debug.nospace() << ", " << ZigbeeUtils::convertByteArrayToHexString(dataType.data());
|
debug.nospace() << ", " << ZigbeeUtils::convertByteArrayToHexString(dataType.data());
|
||||||
debug.nospace() << ")";
|
debug.nospace() << ")";
|
||||||
|
|||||||
@ -1,3 +1,30 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 ZIGBEEDATATYPE_H
|
#ifndef ZIGBEEDATATYPE_H
|
||||||
#define ZIGBEEDATATYPE_H
|
#define ZIGBEEDATATYPE_H
|
||||||
|
|
||||||
@ -7,6 +34,7 @@
|
|||||||
class ZigbeeDataType
|
class ZigbeeDataType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ZigbeeDataType();
|
||||||
ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data = QByteArray());
|
ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data = QByteArray());
|
||||||
|
|
||||||
ZigbeeDataType(quint8 value, Zigbee::DataType dataType = Zigbee::Uint8);
|
ZigbeeDataType(quint8 value, Zigbee::DataType dataType = Zigbee::Uint8);
|
||||||
@ -32,8 +60,14 @@ public:
|
|||||||
QByteArray data() const;
|
QByteArray data() const;
|
||||||
int dataLength() const;
|
int dataLength() const;
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
static int typeLength(Zigbee::DataType dataType);
|
static int typeLength(Zigbee::DataType dataType);
|
||||||
|
|
||||||
|
ZigbeeDataType &operator=(const ZigbeeDataType &other);
|
||||||
|
bool operator==(const ZigbeeDataType &other) const;
|
||||||
|
bool operator!=(const ZigbeeDataType &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Zigbee::DataType m_dataType = Zigbee::NoData;
|
Zigbee::DataType m_dataType = Zigbee::NoData;
|
||||||
QByteArray m_data;
|
QByteArray m_data;
|
||||||
|
|||||||
@ -671,9 +671,16 @@ void ZigbeeNode::initBasicCluster()
|
|||||||
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
||||||
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
||||||
if (!attributeStatusRecords.isEmpty()) {
|
if (!attributeStatusRecords.isEmpty()) {
|
||||||
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
|
||||||
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
|
||||||
m_endpoints.first()->m_manufacturerName = QString::fromUtf8(attributeStatusRecords.first().data);
|
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
|
||||||
|
bool valueOk = false;
|
||||||
|
QString manufacturerName = attributeStatusRecord.dataType.toString(&valueOk);
|
||||||
|
if (valueOk) {
|
||||||
|
m_endpoints.first()->m_manufacturerName = manufacturerName;
|
||||||
|
} else {
|
||||||
|
qCWarning(dcZigbeeNode()) << "Could not convert manufacturer name attribute data to string" << attributeStatusRecord.dataType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,13 +694,19 @@ void ZigbeeNode::initBasicCluster()
|
|||||||
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
||||||
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
||||||
if (!attributeStatusRecords.isEmpty()) {
|
if (!attributeStatusRecords.isEmpty()) {
|
||||||
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
|
||||||
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
|
||||||
m_endpoints.first()->m_modelIdentifier = QString::fromUtf8(attributeStatusRecords.first().data);
|
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
|
||||||
|
bool valueOk = false;
|
||||||
|
QString modelIdentifier = attributeStatusRecord.dataType.toString(&valueOk);
|
||||||
|
if (valueOk) {
|
||||||
|
m_endpoints.first()->m_modelIdentifier = modelIdentifier;
|
||||||
|
} else {
|
||||||
|
qCWarning(dcZigbeeNode()) << "Could not convert model identifier attribute data to string" << attributeStatusRecord.dataType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZigbeeClusterBasic::Attribute attributeId = ZigbeeClusterBasic::AttributeSwBuildId;
|
ZigbeeClusterBasic::Attribute attributeId = ZigbeeClusterBasic::AttributeSwBuildId;
|
||||||
qCDebug(dcZigbeeNode()) << "Reading attribute" << attributeId;
|
qCDebug(dcZigbeeNode()) << "Reading attribute" << attributeId;
|
||||||
ZigbeeClusterReply *reply = basicCluster->readAttributes({static_cast<quint16>(attributeId)});
|
ZigbeeClusterReply *reply = basicCluster->readAttributes({static_cast<quint16>(attributeId)});
|
||||||
@ -704,9 +717,16 @@ void ZigbeeNode::initBasicCluster()
|
|||||||
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
||||||
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
||||||
if (!attributeStatusRecords.isEmpty()) {
|
if (!attributeStatusRecords.isEmpty()) {
|
||||||
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
|
||||||
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
|
||||||
m_endpoints.first()->m_softwareBuildId = QString::fromUtf8(attributeStatusRecords.first().data);
|
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecord.dataType));
|
||||||
|
bool valueOk = false;
|
||||||
|
QString softwareBuildId = attributeStatusRecord.dataType.toString(&valueOk);
|
||||||
|
if (valueOk) {
|
||||||
|
m_endpoints.first()->m_softwareBuildId = softwareBuildId;
|
||||||
|
} else {
|
||||||
|
qCWarning(dcZigbeeNode()) << "Could not convert software build id attribute data to string" << attributeStatusRecord.dataType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,7 +735,6 @@ void ZigbeeNode::initBasicCluster()
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribute)
|
||||||
|
|||||||
@ -154,6 +154,9 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(Zigbee::ClusterId clusterId, Zi
|
|||||||
case Zigbee::ClusterIdBasic:
|
case Zigbee::ClusterIdBasic:
|
||||||
return new ZigbeeClusterBasic(m_network, m_node, this, direction, this);
|
return new ZigbeeClusterBasic(m_network, m_node, this, direction, this);
|
||||||
break;
|
break;
|
||||||
|
case Zigbee::ClusterIdOnOff:
|
||||||
|
return new ZigbeeClusterOnOff(m_network, m_node, this, direction, this);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return new ZigbeeCluster(m_network, m_node, this, clusterId, direction, this);
|
return new ZigbeeCluster(m_network, m_node, this, clusterId, direction, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "zcl/zigbeecluster.h"
|
#include "zcl/zigbeecluster.h"
|
||||||
#include "zcl/general/zigbeeclusterbasic.h"
|
#include "zcl/general/zigbeeclusterbasic.h"
|
||||||
|
#include "zcl/general/zigbeeclusteronoff.h"
|
||||||
|
|
||||||
class ZigbeeNode;
|
class ZigbeeNode;
|
||||||
class ZigbeeNetwork;
|
class ZigbeeNetwork;
|
||||||
|
|||||||
Reference in New Issue
Block a user