Merge PR #65: Complete the OTA cluster implementation
commit
bbbbbbc521
|
|
@ -48,7 +48,6 @@ ZigbeeClusterPowerConfiguration::BatteryAlarmMask ZigbeeClusterPowerConfiguratio
|
||||||
|
|
||||||
void ZigbeeClusterPowerConfiguration::setAttribute(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeClusterPowerConfiguration::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
|
||||||
ZigbeeCluster::setAttribute(attribute);
|
ZigbeeCluster::setAttribute(attribute);
|
||||||
|
|
||||||
if (attribute.id() == AttributeBatteryPercentageRemaining) {
|
if (attribute.id() == AttributeBatteryPercentageRemaining) {
|
||||||
|
|
|
||||||
|
|
@ -39,19 +39,156 @@ ZigbeeClusterOta::ZigbeeClusterOta(ZigbeeNetwork *network, ZigbeeNode *node, Zig
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOta::sendImageNotify(PayloadType payloadType, quint8 queryJitter, quint16 manufacturerCode, quint16 imageType, quint32 newFileVersion)
|
||||||
|
{
|
||||||
|
if (queryJitter > 100) {
|
||||||
|
queryJitter = 100;
|
||||||
|
}
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << static_cast<quint8>(payloadType);
|
||||||
|
stream << queryJitter;
|
||||||
|
if (payloadType >= PayloadTypeQueryJitterAndManufacturerCode) {
|
||||||
|
stream << manufacturerCode;
|
||||||
|
}
|
||||||
|
if (payloadType >= PayloadTypeQueryJitterAndManufacturerCodeAndImageType) {
|
||||||
|
stream << imageType;
|
||||||
|
}
|
||||||
|
if (payloadType >= PayloadTypeQueryJitterAndManufacturerCodeAndImageTypeAndNewFileVersion) {
|
||||||
|
stream << newFileVersion;
|
||||||
|
}
|
||||||
|
ZigbeeClusterReply *reply = executeClusterCommand(CommandImageNotify, payload, ZigbeeClusterLibrary::DirectionServerToClient);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOta::sendQueryNextImageResponse(quint8 transactionSequenceNumber, StatusCode statusCode, quint16 manufacturerCode, quint16 imageType, quint32 fileVersion, quint32 imageSize)
|
||||||
|
{
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << static_cast<quint8>(statusCode);
|
||||||
|
if (statusCode == StatusCodeSuccess) {
|
||||||
|
stream << manufacturerCode;
|
||||||
|
stream << imageType;
|
||||||
|
stream << fileVersion;
|
||||||
|
stream << imageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *reply = sendClusterServerResponse(CommandQueryNextImageResponse, transactionSequenceNumber, payload);
|
||||||
|
connect(reply, &ZigbeeClusterReply::finished, this, [reply](){
|
||||||
|
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "OTA: Error sending query next image response:" << reply->error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(dcZigbeeCluster()) << "OTA: Query image response sent successfully.";
|
||||||
|
});
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOta::sendImageBlockResponse(quint8 transactionSequenceNumber, quint16 manufacturerCode, quint16 imageType, quint32 fileVersion, quint32 fileOffset, const QByteArray &imageData)
|
||||||
|
{
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << static_cast<quint8>(StatusCodeSuccess);
|
||||||
|
stream << manufacturerCode;
|
||||||
|
stream << imageType;
|
||||||
|
stream << fileVersion;
|
||||||
|
stream << fileOffset;
|
||||||
|
stream << static_cast<quint8>(imageData.length());
|
||||||
|
stream.writeRawData(imageData.data(), imageData.length());
|
||||||
|
|
||||||
|
ZigbeeClusterReply *reply = sendClusterServerResponse(CommandImageBlockResponse, transactionSequenceNumber, payload);
|
||||||
|
connect(reply, &ZigbeeClusterReply::finished, this, [reply](){
|
||||||
|
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "OTA: Error sending image block response:" << reply->error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(dcZigbeeCluster()) << "OTA: Image block response sent successfully.";
|
||||||
|
});
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOta::sendAbortImageBlockResponse(quint8 transactionSequenceNumber)
|
||||||
|
{
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << static_cast<quint8>(StatusCodeAbort);
|
||||||
|
ZigbeeClusterReply *reply = sendClusterServerResponse(CommandImageBlockResponse, transactionSequenceNumber, payload);
|
||||||
|
connect(reply, &ZigbeeClusterReply::finished, this, [reply](){
|
||||||
|
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "OTA: Error sending abort image block response:" << reply->error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(dcZigbeeCluster()) << "OTA: Abort image block response sent successfully.";
|
||||||
|
});
|
||||||
|
return reply;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOta::sendDelayImageBlockResponse(quint8 transactionSequenceNumber, const QDateTime &requestTime, quint16 minimumBlockPeriod)
|
||||||
|
{
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << static_cast<quint8>(StatusCodeWaitForData);
|
||||||
|
stream << static_cast<quint32>(requestTime.toMSecsSinceEpoch() / 1000);
|
||||||
|
stream << minimumBlockPeriod;
|
||||||
|
|
||||||
|
ZigbeeClusterReply *reply = sendClusterServerResponse(CommandImageBlockResponse, transactionSequenceNumber, payload);
|
||||||
|
connect(reply, &ZigbeeClusterReply::finished, this, [reply](){
|
||||||
|
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "OTA: Error sending delay image block response:" << reply->error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(dcZigbeeCluster()) << "OTA: Delay image block response sent successfully.";
|
||||||
|
});
|
||||||
|
return reply;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOta::sendUpgradeEndResponse(quint8 transactionSequenceNumber, quint16 manufacturerCode, quint16 imageType, quint32 fileVersion, quint32 serverTime, quint32 requestTime)
|
||||||
|
{
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << manufacturerCode;
|
||||||
|
stream << imageType;
|
||||||
|
stream << fileVersion;
|
||||||
|
stream << serverTime;
|
||||||
|
stream << requestTime;
|
||||||
|
|
||||||
|
ZigbeeClusterReply *reply = sendClusterServerResponse(CommandUpgradeEndResponse, transactionSequenceNumber, payload);
|
||||||
|
connect(reply, &ZigbeeClusterReply::finished, this, [reply](){
|
||||||
|
if (reply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "OTA: Error sending image block response:" << reply->error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCDebug(dcZigbeeCluster()) << "OTA: Query image block data successfully.";
|
||||||
|
});
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeClusterOta::sendAbortUpgradeEndResponse(quint8 transactionSequenceNumber)
|
||||||
|
{
|
||||||
|
return sendDefaultResponse(transactionSequenceNumber, ZigbeeClusterLibrary::CommandDefaultResponse, ZigbeeClusterLibrary::StatusSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeClusterOta::FileVersion ZigbeeClusterOta::parseFileVersion(quint32 fileVersionValue)
|
ZigbeeClusterOta::FileVersion ZigbeeClusterOta::parseFileVersion(quint32 fileVersionValue)
|
||||||
{
|
{
|
||||||
FileVersion fileVersion;
|
FileVersion fileVersion;
|
||||||
fileVersion.applicationRelease = static_cast<quint8>(fileVersionValue & 0xFF000000);
|
fileVersion.applicationRelease = static_cast<quint8>(fileVersionValue >> 24);
|
||||||
fileVersion.applicationBuild = static_cast<quint8>(fileVersionValue & 0x00FF0000);
|
fileVersion.applicationBuild = static_cast<quint8>(fileVersionValue >> 16);
|
||||||
fileVersion.stackRelease = static_cast<quint8>(fileVersionValue & 0x0000FF00);
|
fileVersion.stackRelease = static_cast<quint8>(fileVersionValue >> 8);
|
||||||
fileVersion.stackBuild = static_cast<quint8>(fileVersionValue & 0x000000FF);
|
fileVersion.stackBuild = static_cast<quint8>(fileVersionValue);
|
||||||
return fileVersion;
|
return fileVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeClusterOta::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
void ZigbeeClusterOta::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeCluster()) << "Processing cluster frame" << m_node << m_endpoint << this << frame;
|
qCDebug(dcZigbeeCluster()) << "OTA: Processing cluster frame" << m_node << m_endpoint << this << frame << frame.payload.toHex();
|
||||||
|
|
||||||
switch (m_direction) {
|
switch (m_direction) {
|
||||||
case Client:
|
case Client:
|
||||||
|
|
@ -70,37 +207,64 @@ void ZigbeeClusterOta::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
||||||
QDataStream requestStream(&frame.payload, QIODevice::ReadOnly);
|
QDataStream requestStream(&frame.payload, QIODevice::ReadOnly);
|
||||||
requestStream.setByteOrder(QDataStream::LittleEndian);
|
requestStream.setByteOrder(QDataStream::LittleEndian);
|
||||||
requestStream >> fieldControl >> manufacturerCode >> imageType >> currentVersion >> hardwareVersion;
|
requestStream >> fieldControl >> manufacturerCode >> imageType >> currentVersion >> hardwareVersion;
|
||||||
qCDebug(dcZigbeeCluster()) << "OTA image request:" << (fieldControl == 0x0000 ? "Hardware version not present" : "Hardware version present");
|
FileVersion currentFileVersion = parseFileVersion(currentVersion);
|
||||||
|
qCDebug(dcZigbeeCluster()) << "OTA image request:" << (fieldControl == 0x00 ? "Hardware version not present" : "Hardware version present");
|
||||||
qCDebug(dcZigbeeCluster()) << "OTA image request: Manufacturer code" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
qCDebug(dcZigbeeCluster()) << "OTA image request: Manufacturer code" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
||||||
qCDebug(dcZigbeeCluster()) << "OTA image request: Image type" << ZigbeeUtils::convertUint16ToHexString(imageType);
|
qCDebug(dcZigbeeCluster()) << "OTA image request: Image type" << ZigbeeUtils::convertUint16ToHexString(imageType);
|
||||||
qCDebug(dcZigbeeCluster()) << "OTA image request: Current file version" << ZigbeeUtils::convertUint32ToHexString(currentVersion) << parseFileVersion(currentVersion);
|
qCDebug(dcZigbeeCluster()) << "OTA image request: Current file version" << ZigbeeUtils::convertUint32ToHexString(currentVersion) << currentFileVersion;
|
||||||
qCDebug(dcZigbeeCluster()) << "OTA image request: Hardware version" << hardwareVersion;
|
qCDebug(dcZigbeeCluster()) << "OTA image request: Hardware version" << hardwareVersion;
|
||||||
|
|
||||||
// Respond with no image available until we implement the entire cluster for OTA updates
|
emit queryNextImageRequestReceived(frame.header.transactionSequenceNumber, manufacturerCode, imageType, currentVersion, hardwareVersion);
|
||||||
qCDebug(dcZigbeeCluster()) << "OTA mechanism not implemented yet. Tell the node there is no image available.";
|
break;
|
||||||
|
}
|
||||||
|
case CommandImageBlockRequest: {
|
||||||
|
quint8 fieldControl;
|
||||||
|
quint16 manufacturerCode;
|
||||||
|
quint16 imageType;
|
||||||
|
quint32 fileVersion;
|
||||||
|
quint32 fileOffset;
|
||||||
|
quint8 maximumDataSize;
|
||||||
|
quint64 requestNodeAddress = 0;
|
||||||
|
quint16 minimumBlockPerdiod = 0;
|
||||||
|
|
||||||
QByteArray payload;
|
QDataStream stream(frame.payload);
|
||||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
stream << static_cast<quint8>(StatuCodeNoImageAvailable);
|
stream >> fieldControl >> manufacturerCode >> imageType >> fileVersion >> fileOffset >> maximumDataSize;
|
||||||
|
if (fieldControl & 0x01) {
|
||||||
// Note: if there would be an image available, the response would be success, followed by manufacturer code, image type, file version of image and file size
|
stream >> requestNodeAddress;
|
||||||
|
}
|
||||||
ZigbeeClusterReply *reply = sendClusterServerResponse(CommandQueryNextImageResponse, frame.header.transactionSequenceNumber, payload);
|
if (fieldControl & 0x02) {
|
||||||
connect(reply, &ZigbeeClusterReply::finished, this, [](){
|
stream >> minimumBlockPerdiod;
|
||||||
qCDebug(dcZigbeeCluster()) << "OTA image request response for image query sent successfully to requested node.";
|
}
|
||||||
});
|
qCDebug(dcZigbeeCluster()) << "OTA: Image block request receved. FieldControl:" << fieldControl << "ManufacturerCode:" << manufacturerCode << "ImageType:" << imageType << "File version:" << fileVersion << "Offset:" << fileOffset << "Max size:" << maximumDataSize << "Request Address:" << ZigbeeAddress(requestNodeAddress) << "Min block period:" << minimumBlockPerdiod;
|
||||||
|
emit imageBlockRequestReceived(frame.header.transactionSequenceNumber, manufacturerCode, imageType, fileVersion, fileOffset, maximumDataSize, ZigbeeAddress(requestNodeAddress), minimumBlockPerdiod);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CommandUpgradeEndRequest: {
|
||||||
|
quint8 status;
|
||||||
|
quint16 manufacturerCode;
|
||||||
|
quint16 imageType;
|
||||||
|
quint32 fileVersion;
|
||||||
|
QDataStream stream(frame.payload);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream >> status >> manufacturerCode >> imageType >> fileVersion;
|
||||||
|
emit upgradeEndRequestReceived(frame.header.transactionSequenceNumber, static_cast<StatusCode>(status), manufacturerCode, imageType, fileVersion);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
qCWarning(dcZigbeeCluster()) << "Received command" << command << "which is not implemented yet from" << m_node << m_endpoint << this;
|
qCWarning(dcZigbeeCluster()) << "Received unhandled command" << command << "from" << m_node << m_endpoint << this;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Server:
|
case Server:
|
||||||
|
if (frame.header.frameControl.direction == ZigbeeClusterLibrary::DirectionServerToClient) {
|
||||||
|
Command command = static_cast<Command>(frame.header.command);
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Received" << command << "from" << m_node << m_endpoint << this;
|
||||||
|
} else {
|
||||||
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
|
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#define ZIGBEECLUSTEROTA_H
|
#define ZIGBEECLUSTEROTA_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
#include "zcl/zigbeecluster.h"
|
#include "zcl/zigbeecluster.h"
|
||||||
#include "zcl/zigbeeclusterreply.h"
|
#include "zcl/zigbeeclusterreply.h"
|
||||||
|
|
@ -76,18 +77,26 @@ public:
|
||||||
Q_ENUM(Command)
|
Q_ENUM(Command)
|
||||||
|
|
||||||
enum StatusCode {
|
enum StatusCode {
|
||||||
StatuCodeSuccess = 0x00,
|
StatusCodeSuccess = 0x00,
|
||||||
StatuCodeAbort = 0x95,
|
StatusCodeAbort = 0x95,
|
||||||
StatuCodeNotAuthorized = 0x7E,
|
StatusCodeNotAuthorized = 0x7E,
|
||||||
StatuCodeInvalidImage = 0x96,
|
StatusCodeInvalidImage = 0x96,
|
||||||
StatuCodeWaitForData = 0x97,
|
StatusCodeWaitForData = 0x97,
|
||||||
StatuCodeNoImageAvailable = 0x98,
|
StatusCodeNoImageAvailable = 0x98,
|
||||||
StatuCodeMalformedCommand = 0x80,
|
StatusCodeMalformedCommand = 0x80,
|
||||||
StatuCodeUnsupportedClusterCommand = 0x81,
|
StatusCodeUnsupportedClusterCommand = 0x81,
|
||||||
StatuCodeRequireMoreImage = 0x99
|
StatusCodeRequireMoreImage = 0x99
|
||||||
};
|
};
|
||||||
Q_ENUM(StatusCode)
|
Q_ENUM(StatusCode)
|
||||||
|
|
||||||
|
enum PayloadType {
|
||||||
|
PayloadTypeQueryJitter = 0x00,
|
||||||
|
PayloadTypeQueryJitterAndManufacturerCode = 0x01,
|
||||||
|
PayloadTypeQueryJitterAndManufacturerCodeAndImageType = 0x02,
|
||||||
|
PayloadTypeQueryJitterAndManufacturerCodeAndImageTypeAndNewFileVersion = 0x03
|
||||||
|
};
|
||||||
|
Q_ENUM(PayloadType)
|
||||||
|
|
||||||
typedef struct FileVersion {
|
typedef struct FileVersion {
|
||||||
quint8 applicationRelease;
|
quint8 applicationRelease;
|
||||||
quint8 applicationBuild;
|
quint8 applicationBuild;
|
||||||
|
|
@ -95,13 +104,28 @@ public:
|
||||||
quint8 stackBuild;
|
quint8 stackBuild;
|
||||||
} FileVersion;
|
} FileVersion;
|
||||||
|
|
||||||
|
|
||||||
explicit ZigbeeClusterOta(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
explicit ZigbeeClusterOta(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
ZigbeeClusterReply *sendImageNotify(PayloadType payloadType = PayloadTypeQueryJitter, quint8 queryJitter = 100, quint16 manufacturerCode = 0, quint16 imageType = 0, quint32 newFileVersion = 0);
|
||||||
|
ZigbeeClusterReply *sendQueryNextImageResponse(quint8 transactionSequenceNumber, StatusCode statusCode = StatusCodeNoImageAvailable, quint16 manufacturerCode = 0, quint16 imageType = 0, quint32 fileVersion = 0, quint32 imageSize = 0);
|
||||||
|
|
||||||
|
ZigbeeClusterReply *sendImageBlockResponse(quint8 transactionSequenceNumber, quint16 manufacturerCode, quint16 imageType, quint32 fileVersion, quint32 fileOffset, const QByteArray &imageData);
|
||||||
|
ZigbeeClusterReply *sendAbortImageBlockResponse(quint8 transactionSequenceNumber);
|
||||||
|
ZigbeeClusterReply *sendDelayImageBlockResponse(quint8 transactionSequenceNumber, const QDateTime &requestTime, quint16 minimumBlockPeriod);
|
||||||
|
|
||||||
|
ZigbeeClusterReply *sendUpgradeEndResponse(quint8 transactionSequenceNumber, quint16 manufacturerCode, quint16 imageType, quint32 fileVersion, quint32 serverTime = 0, quint32 requestTime = 1);
|
||||||
|
ZigbeeClusterReply *sendAbortUpgradeEndResponse(quint8 transactionSequenceNumber);
|
||||||
|
|
||||||
|
static FileVersion parseFileVersion(quint32 fileVersionValue);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void queryNextImageRequestReceived(quint8 transactionSequenceNumber, quint16 manufactuerCode, quint16 imageType, quint32 fileVersion, quint16 hardwareVersion);
|
||||||
|
void imageBlockRequestReceived(quint8 transactionSequenceNumber, quint16 manufacturerCode, quint16 imageType, quint32 fileVersion, quint32 fileOffset, quint8 maximumDataSize, const ZigbeeAddress &requestNodeAddress, quint16 minimumBlockPeriod);
|
||||||
|
void upgradeEndRequestReceived(quint8 transactionSequenceNumber, StatusCode statusCode, quint16 manufacturerCode, quint16 imageType, quint32 fileVersion);
|
||||||
protected:
|
protected:
|
||||||
void processDataIndication(ZigbeeClusterLibrary::Frame frame) override;
|
void processDataIndication(ZigbeeClusterLibrary::Frame frame) override;
|
||||||
|
|
||||||
private:
|
|
||||||
FileVersion parseFileVersion(quint32 fileVersionValue);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ZigbeeClusterOta::FileVersion &fileVersion);
|
QDebug operator<<(QDebug debug, const ZigbeeClusterOta::FileVersion &fileVersion);
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ ZigbeeClusterReply *ZigbeeCluster::createClusterReply(const ZigbeeNetworkRequest
|
||||||
return zclReply;
|
return zclReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterReply *ZigbeeCluster::executeClusterCommand(quint8 command, const QByteArray &payload)
|
ZigbeeClusterReply *ZigbeeCluster::executeClusterCommand(quint8 command, const QByteArray &payload, ZigbeeClusterLibrary::Direction direction)
|
||||||
{
|
{
|
||||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ ZigbeeClusterReply *ZigbeeCluster::executeClusterCommand(quint8 command, const Q
|
||||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||||
frameControl.manufacturerSpecific = false;
|
frameControl.manufacturerSpecific = false;
|
||||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
frameControl.direction = direction;
|
||||||
frameControl.disableDefaultResponse = false;
|
frameControl.disableDefaultResponse = false;
|
||||||
|
|
||||||
// Build ZCL header
|
// Build ZCL header
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ protected:
|
||||||
|
|
||||||
// Cluster specific
|
// Cluster specific
|
||||||
ZigbeeClusterReply *createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame);
|
ZigbeeClusterReply *createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame);
|
||||||
ZigbeeClusterReply *executeClusterCommand(quint8 command, const QByteArray &payload = QByteArray());
|
ZigbeeClusterReply *executeClusterCommand(quint8 command, const QByteArray &payload = QByteArray(), ZigbeeClusterLibrary::Direction direction = ZigbeeClusterLibrary::DirectionClientToServer);
|
||||||
|
|
||||||
ZigbeeClusterReply *sendClusterServerResponse(quint8 command, quint8 transactionSequenceNumber, const QByteArray &payload = QByteArray());
|
ZigbeeClusterReply *sendClusterServerResponse(quint8 command, quint8 transactionSequenceNumber, const QByteArray &payload = QByteArray());
|
||||||
ZigbeeClusterReply *sendDefaultResponse(quint8 transactionSequenceNumber, quint8 command, quint8 status);
|
ZigbeeClusterReply *sendDefaultResponse(quint8 transactionSequenceNumber, quint8 command, quint8 status);
|
||||||
|
|
|
||||||
|
|
@ -265,8 +265,9 @@ QByteArray ZigbeeClusterLibrary::buildAttributeReportingConfiguration(const Zigb
|
||||||
stream << reportingConfiguration.minReportingInterval;
|
stream << reportingConfiguration.minReportingInterval;
|
||||||
stream << reportingConfiguration.maxReportingInterval;
|
stream << reportingConfiguration.maxReportingInterval;
|
||||||
|
|
||||||
for (int i = 0; i < reportingConfiguration.reportableChange.count(); i++)
|
for (int i = 0; i < reportingConfiguration.reportableChange.count(); i++) {
|
||||||
stream << static_cast<quint8>(reportingConfiguration.reportableChange.at(i));
|
stream << static_cast<quint8>(reportingConfiguration.reportableChange.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
// Note: for reporting the timeoutPeriod is omitted
|
// Note: for reporting the timeoutPeriod is omitted
|
||||||
if (reportingConfiguration.direction == ReportingDirectionReceiving) {
|
if (reportingConfiguration.direction == ReportingDirectionReceiving) {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ ZigbeeClusterReply::ZigbeeClusterReply(const ZigbeeNetworkRequest &request, Zigb
|
||||||
m_request(request),
|
m_request(request),
|
||||||
m_requestFrame(requestFrame)
|
m_requestFrame(requestFrame)
|
||||||
{
|
{
|
||||||
m_timeoutTimer.setInterval(10000);
|
m_timeoutTimer.setInterval(20000);
|
||||||
connect(&m_timeoutTimer, &QTimer::timeout, this, [this](){
|
connect(&m_timeoutTimer, &QTimer::timeout, this, [this](){
|
||||||
m_error = ErrorTimeout;
|
m_error = ErrorTimeout;
|
||||||
emit finished();
|
emit finished();
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ ZigbeeDeviceObjectReply::ZigbeeDeviceObjectReply(const ZigbeeNetworkRequest &req
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_request(request)
|
m_request(request)
|
||||||
{
|
{
|
||||||
m_timeoutTimer.setInterval(10000);
|
m_timeoutTimer.setInterval(20000);
|
||||||
connect(&m_timeoutTimer, &QTimer::timeout, this, [this](){
|
connect(&m_timeoutTimer, &QTimer::timeout, this, [this](){
|
||||||
m_error = ErrorTimeout;
|
m_error = ErrorTimeout;
|
||||||
emit finished();
|
emit finished();
|
||||||
|
|
|
||||||
|
|
@ -410,7 +410,7 @@ void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
|
||||||
|
|
||||||
connect(node, &ZigbeeNode::clusterAdded, this, [this, node](ZigbeeCluster *cluster){
|
connect(node, &ZigbeeNode::clusterAdded, this, [this, node](ZigbeeCluster *cluster){
|
||||||
if (node->state() == ZigbeeNode::StateInitialized) {
|
if (node->state() == ZigbeeNode::StateInitialized) {
|
||||||
qCWarning(dcZigbeeNetwork()) << node << cluster << "cluster added but the node has already been initialized. This node is out of spec. Save the node nether the less...";
|
qCWarning(dcZigbeeNetwork()) << node << "cluster" << cluster << "added on endpoint" << cluster->endpoint()->endpointId() << "but the node has already been initialized. This node is out of spec. Saving the node nethertheless...";
|
||||||
m_database->saveNode(node);
|
m_database->saveNode(node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObj
|
||||||
{
|
{
|
||||||
m_timer = new QTimer(this);
|
m_timer = new QTimer(this);
|
||||||
m_timer->setSingleShot(true);
|
m_timer->setSingleShot(true);
|
||||||
m_timer->setInterval(10000);
|
m_timer->setInterval(20000);
|
||||||
connect(m_timer, &QTimer::timeout, this, [this](){
|
connect(m_timer, &QTimer::timeout, this, [this](){
|
||||||
m_error = ErrorTimeout;
|
m_error = ErrorTimeout;
|
||||||
emit finished();
|
emit finished();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue