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)));
|
||||
|
||||
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();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ SOURCES += \
|
||||
backends/deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
||||
backends/deconz/zigbeebridgecontrollerdeconz.cpp \
|
||||
backends/deconz/zigbeenetworkdeconz.cpp \
|
||||
zcl/general/zigbeeclusteronoff.cpp \
|
||||
zcl/zigbeecluster.cpp \
|
||||
zcl/zigbeeclusterattribute.cpp \
|
||||
zcl/zigbeeclusterlibrary.cpp \
|
||||
@ -49,6 +50,7 @@ HEADERS += \
|
||||
backends/deconz/interface/zigbeeinterfacedeconzreply.h \
|
||||
backends/deconz/zigbeebridgecontrollerdeconz.h \
|
||||
backends/deconz/zigbeenetworkdeconz.h \
|
||||
zcl/general/zigbeeclusteronoff.h \
|
||||
zcl/zigbeecluster.h \
|
||||
zcl/zigbeeclusterattribute.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 "loggingcategory.h"
|
||||
|
||||
@ -10,11 +37,11 @@ ZigbeeClusterBasic::ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node,
|
||||
void ZigbeeClusterBasic::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
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;
|
||||
emit attributeChanged(attribute);
|
||||
} 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);
|
||||
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
|
||||
#define ZIGBEECLUSTERBASIC_H
|
||||
|
||||
@ -172,13 +199,9 @@ public:
|
||||
|
||||
explicit ZigbeeClusterBasic(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
if (hasAttribute(attribute.id())) {
|
||||
qCDebug(dcZigbeeCluster()) << this << "update attribute" << attribute;
|
||||
qCDebug(dcZigbeeCluster()) << "Update attribute" << this << attribute;
|
||||
m_attributes[attribute.id()] = attribute;
|
||||
emit attributeChanged(attribute);
|
||||
} else {
|
||||
qCDebug(dcZigbeeCluster()) << this << "add attribute" << attribute;
|
||||
qCDebug(dcZigbeeCluster()) << "Add attribute" << this << attribute;
|
||||
m_attributes.insert(attribute.id(), attribute);
|
||||
emit attributeChanged(attribute);
|
||||
}
|
||||
@ -94,7 +94,7 @@ void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
|
||||
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
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
@ -139,7 +139,7 @@ ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< m_node << m_endpoint << this << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
@ -211,14 +211,23 @@ bool ZigbeeCluster::verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetwo
|
||||
void ZigbeeCluster::finishZclReply(ZigbeeClusterReply *zclReply)
|
||||
{
|
||||
m_pendingReplies.remove(zclReply->transactionSequenceNumber());
|
||||
qCDebug(dcZigbeeCluster()) << "ZigbeeClusterReply finished" << zclReply->request() << zclReply->requestFrame() << zclReply->responseFrame();
|
||||
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)
|
||||
{
|
||||
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)) {
|
||||
ZigbeeClusterReply *reply = m_pendingReplies.value(frame.header.transactionSequenceNumber);
|
||||
reply->m_responseData = payload;
|
||||
@ -231,8 +240,8 @@ void ZigbeeCluster::processApsDataIndication(QByteArray payload)
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: increase transaction sequence number
|
||||
qCWarning(dcZigbeeNode()) << m_node << m_endpoint << this << "Unhandled ZCL indication" << ZigbeeUtils::convertByteArrayToHexString(payload);
|
||||
// Not for a reply, process the indication
|
||||
processDataIndication(frame);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
||||
@ -252,7 +261,7 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeRep
|
||||
<< attributeReport.attributeId << ", "
|
||||
<< attributeReport.attributeStatus << ", "
|
||||
<< attributeReport.dataType << ", "
|
||||
<< attributeReport.data << ", "
|
||||
<< ZigbeeUtils::convertByteArrayToHexString(attributeReport.data)
|
||||
<< ")";
|
||||
|
||||
return debug.space();
|
||||
|
||||
@ -89,23 +89,6 @@ public:
|
||||
// };
|
||||
// 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
|
||||
|
||||
@ -195,6 +178,8 @@ protected:
|
||||
bool verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply);
|
||||
void finishZclReply(ZigbeeClusterReply *zclReply);
|
||||
|
||||
virtual void processDataIndication(ZigbeeClusterLibrary::Frame frame);
|
||||
|
||||
private:
|
||||
virtual void setAttribute(const ZigbeeClusterAttribute &attribute);
|
||||
|
||||
@ -204,7 +189,6 @@ signals:
|
||||
public slots:
|
||||
void processApsDataIndication(QByteArray payload);
|
||||
|
||||
|
||||
};
|
||||
|
||||
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_dataType(dataType),
|
||||
m_data(data)
|
||||
m_dataType(dataType)
|
||||
{
|
||||
|
||||
}
|
||||
@ -45,7 +44,6 @@ ZigbeeClusterAttribute::ZigbeeClusterAttribute(const ZigbeeClusterAttribute &oth
|
||||
{
|
||||
m_id = other.id();
|
||||
m_dataType = other.dataType();
|
||||
m_data = other.data();
|
||||
}
|
||||
|
||||
quint16 ZigbeeClusterAttribute::id() const
|
||||
@ -53,29 +51,21 @@ quint16 ZigbeeClusterAttribute::id() const
|
||||
return m_id;
|
||||
}
|
||||
|
||||
Zigbee::DataType ZigbeeClusterAttribute::dataType() const
|
||||
ZigbeeDataType ZigbeeClusterAttribute::dataType() const
|
||||
{
|
||||
return m_dataType;
|
||||
}
|
||||
|
||||
QByteArray ZigbeeClusterAttribute::data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
ZigbeeClusterAttribute &ZigbeeClusterAttribute::operator=(const ZigbeeClusterAttribute &other)
|
||||
{
|
||||
m_id = other.id();
|
||||
m_dataType = other.dataType();
|
||||
m_data = other.data();
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ZigbeeClusterAttribute::operator==(const ZigbeeClusterAttribute &other) const
|
||||
{
|
||||
return m_id == other.id() &&
|
||||
m_dataType == other.dataType() &&
|
||||
m_data == other.data();
|
||||
return m_id == other.id() && m_dataType == other.dataType();
|
||||
}
|
||||
|
||||
bool ZigbeeClusterAttribute::operator!=(const ZigbeeClusterAttribute &other) const
|
||||
@ -85,16 +75,14 @@ bool ZigbeeClusterAttribute::operator!=(const ZigbeeClusterAttribute &other) con
|
||||
|
||||
bool ZigbeeClusterAttribute::isValid() const
|
||||
{
|
||||
return m_id != 0 ||
|
||||
m_dataType != Zigbee::NoData ||
|
||||
!m_data.isNull();
|
||||
return m_id != 0xffff && m_dataType.isValid();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
debug.nospace().noquote() << "ZigbeeClusterAttribute("
|
||||
<< ZigbeeUtils::convertUint16ToHexString(attribute.id()) << ", "
|
||||
<< attribute.dataType() << ", "
|
||||
<< ZigbeeUtils::convertByteArrayToHexString(attribute.data()) << ")";
|
||||
<< attribute.dataType()
|
||||
<< ")";
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
@ -31,17 +31,17 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeedatatype.h"
|
||||
|
||||
class ZigbeeClusterAttribute
|
||||
{
|
||||
public:
|
||||
ZigbeeClusterAttribute();
|
||||
ZigbeeClusterAttribute(quint16 id, Zigbee::DataType dataType, QByteArray data);
|
||||
ZigbeeClusterAttribute(quint16 id, const ZigbeeDataType &dataType);
|
||||
ZigbeeClusterAttribute(const ZigbeeClusterAttribute &other);
|
||||
|
||||
quint16 id() const;
|
||||
Zigbee::DataType dataType() const;
|
||||
QByteArray data() const;
|
||||
ZigbeeDataType dataType() const;
|
||||
|
||||
ZigbeeClusterAttribute &operator=(const ZigbeeClusterAttribute &other);
|
||||
bool operator==(const ZigbeeClusterAttribute &other) const;
|
||||
@ -50,9 +50,8 @@ public:
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
quint16 m_id = 0;
|
||||
Zigbee::DataType m_dataType = Zigbee::NoData;
|
||||
QByteArray m_data;
|
||||
quint16 m_id = 0xffff;
|
||||
ZigbeeDataType m_dataType;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeClusterAttribute &attribute);
|
||||
|
||||
@ -104,13 +104,11 @@ QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> ZigbeeClusterLibrary::par
|
||||
|
||||
QDataStream stream(payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint16 attributeId; quint8 statusInt; quint8 dataTypeInt; quint16 numberOfElenemts; quint8 elementType;
|
||||
QByteArray data;
|
||||
quint16 attributeId; quint8 statusInt; quint8 dataTypeInt;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
// Reset variables
|
||||
attributeId = 0; statusInt = 0; dataTypeInt = 0; numberOfElenemts = 0; elementType = 0;
|
||||
data.clear();
|
||||
attributeId = 0; statusInt = 0; dataTypeInt = 0;
|
||||
|
||||
// Read attribute id and status
|
||||
stream >> attributeId >> statusInt;
|
||||
@ -126,72 +124,15 @@ QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> ZigbeeClusterLibrary::par
|
||||
stream >> dataTypeInt;
|
||||
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(dataTypeInt);
|
||||
|
||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse:" << dataType;
|
||||
|
||||
// Parse data depending on the type
|
||||
if (dataType == Zigbee::Array || dataType == Zigbee::Set || dataType == Zigbee::Bag) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
qCDebug(dcZigbeeClusterLibrary()) << "Parse data type:" << dataType;
|
||||
ZigbeeDataType type = readDataType(&stream, dataType);
|
||||
if (!type.isValid())
|
||||
continue;
|
||||
|
||||
ReadAttributeStatusRecord attributeRecord;
|
||||
attributeRecord.attributeId = attributeId;
|
||||
attributeRecord.attributeStatus = status;
|
||||
attributeRecord.dataType = dataType;
|
||||
attributeRecord.data = data;
|
||||
attributeRecord.dataType = type;
|
||||
qCDebug(dcZigbeeClusterLibrary()) << attributeRecord;
|
||||
attributeStatusRecords.append(attributeRecord);
|
||||
}
|
||||
@ -200,6 +141,82 @@ QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> ZigbeeClusterLibrary::par
|
||||
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)
|
||||
{
|
||||
QDataStream stream(frameData);
|
||||
@ -281,12 +298,11 @@ QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::Frame &frame)
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeClusterLibrary::ReadAttributeStatusRecord &attributeStatusRecord)
|
||||
{
|
||||
debug.nospace().noquote() << "ReadAttributeStatusRecord("
|
||||
<< ZigbeeUtils::convertUint16ToHexString(attributeStatusRecord.attributeId) << ", "
|
||||
<< attributeStatusRecord.attributeStatus << ", "
|
||||
<< attributeStatusRecord.dataType << ", "
|
||||
<< attributeStatusRecord.data
|
||||
<< ")";
|
||||
debug.nospace() << "ReadAttributeStatusRecord("
|
||||
<< ZigbeeUtils::convertUint16ToHexString(attributeStatusRecord.attributeId) << ", "
|
||||
<< attributeStatusRecord.attributeStatus << ", "
|
||||
<< attributeStatusRecord.dataType
|
||||
<< ")";
|
||||
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeedatatype.h"
|
||||
|
||||
class ZigbeeClusterLibrary
|
||||
{
|
||||
@ -101,7 +102,7 @@ public:
|
||||
FrameControl frameControl;
|
||||
quint16 manufacturerCode = 0;
|
||||
quint8 transactionSequenceNumber = 0;
|
||||
Command command;
|
||||
quint8 command;
|
||||
} ZclHeader;
|
||||
|
||||
typedef struct Frame {
|
||||
@ -114,8 +115,7 @@ public:
|
||||
typedef struct ReadAttributeStatusRecord {
|
||||
quint16 attributeId;
|
||||
Zigbee::ZigbeeStatus attributeStatus;
|
||||
Zigbee::DataType dataType;
|
||||
QByteArray data;
|
||||
ZigbeeDataType dataType;
|
||||
} ReadAttributeStatusRecord;
|
||||
|
||||
|
||||
@ -128,7 +128,7 @@ public:
|
||||
static QList<ReadAttributeStatusRecord> parseAttributeStatusRecords(const QByteArray &payload);
|
||||
|
||||
//static QByteArray readAttributeData(const QDataStream &stream, Zigbee::DataType dataType);
|
||||
|
||||
static ZigbeeDataType readDataType(QDataStream *stream, Zigbee::DataType dataType);
|
||||
|
||||
static Frame parseFrameData(const QByteArray &frameData);
|
||||
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"
|
||||
|
||||
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
|
||||
#define ZIGBEECLUSTERREPLY_H
|
||||
|
||||
|
||||
@ -356,5 +356,5 @@ void ZigbeeDeviceObject::processApsDataIndication(quint8 destinationEndpoint, qu
|
||||
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 "zigbeeutils.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeDataType::ZigbeeDataType()
|
||||
{
|
||||
setDataType(Zigbee::NoData);
|
||||
}
|
||||
|
||||
ZigbeeDataType::ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data):
|
||||
m_data(data)
|
||||
{
|
||||
setDataType(dataType);
|
||||
|
||||
|
||||
|
||||
// TODO: verify data length and consistency
|
||||
|
||||
|
||||
@ -414,6 +444,12 @@ int ZigbeeDataType::dataLength() const
|
||||
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 length = 0;
|
||||
@ -597,6 +633,23 @@ int ZigbeeDataType::typeLength(Zigbee::DataType dataType)
|
||||
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)
|
||||
{
|
||||
m_dataType = dataType;
|
||||
@ -885,6 +938,7 @@ void ZigbeeDataType::setDataType(Zigbee::DataType dataType)
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDataType &dataType)
|
||||
{
|
||||
// FIXME: print data depending on the datatype
|
||||
debug.nospace() << "ZigbeeDataType(" << dataType.name();
|
||||
debug.nospace() << ", " << ZigbeeUtils::convertByteArrayToHexString(dataType.data());
|
||||
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
|
||||
#define ZIGBEEDATATYPE_H
|
||||
|
||||
@ -7,6 +34,7 @@
|
||||
class ZigbeeDataType
|
||||
{
|
||||
public:
|
||||
ZigbeeDataType();
|
||||
ZigbeeDataType(Zigbee::DataType dataType, const QByteArray &data = QByteArray());
|
||||
|
||||
ZigbeeDataType(quint8 value, Zigbee::DataType dataType = Zigbee::Uint8);
|
||||
@ -32,8 +60,14 @@ public:
|
||||
QByteArray data() const;
|
||||
int dataLength() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
static int typeLength(Zigbee::DataType dataType);
|
||||
|
||||
ZigbeeDataType &operator=(const ZigbeeDataType &other);
|
||||
bool operator==(const ZigbeeDataType &other) const;
|
||||
bool operator!=(const ZigbeeDataType &other) const;
|
||||
|
||||
private:
|
||||
Zigbee::DataType m_dataType = Zigbee::NoData;
|
||||
QByteArray m_data;
|
||||
|
||||
@ -671,9 +671,16 @@ void ZigbeeNode::initBasicCluster()
|
||||
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
||||
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
||||
if (!attributeStatusRecords.isEmpty()) {
|
||||
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
||||
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
||||
m_endpoints.first()->m_manufacturerName = QString::fromUtf8(attributeStatusRecords.first().data);
|
||||
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
|
||||
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
|
||||
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";
|
||||
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
||||
if (!attributeStatusRecords.isEmpty()) {
|
||||
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
||||
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
||||
m_endpoints.first()->m_modelIdentifier = QString::fromUtf8(attributeStatusRecords.first().data);
|
||||
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
|
||||
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
|
||||
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;
|
||||
qCDebug(dcZigbeeNode()) << "Reading attribute" << attributeId;
|
||||
ZigbeeClusterReply *reply = basicCluster->readAttributes({static_cast<quint16>(attributeId)});
|
||||
@ -704,9 +717,16 @@ void ZigbeeNode::initBasicCluster()
|
||||
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully";
|
||||
QList<ZigbeeClusterLibrary::ReadAttributeStatusRecord> attributeStatusRecords = ZigbeeClusterLibrary::parseAttributeStatusRecords(reply->responseFrame().payload);
|
||||
if (!attributeStatusRecords.isEmpty()) {
|
||||
qCDebug(dcZigbeeNode()) << attributeStatusRecords.first();
|
||||
basicCluster->setAttribute(ZigbeeClusterAttribute(static_cast<quint16>(attributeId), attributeStatusRecords.first().dataType, attributeStatusRecords.first().data));
|
||||
m_endpoints.first()->m_softwareBuildId = QString::fromUtf8(attributeStatusRecords.first().data);
|
||||
ZigbeeClusterLibrary::ReadAttributeStatusRecord attributeStatusRecord = attributeStatusRecords.first();
|
||||
qCDebug(dcZigbeeNode()) << attributeStatusRecord;
|
||||
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)
|
||||
|
||||
@ -154,6 +154,9 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(Zigbee::ClusterId clusterId, Zi
|
||||
case Zigbee::ClusterIdBasic:
|
||||
return new ZigbeeClusterBasic(m_network, m_node, this, direction, this);
|
||||
break;
|
||||
case Zigbee::ClusterIdOnOff:
|
||||
return new ZigbeeClusterOnOff(m_network, m_node, this, direction, this);
|
||||
break;
|
||||
default:
|
||||
return new ZigbeeCluster(m_network, m_node, this, clusterId, direction, this);
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
|
||||
#include "zcl/zigbeecluster.h"
|
||||
#include "zcl/general/zigbeeclusterbasic.h"
|
||||
#include "zcl/general/zigbeeclusteronoff.h"
|
||||
|
||||
class ZigbeeNode;
|
||||
class ZigbeeNetwork;
|
||||
|
||||
Reference in New Issue
Block a user