Implement ZCL default response for clusters and improve ISA zone cluster
This commit is contained in:
parent
2edfaa402a
commit
1c30c1de8b
@ -39,10 +39,36 @@ ZigbeeClusterIasZone::ZigbeeClusterIasZone(ZigbeeNetwork *network, ZigbeeNode *n
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterIasZone::ZoneState ZigbeeClusterIasZone::zoneState() const
|
||||||
|
{
|
||||||
|
return m_zoneState;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterIasZone::ZoneType ZigbeeClusterIasZone::zoneType() const
|
||||||
|
{
|
||||||
|
return m_zoneType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterIasZone::ZoneStatus ZigbeeClusterIasZone::zoneStatus() const
|
||||||
|
{
|
||||||
|
return m_zoneStatus;
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeClusterIasZone::setAttribute(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeClusterIasZone::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||||
updateOrAddAttribute(attribute);
|
updateOrAddAttribute(attribute);
|
||||||
|
|
||||||
|
if (attribute.id() == AttributeZoneState) {
|
||||||
|
quint8 zoneStateInt = attribute.dataType().toUInt8();
|
||||||
|
m_zoneState = static_cast<ZoneState>(zoneStateInt);
|
||||||
|
} else if (attribute.id() == AttributeZoneType) {
|
||||||
|
quint16 zoneTypeInt = attribute.dataType().toUInt16();
|
||||||
|
m_zoneType = static_cast<ZoneType>(zoneTypeInt);
|
||||||
|
} else if (attribute.id() == AttributeZoneStatus) {
|
||||||
|
quint16 zoneStatusInt = attribute.dataType().toUInt16();
|
||||||
|
m_zoneStatus = ZoneStatus(zoneStatusInt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeClusterIasZone::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
void ZigbeeClusterIasZone::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
||||||
@ -75,6 +101,16 @@ void ZigbeeClusterIasZone::processDataIndication(ZigbeeClusterLibrary::Frame fra
|
|||||||
// Update the ZoneState attribute
|
// Update the ZoneState attribute
|
||||||
setAttribute(ZigbeeClusterAttribute(AttributeZoneState, ZigbeeDataType(Zigbee::BitMap16, frame.payload.left(2))));
|
setAttribute(ZigbeeClusterAttribute(AttributeZoneState, ZigbeeDataType(Zigbee::BitMap16, frame.payload.left(2))));
|
||||||
emit zoneStatusChanged(ZoneStatusFlags(zoneStatus), extendedStatus, zoneId, delay);
|
emit zoneStatusChanged(ZoneStatusFlags(zoneStatus), extendedStatus, zoneId, delay);
|
||||||
|
|
||||||
|
// Respond with default response if enabled
|
||||||
|
if (!frame.header.frameControl.disableDefaultResponse) {
|
||||||
|
// Send the default response with success back to the cluster
|
||||||
|
ZigbeeClusterReply *reply = sendDefaultResponse(frame.header.transactionSequenceNumber, command, ZigbeeClusterLibrary::StatusSuccess);
|
||||||
|
connect(reply, &ZigbeeClusterReply::finished, this, [](){
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Default response sent successfully to the IAS zone status notification.";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ServerCommandZoneEnrollRequest: {
|
case ServerCommandZoneEnrollRequest: {
|
||||||
@ -87,8 +123,16 @@ void ZigbeeClusterIasZone::processDataIndication(ZigbeeClusterLibrary::Frame fra
|
|||||||
<< zoneType << "Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
<< zoneType << "Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
||||||
// Update the ZoneState attribute
|
// Update the ZoneState attribute
|
||||||
setAttribute(ZigbeeClusterAttribute(AttributeZoneType, ZigbeeDataType(Zigbee::Enum16, frame.payload.left(2))));
|
setAttribute(ZigbeeClusterAttribute(AttributeZoneType, ZigbeeDataType(Zigbee::Enum16, frame.payload.left(2))));
|
||||||
|
|
||||||
emit zoneEnrollRequest(zoneType, manufacturerCode);
|
emit zoneEnrollRequest(zoneType, manufacturerCode);
|
||||||
|
|
||||||
|
// Respond with default response if enabled
|
||||||
|
if (!frame.header.frameControl.disableDefaultResponse) {
|
||||||
|
// Send the default response with success back to the cluster
|
||||||
|
ZigbeeClusterReply *reply = sendDefaultResponse(frame.header.transactionSequenceNumber, command, ZigbeeClusterLibrary::StatusSuccess);
|
||||||
|
connect(reply, &ZigbeeClusterReply::finished, this, [](){
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Default response sent successfully to the IAS zone status notification.";
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,9 +123,15 @@ public:
|
|||||||
|
|
||||||
explicit ZigbeeClusterIasZone(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
explicit ZigbeeClusterIasZone(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
// TODO: write server commands
|
ZoneState zoneState() const;
|
||||||
|
ZoneType zoneType() const;
|
||||||
|
ZoneStatus zoneStatus() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ZoneState m_zoneState = ZoneStateNotEnrolled;
|
||||||
|
ZoneType m_zoneType = ZoneTypeInvalidZone;
|
||||||
|
ZoneStatus m_zoneStatus;
|
||||||
|
|
||||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@ -282,6 +282,52 @@ ZigbeeClusterReply *ZigbeeCluster::sendClusterServerResponse(quint8 command, qui
|
|||||||
return zclReply;
|
return zclReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterReply *ZigbeeCluster::sendDefaultResponse(quint8 transactionSequenceNumber, quint8 command, quint8 status)
|
||||||
|
{
|
||||||
|
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||||
|
|
||||||
|
// Build ZCL frame control
|
||||||
|
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||||
|
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||||
|
frameControl.manufacturerSpecific = false;
|
||||||
|
frameControl.direction = ZigbeeClusterLibrary::DirectionServerToClient;
|
||||||
|
frameControl.disableDefaultResponse = true;
|
||||||
|
|
||||||
|
// Build ZCL header
|
||||||
|
ZigbeeClusterLibrary::Header header;
|
||||||
|
header.frameControl = frameControl;
|
||||||
|
header.command = ZigbeeClusterLibrary::CommandDefaultResponse;
|
||||||
|
header.transactionSequenceNumber = transactionSequenceNumber;
|
||||||
|
|
||||||
|
QByteArray payload;
|
||||||
|
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << command << status;
|
||||||
|
|
||||||
|
// Build ZCL frame
|
||||||
|
ZigbeeClusterLibrary::Frame frame;
|
||||||
|
frame.header = header;
|
||||||
|
frame.payload = payload;
|
||||||
|
|
||||||
|
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||||
|
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||||
|
|
||||||
|
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Send default response" << "TSN:" << ZigbeeUtils::convertByteToHexString(transactionSequenceNumber) << ZigbeeUtils::convertByteArrayToHexString(payload);
|
||||||
|
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||||
|
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||||
|
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||||
|
finishZclReply(zclReply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: since this is a response to a request, we don't expect any additional indications and the reply is finished
|
||||||
|
finishZclReply(zclReply);
|
||||||
|
});
|
||||||
|
|
||||||
|
return zclReply;
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeNetworkRequest ZigbeeCluster::createGeneralRequest()
|
ZigbeeNetworkRequest ZigbeeCluster::createGeneralRequest()
|
||||||
{
|
{
|
||||||
// Build the request
|
// Build the request
|
||||||
|
|||||||
@ -119,6 +119,7 @@ protected:
|
|||||||
ZigbeeClusterReply *executeClusterCommand(quint8 command, const QByteArray &payload = QByteArray());
|
ZigbeeClusterReply *executeClusterCommand(quint8 command, const QByteArray &payload = QByteArray());
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
bool verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply);
|
bool verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply);
|
||||||
void finishZclReply(ZigbeeClusterReply *zclReply);
|
void finishZclReply(ZigbeeClusterReply *zclReply);
|
||||||
|
|||||||
Reference in New Issue
Block a user