Implement basic cluster fetching
This commit is contained in:
parent
9174ff39c4
commit
b211dbf347
@ -143,7 +143,10 @@ void ZigbeeInterface::onReadyRead()
|
|||||||
m_lengthValue = 0;
|
m_lengthValue = 0;
|
||||||
m_escapeDetected = false;
|
m_escapeDetected = false;
|
||||||
m_data.clear();
|
m_data.clear();
|
||||||
|
if (!m_unhandledBuffer.isEmpty()) {
|
||||||
|
qCDebug(dcZigbeeInterfaceTraffic()) << "Controller debug message:" << QString::fromUtf8(m_unhandledBuffer);
|
||||||
|
m_unhandledBuffer.clear();
|
||||||
|
}
|
||||||
setReadingState(WaitForTypeMsb);
|
setReadingState(WaitForTypeMsb);
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
@ -185,7 +188,8 @@ void ZigbeeInterface::onReadyRead()
|
|||||||
// Read data bytes depending on the reading state
|
// Read data bytes depending on the reading state
|
||||||
switch (m_readingState) {
|
switch (m_readingState) {
|
||||||
case WaitForStart:
|
case WaitForStart:
|
||||||
qCWarning(dcZigbeeInterfaceTraffic()) << "Wait for start but reviced data:" << byte;
|
qCDebug(dcZigbeeInterfaceTraffic()) << "Wait for start but reviced data:" << byte;
|
||||||
|
m_unhandledBuffer.append(static_cast<char>(byte));
|
||||||
break;
|
break;
|
||||||
case WaitForTypeMsb:
|
case WaitForTypeMsb:
|
||||||
m_messageTypeValue = byte;
|
m_messageTypeValue = byte;
|
||||||
|
|||||||
@ -60,6 +60,7 @@ private:
|
|||||||
QTimer *m_reconnectTimer = nullptr;
|
QTimer *m_reconnectTimer = nullptr;
|
||||||
QSerialPort *m_serialPort = nullptr;
|
QSerialPort *m_serialPort = nullptr;
|
||||||
QByteArray m_messageBuffer;
|
QByteArray m_messageBuffer;
|
||||||
|
QByteArray m_unhandledBuffer;
|
||||||
bool m_available = false;
|
bool m_available = false;
|
||||||
|
|
||||||
// Message parsing
|
// Message parsing
|
||||||
|
|||||||
@ -381,6 +381,23 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandFactoryResetNode(quint16
|
|||||||
return sendRequest(request);
|
return sendRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandManagementLeaveRequest(quint16 shortAddress, const ZigbeeAddress &ieeeAddress, bool rejoin, bool removeChildren)
|
||||||
|
{
|
||||||
|
QByteArray data;
|
||||||
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||||
|
stream << shortAddress;
|
||||||
|
stream << ieeeAddress.toUInt64();
|
||||||
|
stream << (rejoin ? static_cast<quint8>(0x01) : static_cast<quint8>(0x00));
|
||||||
|
stream << (removeChildren ? static_cast<quint8>(0x01) : static_cast<quint8>(0x00));
|
||||||
|
|
||||||
|
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeManagementLeaveRequest, data));
|
||||||
|
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeManagementLeaveResponse);
|
||||||
|
request.setDescription("Leave node request " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||||
|
request.setTimoutIntervall(10000);
|
||||||
|
|
||||||
|
return sendRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandReadAttributeRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, QList<quint16> attributes, bool manufacturerSpecific, quint16 manufacturerId)
|
ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandReadAttributeRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, QList<quint16> attributes, bool manufacturerSpecific, quint16 manufacturerId)
|
||||||
{
|
{
|
||||||
// Address mode: TODO
|
// Address mode: TODO
|
||||||
@ -413,7 +430,9 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandReadAttributeRequest(qui
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeReadAttributeRequest, data));
|
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeReadAttributeRequest, data));
|
||||||
//request.setExpectedAdditionalMessageType(Zigbee::MessageTypeReadAttributeResponse);
|
if (attributes.count() == 1) {
|
||||||
|
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeReadAttributeResponse);
|
||||||
|
}
|
||||||
request.setDescription("Read attribute request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
request.setDescription("Read attribute request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||||
request.setTimoutIntervall(12000);
|
request.setTimoutIntervall(12000);
|
||||||
|
|
||||||
|
|||||||
@ -78,6 +78,7 @@ public:
|
|||||||
ZigbeeInterfaceReply *commandUserDescriptorRequest(quint16 shortAddress, quint16 address);
|
ZigbeeInterfaceReply *commandUserDescriptorRequest(quint16 shortAddress, quint16 address);
|
||||||
|
|
||||||
ZigbeeInterfaceReply *commandFactoryResetNode(quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint);
|
ZigbeeInterfaceReply *commandFactoryResetNode(quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint);
|
||||||
|
ZigbeeInterfaceReply *commandManagementLeaveRequest(quint16 shortAddress, const ZigbeeAddress &ieeeAddress, bool rejoin = false, bool removeChildren = false);
|
||||||
|
|
||||||
ZigbeeInterfaceReply *commandReadAttributeRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, QList<quint16> attributes, bool manufacturerSpecific, quint16 manufacturerId);
|
ZigbeeInterfaceReply *commandReadAttributeRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, QList<quint16> attributes, bool manufacturerSpecific, quint16 manufacturerId);
|
||||||
ZigbeeInterfaceReply *commandConfigureReportingRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, quint8 direction, bool manufacturerSpecific, quint16 manufacturerId, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations);
|
ZigbeeInterfaceReply *commandConfigureReportingRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, quint8 direction, bool manufacturerSpecific, quint16 manufacturerId, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations);
|
||||||
|
|||||||
@ -695,81 +695,14 @@ void ZigbeeNetworkNxp::processAttributeReport(const ZigbeeInterfaceMessage &mess
|
|||||||
|
|
||||||
void ZigbeeNetworkNxp::processReadAttributeResponse(const ZigbeeInterfaceMessage &message)
|
void ZigbeeNetworkNxp::processReadAttributeResponse(const ZigbeeInterfaceMessage &message)
|
||||||
{
|
{
|
||||||
QByteArray data = message.data();
|
ZigbeeClusterAttributeReport attributeReport = ZigbeeUtils::parseAttributeReport(message.data());
|
||||||
|
|
||||||
quint8 sequenceNumber = 0;
|
ZigbeeNodeNxp *node = qobject_cast<ZigbeeNodeNxp *>(getZigbeeNode(attributeReport.sourceAddress));
|
||||||
quint16 sourceAddress = 0;
|
|
||||||
quint8 endpointId = 0;
|
|
||||||
quint16 clusterId = 0;
|
|
||||||
quint16 attributeId = 0;
|
|
||||||
quint8 attributeStatus = 0;
|
|
||||||
quint8 attributDataType = 0;
|
|
||||||
quint16 dataSize = 0;
|
|
||||||
|
|
||||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
|
||||||
stream >> sequenceNumber >> sourceAddress >> endpointId >> clusterId >> attributeId >> attributeStatus >> attributDataType >> dataSize;
|
|
||||||
|
|
||||||
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(attributDataType);
|
|
||||||
QByteArray attributeData = data.right(dataSize);
|
|
||||||
|
|
||||||
if (attributeData.length() != dataSize) {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "HACK" << attributeData.length() << "!=" << dataSize;
|
|
||||||
// Note: the NXP firmware for JN5169 has a bug here and does not send the attributeStatus.
|
|
||||||
// Repars data without attribute status
|
|
||||||
sequenceNumber = 0;
|
|
||||||
sourceAddress = 0;
|
|
||||||
endpointId = 0;
|
|
||||||
clusterId = 0;
|
|
||||||
attributeId = 0;
|
|
||||||
attributeStatus = 0;
|
|
||||||
attributDataType = 0;
|
|
||||||
dataSize = 0;
|
|
||||||
|
|
||||||
QDataStream alternativeStream(&data, QIODevice::ReadOnly);
|
|
||||||
alternativeStream >> sequenceNumber >> sourceAddress >> endpointId >> clusterId >> attributeId >> attributDataType >> dataSize;
|
|
||||||
|
|
||||||
dataType = static_cast<Zigbee::DataType>(attributDataType);
|
|
||||||
attributeData = data.right(dataSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Attribute read response:";
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Source address:" << ZigbeeUtils::convertUint16ToHexString(sourceAddress);
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " End point:" << ZigbeeUtils::convertByteToHexString(endpointId);
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Cluster:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Attribut id:" << ZigbeeUtils::convertUint16ToHexString(attributeId);
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Attribut status:" << static_cast<Zigbee::ZigbeeStatus>(attributeStatus);
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Attribut data type:" << dataType;
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Attribut size:" << dataSize;
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Data:" << ZigbeeUtils::convertByteArrayToHexString(attributeData);
|
|
||||||
|
|
||||||
switch (dataType) {
|
|
||||||
case Zigbee::CharString:
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Data(converted)" << QString::fromUtf8(attributeData);
|
|
||||||
break;
|
|
||||||
case Zigbee::Bool:
|
|
||||||
qCDebug(dcZigbeeNetwork()) << " Data(converted)" << static_cast<bool>(attributeData.at(0));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ZigbeeNodeNxp *node = qobject_cast<ZigbeeNodeNxp *>(getZigbeeNode(sourceAddress));
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data.";
|
qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterAttributeReport attributeReport;
|
|
||||||
attributeReport.sourceAddress = sourceAddress;
|
|
||||||
attributeReport.endpointId = endpointId;
|
|
||||||
attributeReport.clusterId = static_cast<Zigbee::ClusterId>(clusterId);
|
|
||||||
attributeReport.attributeId = attributeId;
|
|
||||||
attributeReport.attributeStatus = static_cast<Zigbee::ZigbeeStatus>(attributeStatus);
|
|
||||||
attributeReport.dataType = dataType;
|
|
||||||
attributeReport.data = attributeData;
|
|
||||||
|
|
||||||
node->setClusterAttributeReport(attributeReport);
|
node->setClusterAttributeReport(attributeReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::readAttribute(ZigbeeCluster *cluster,
|
|||||||
ZigbeeInterfaceReply *reply = m_controller->commandReadAttributeRequest(0x02, node()->shortAddress(), 0x01,
|
ZigbeeInterfaceReply *reply = m_controller->commandReadAttributeRequest(0x02, node()->shortAddress(), 0x01,
|
||||||
endpointId(), cluster, attributes,
|
endpointId(), cluster, attributes,
|
||||||
false, node()->manufacturerCode());
|
false, node()->manufacturerCode());
|
||||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){
|
connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||||
@ -52,6 +52,10 @@ ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::readAttribute(ZigbeeCluster *cluster,
|
|||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||||
|
if (!reply->additionalMessage().data().isEmpty()) {
|
||||||
|
ZigbeeClusterAttributeReport report = ZigbeeUtils::parseAttributeReport(reply->additionalMessage().data());
|
||||||
|
setClusterAttribute(report.clusterId, ZigbeeClusterAttribute(report.attributeId, report.dataType, report.data));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -60,8 +64,11 @@ ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::readAttribute(ZigbeeCluster *cluster,
|
|||||||
ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations)
|
ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeNode()) << "Configure reporting" << node();
|
qCDebug(dcZigbeeNode()) << "Configure reporting" << node();
|
||||||
|
|
||||||
|
// FIXME: check the report configuration and the direction field according to specs
|
||||||
|
|
||||||
ZigbeeInterfaceReply *reply = m_controller->commandConfigureReportingRequest(0x02, node()->shortAddress(), 0x01,
|
ZigbeeInterfaceReply *reply = m_controller->commandConfigureReportingRequest(0x02, node()->shortAddress(), 0x01,
|
||||||
endpointId(), cluster, 0x01,
|
endpointId(), cluster, 0x00,
|
||||||
false, node()->manufacturerCode(), reportConfigurations);
|
false, node()->manufacturerCode(), reportConfigurations);
|
||||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){
|
connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@ -336,4 +343,5 @@ void ZigbeeNodeEndpointNxp::setClusterAttribute(Zigbee::ClusterId clusterId, con
|
|||||||
}
|
}
|
||||||
cluster->setAttribute(attribute);
|
cluster->setAttribute(attribute);
|
||||||
emit clusterAttributeChanged(cluster, attribute);
|
emit clusterAttributeChanged(cluster, attribute);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,6 +51,22 @@ ZigbeeNodeNxp::ZigbeeNodeNxp(ZigbeeBridgeControllerNxp *controller, QObject *par
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNodeNxp::leaveNetworkRequest(bool rejoin, bool removeChildren)
|
||||||
|
{
|
||||||
|
ZigbeeInterfaceReply *reply = m_controller->commandManagementLeaveRequest(shortAddress(), extendedAddress(), rejoin, removeChildren);
|
||||||
|
connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||||
|
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
||||||
|
// TODO: check error handling
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
||||||
{
|
{
|
||||||
m_initState = initState;
|
m_initState = initState;
|
||||||
@ -170,8 +186,10 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
|||||||
qCDebug(dcZigbeeNetwork()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
qCDebug(dcZigbeeNetwork()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||||
if (profileId == Zigbee::ZigbeeProfileLightLink) {
|
if (profileId == Zigbee::ZigbeeProfileLightLink) {
|
||||||
qCDebug(dcZigbeeNetwork()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::LightLinkDevice>(deviceId);
|
qCDebug(dcZigbeeNetwork()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::LightLinkDevice>(deviceId);
|
||||||
} else {
|
} else if (profileId == Zigbee::ZigbeeProfileHomeAutomation) {
|
||||||
qCDebug(dcZigbeeNetwork()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::HomeAutomationDevice>(deviceId);
|
qCDebug(dcZigbeeNetwork()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::HomeAutomationDevice>(deviceId);
|
||||||
|
} else if (profileId == Zigbee::ZigbeeProfileGreenPower) {
|
||||||
|
qCDebug(dcZigbeeNetwork()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::GreenPowerDevice>(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 deviceVersion = (bitField >> 4);
|
quint8 deviceVersion = (bitField >> 4);
|
||||||
@ -208,7 +226,7 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
|||||||
|
|
||||||
quint16 clusterId = 0;
|
quint16 clusterId = 0;
|
||||||
stream >> clusterId;
|
stream >> clusterId;
|
||||||
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
if (!endpoint->hasOutputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||||
endpoint->addOutputCluster(new ZigbeeCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
endpoint->addOutputCluster(new ZigbeeCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
||||||
}
|
}
|
||||||
qCDebug(dcZigbeeNetwork()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
qCDebug(dcZigbeeNetwork()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
@ -218,20 +236,22 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
|||||||
m_uninitializedEndpoints.removeAll(endpointId);
|
m_uninitializedEndpoints.removeAll(endpointId);
|
||||||
if (m_uninitializedEndpoints.isEmpty()) {
|
if (m_uninitializedEndpoints.isEmpty()) {
|
||||||
qCDebug(dcZigbeeNode()) << "All endpoints fetched.";
|
qCDebug(dcZigbeeNode()) << "All endpoints fetched.";
|
||||||
setInitState(InitStateReadClusterAttributes);
|
setInitState(InitStateReadBasicClusterAttributes);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InitStateReadClusterAttributes:
|
case InitStateReadBasicClusterAttributes:
|
||||||
// if (shortAddress() == 0x0000) {
|
if (shortAddress() == 0x0000) {
|
||||||
// qCDebug(dcZigbeeNode()) << "No need to read the endpoint baisc clusters of the coordinator node";
|
qCDebug(dcZigbeeNode()) << "No need to read the endpoint baisc clusters of the coordinator node";
|
||||||
// setState(StateInitialized);
|
setState(StateInitialized);
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
|
|
||||||
foreach (ZigbeeNodeEndpoint *endpoint, m_endpoints) {
|
foreach (ZigbeeNodeEndpoint *endpoint, m_endpoints) {
|
||||||
|
|
||||||
|
ZigbeeNodeEndpointNxp *endpointNxp = qobject_cast<ZigbeeNodeEndpointNxp *>(endpoint);
|
||||||
|
|
||||||
// Read basic cluster
|
// Read basic cluster
|
||||||
qCDebug(dcZigbeeNode()) << "Read basic cluster for endpoint" << endpoint;
|
qCDebug(dcZigbeeNode()) << "Read basic cluster for endpoint" << endpoint;
|
||||||
|
|
||||||
@ -242,34 +262,53 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<quint16> attributes;
|
m_uninitializedEndpoints.clear();
|
||||||
attributes.append(ZigbeeCluster::BasicAttributeZclVersion);
|
m_uninitalizedBasicClusterAttributes.append(ZigbeeCluster::BasicAttributeZclVersion);
|
||||||
attributes.append(ZigbeeCluster::BasicAttributeManufacturerName);
|
m_uninitalizedBasicClusterAttributes.append(ZigbeeCluster::BasicAttributeManufacturerName);
|
||||||
// Note: some devices inform about the model identifier trough attribute report and the cluster contains different information
|
// Note: some devices inform about the model identifier trough attribute report and the cluster contains different information
|
||||||
// Read the model identifier only if we don't have it yet. This is out of spec.
|
// Read the model identifier only if we don't have it yet. This is out of spec but required for some strange endpoints.
|
||||||
if (!basicCluster->hasAttribute(ZigbeeCluster::BasicAttributeModelIdentifier))
|
if (!basicCluster->hasAttribute(ZigbeeCluster::BasicAttributeModelIdentifier))
|
||||||
attributes.append(ZigbeeCluster::BasicAttributeModelIdentifier);
|
m_uninitalizedBasicClusterAttributes.append(ZigbeeCluster::BasicAttributeModelIdentifier);
|
||||||
|
|
||||||
attributes.append(ZigbeeCluster::BasicAttributePowerSource);
|
m_uninitalizedBasicClusterAttributes.append(ZigbeeCluster::BasicAttributePowerSource);
|
||||||
attributes.append(ZigbeeCluster::BasicAttributeSwBuildId);
|
m_uninitalizedBasicClusterAttributes.append(ZigbeeCluster::BasicAttributeSwBuildId);
|
||||||
ZigbeeInterfaceReply *reply = m_controller->commandReadAttributeRequest(0x02, shortAddress(),
|
|
||||||
0x01, endpoint->endpointId(),
|
|
||||||
basicCluster,
|
|
||||||
attributes,
|
|
||||||
false,
|
|
||||||
manufacturerCode());
|
|
||||||
|
|
||||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply, endpoint](){
|
// Note: for having smoother flow request each attribute sequentially, not all at once
|
||||||
reply->deleteLater();
|
|
||||||
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
|
||||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully for" << endpoint;
|
for (int i = 0; i < m_uninitalizedBasicClusterAttributes.count(); i++) {
|
||||||
qCDebug(dcZigbeeNode()) << "The device should response with multiple attribute read notifications.";
|
quint16 attributeId = m_uninitalizedBasicClusterAttributes.at(i);
|
||||||
setState(StateInitialized);
|
ZigbeeInterfaceReply *reply = m_controller->commandReadAttributeRequest(0x02, shortAddress(),
|
||||||
});
|
0x01, endpoint->endpointId(),
|
||||||
|
basicCluster,
|
||||||
|
{ attributeId },
|
||||||
|
false,
|
||||||
|
manufacturerCode());
|
||||||
|
|
||||||
|
connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply, endpointNxp, attributeId](){
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||||
|
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
||||||
|
} else {
|
||||||
|
ZigbeeClusterAttributeReport report = ZigbeeUtils::parseAttributeReport(reply->additionalMessage().data());
|
||||||
|
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully for" << endpointNxp << report;
|
||||||
|
if (report.attributeStatus == Zigbee::ZigbeeStatusSuccess) {
|
||||||
|
if (attributeId == ZigbeeCluster::BasicAttributeManufacturerName) {
|
||||||
|
endpointNxp->setManufacturerName(QString::fromUtf8(report.data));
|
||||||
|
} else if (attributeId == ZigbeeCluster::BasicAttributeModelIdentifier) {
|
||||||
|
endpointNxp->setModelIdentifier(QString::fromUtf8(report.data));
|
||||||
|
} else if (attributeId == ZigbeeCluster::BasicAttributeSwBuildId) {
|
||||||
|
endpointNxp->setSoftwareBuildId(QString::fromUtf8(report.data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_uninitalizedBasicClusterAttributes.removeAll(attributeId);
|
||||||
|
if (m_uninitalizedBasicClusterAttributes.isEmpty()) {
|
||||||
|
setState(StateInitialized);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,7 +329,7 @@ ZigbeeNodeEndpoint *ZigbeeNodeNxp::createNodeEndpoint(quint8 endpointId, QObject
|
|||||||
void ZigbeeNodeNxp::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report)
|
void ZigbeeNodeNxp::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report)
|
||||||
{
|
{
|
||||||
if (report.attributeStatus != Zigbee::ZigbeeStatusSuccess) {
|
if (report.attributeStatus != Zigbee::ZigbeeStatusSuccess) {
|
||||||
qCWarning(dcZigbeeNode()) << this << "Got incalid status report" << report.endpointId << report.clusterId << report.attributeId << report.attributeStatus;
|
qCWarning(dcZigbeeNode()) << this << "Got incalid status report" << report;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,17 +47,20 @@ public:
|
|||||||
InitStatePowerDescriptor,
|
InitStatePowerDescriptor,
|
||||||
InitStateActiveEndpoints,
|
InitStateActiveEndpoints,
|
||||||
InitStateSimpleDescriptors,
|
InitStateSimpleDescriptors,
|
||||||
InitStateReadClusterAttributes
|
InitStateReadBasicClusterAttributes
|
||||||
};
|
};
|
||||||
Q_ENUM(InitState)
|
Q_ENUM(InitState)
|
||||||
|
|
||||||
explicit ZigbeeNodeNxp(ZigbeeBridgeControllerNxp *controller, QObject *parent = nullptr);
|
explicit ZigbeeNodeNxp(ZigbeeBridgeControllerNxp *controller, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZigbeeBridgeControllerNxp *m_controller = nullptr;
|
ZigbeeBridgeControllerNxp *m_controller = nullptr;
|
||||||
InitState m_initState = InitStateNone;
|
InitState m_initState = InitStateNone;
|
||||||
|
|
||||||
QList<quint8> m_uninitializedEndpoints;
|
QList<quint8> m_uninitializedEndpoints;
|
||||||
|
QList<quint16> m_uninitalizedBasicClusterAttributes;
|
||||||
|
|
||||||
void setInitState(InitState initState);
|
void setInitState(InitState initState);
|
||||||
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
|
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
|
||||||
|
|||||||
@ -47,7 +47,8 @@ public:
|
|||||||
ZigbeeProfileTelecomAutomation = 0x0107,
|
ZigbeeProfileTelecomAutomation = 0x0107,
|
||||||
ZigbeeProfilePersonalHomeHospitalCare = 0x0108,
|
ZigbeeProfilePersonalHomeHospitalCare = 0x0108,
|
||||||
ZigbeeProfileAdvancedMetering = 0x0109,
|
ZigbeeProfileAdvancedMetering = 0x0109,
|
||||||
ZigbeeProfileLightLink = 0xC05E
|
ZigbeeProfileLightLink = 0xC05E,
|
||||||
|
ZigbeeProfileGreenPower = 0xA1E0
|
||||||
};
|
};
|
||||||
Q_ENUM(ZigbeeProfile)
|
Q_ENUM(ZigbeeProfile)
|
||||||
|
|
||||||
@ -306,6 +307,10 @@ public:
|
|||||||
// Over the air uppgrade (OTA)
|
// Over the air uppgrade (OTA)
|
||||||
ClusterIdOtaUpgrade = 0x0019,
|
ClusterIdOtaUpgrade = 0x0019,
|
||||||
|
|
||||||
|
// Poll controll
|
||||||
|
ClusterIdPollControl = 0x0020,
|
||||||
|
|
||||||
|
|
||||||
// Closures
|
// Closures
|
||||||
ClusterIdShadeConfiguration = 0x0100,
|
ClusterIdShadeConfiguration = 0x0100,
|
||||||
|
|
||||||
@ -342,9 +347,6 @@ public:
|
|||||||
ClusterIdLoadControl = 0x0701,
|
ClusterIdLoadControl = 0x0701,
|
||||||
ClusterIdSimpleMetering = 0x0702,
|
ClusterIdSimpleMetering = 0x0702,
|
||||||
|
|
||||||
// Electrical Measurement
|
|
||||||
ClusterIdElectricalMeasurement = 0x0B04,
|
|
||||||
|
|
||||||
// ZLL
|
// ZLL
|
||||||
ClusterIdTouchlinkCommissioning = 0x1000,
|
ClusterIdTouchlinkCommissioning = 0x1000,
|
||||||
|
|
||||||
@ -352,7 +354,15 @@ public:
|
|||||||
ClusterIdApplianceControl = 0x001B,
|
ClusterIdApplianceControl = 0x001B,
|
||||||
ClusterIdApplianceIdentification = 0x0B00,
|
ClusterIdApplianceIdentification = 0x0B00,
|
||||||
ClusterIdApplianceEventsAlerts = 0x0B02,
|
ClusterIdApplianceEventsAlerts = 0x0B02,
|
||||||
ClusterIdApplianceStatistics = 0x0B03
|
ClusterIdApplianceStatistics = 0x0B03,
|
||||||
|
|
||||||
|
// Electrical Measurement
|
||||||
|
ClusterIdElectricalMeasurement = 0x0B04,
|
||||||
|
ClusterIdDiagnostics = 0x0B05,
|
||||||
|
|
||||||
|
// Zigbee green power
|
||||||
|
ClusterIdGreenPower = 0x0021
|
||||||
|
|
||||||
};
|
};
|
||||||
Q_ENUM(ClusterId)
|
Q_ENUM(ClusterId)
|
||||||
|
|
||||||
@ -451,6 +461,18 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(HomeAutomationDevice)
|
Q_ENUM(HomeAutomationDevice)
|
||||||
|
|
||||||
|
|
||||||
|
enum GreenPowerDevice {
|
||||||
|
GreenPowerDeviceProxy = 0x0060,
|
||||||
|
GreenPowerDeviceProxyMinimum = 0x0061,
|
||||||
|
GreenPowerDeviceProxyTargetPlus = 0x0062,
|
||||||
|
GreenPowerDeviceProxyTarget = 0x0063,
|
||||||
|
GreenPowerDeviceProxyCommissioningTool = 0x0064,
|
||||||
|
GreenPowerDeviceProxyCombo = 0x0065,
|
||||||
|
GreenPowerDeviceProxyComboMinimum = 0x0066
|
||||||
|
};
|
||||||
|
Q_ENUM(GreenPowerDevice)
|
||||||
|
|
||||||
enum DataType {
|
enum DataType {
|
||||||
NoData = 0x00,
|
NoData = 0x00,
|
||||||
Data8 = 0x08,
|
Data8 = 0x08,
|
||||||
|
|||||||
@ -93,3 +93,16 @@ QDebug operator<<(QDebug debug, ZigbeeCluster *cluster)
|
|||||||
|
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeReport)
|
||||||
|
{
|
||||||
|
debug.nospace().noquote() << "AttributeReport("
|
||||||
|
<< attributeReport.clusterId << ", "
|
||||||
|
<< attributeReport.attributeId << ", "
|
||||||
|
<< attributeReport.attributeStatus << ", "
|
||||||
|
<< attributeReport.dataType << ", "
|
||||||
|
<< attributeReport.data << ", "
|
||||||
|
<< ")";
|
||||||
|
|
||||||
|
return debug.space();
|
||||||
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ struct ZigbeeClusterReportConfigurationRecord {
|
|||||||
quint8 change;
|
quint8 change;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZigbeeClusterAttributeReport {
|
typedef struct ZigbeeClusterAttributeReport {
|
||||||
quint16 sourceAddress;
|
quint16 sourceAddress;
|
||||||
quint8 endpointId;
|
quint8 endpointId;
|
||||||
Zigbee::ClusterId clusterId;
|
Zigbee::ClusterId clusterId;
|
||||||
@ -51,8 +51,7 @@ struct ZigbeeClusterAttributeReport {
|
|||||||
Zigbee::ZigbeeStatus attributeStatus;
|
Zigbee::ZigbeeStatus attributeStatus;
|
||||||
Zigbee::DataType dataType;
|
Zigbee::DataType dataType;
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
};
|
} ZigbeeClusterAttributeReport;
|
||||||
|
|
||||||
|
|
||||||
class ZigbeeCluster : public QObject
|
class ZigbeeCluster : public QObject
|
||||||
{
|
{
|
||||||
@ -218,5 +217,6 @@ signals:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster);
|
QDebug operator<<(QDebug debug, ZigbeeCluster *cluster);
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeClusterAttributeReport &attributeReport);
|
||||||
|
|
||||||
#endif // ZIGBEECLUSTER_H
|
#endif // ZIGBEECLUSTER_H
|
||||||
|
|||||||
@ -280,7 +280,9 @@ void ZigbeeNetwork::loadNetwork()
|
|||||||
endpoint->m_profile = static_cast<Zigbee::ZigbeeProfile>(settings.value("profile", 0).toUInt());
|
endpoint->m_profile = static_cast<Zigbee::ZigbeeProfile>(settings.value("profile", 0).toUInt());
|
||||||
endpoint->m_deviceId = static_cast<quint16>(settings.value("deviceId", 0).toUInt());
|
endpoint->m_deviceId = static_cast<quint16>(settings.value("deviceId", 0).toUInt());
|
||||||
endpoint->m_deviceVersion = static_cast<quint8>(settings.value("deviceId", 0).toUInt());
|
endpoint->m_deviceVersion = static_cast<quint8>(settings.value("deviceId", 0).toUInt());
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Created" << endpoint;
|
endpoint->m_manufacturerName = settings.value("manufacturerName").toString();
|
||||||
|
endpoint->m_modelIdentifier = settings.value("modelIdentifier").toString();
|
||||||
|
endpoint->m_softwareBuildId = settings.value("softwareBuildId").toString();
|
||||||
|
|
||||||
int inputClustersCount = settings.beginReadArray("inputClusters");
|
int inputClustersCount = settings.beginReadArray("inputClusters");
|
||||||
for (int n = 0; n < inputClustersCount; n ++) {
|
for (int n = 0; n < inputClustersCount; n ++) {
|
||||||
@ -339,11 +341,6 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node)
|
|||||||
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
|
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
|
||||||
settings.beginGroup("Nodes");
|
settings.beginGroup("Nodes");
|
||||||
|
|
||||||
// Clear settings for this node before storing it
|
|
||||||
// settings.beginGroup(node->extendedAddress().toString());
|
|
||||||
// settings.remove("");
|
|
||||||
// settings.endGroup();
|
|
||||||
|
|
||||||
// Save this node
|
// Save this node
|
||||||
settings.beginGroup(node->extendedAddress().toString());
|
settings.beginGroup(node->extendedAddress().toString());
|
||||||
settings.setValue("nwkAddress", node->shortAddress());
|
settings.setValue("nwkAddress", node->shortAddress());
|
||||||
@ -359,6 +356,9 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node)
|
|||||||
settings.setValue("profile", endpoint->profile());
|
settings.setValue("profile", endpoint->profile());
|
||||||
settings.setValue("deviceId", endpoint->deviceId());
|
settings.setValue("deviceId", endpoint->deviceId());
|
||||||
settings.setValue("deviceVersion", endpoint->deviceVersion());
|
settings.setValue("deviceVersion", endpoint->deviceVersion());
|
||||||
|
settings.setValue("manufacturerName", endpoint->manufacturerName());
|
||||||
|
settings.setValue("modelIdentifier", endpoint->modelIdentifier());
|
||||||
|
settings.setValue("softwareBuildId", endpoint->softwareBuildId());
|
||||||
|
|
||||||
settings.beginWriteArray("inputClusters");
|
settings.beginWriteArray("inputClusters");
|
||||||
for (int n = 0; n < endpoint->inputClusters().count(); n++) {
|
for (int n = 0; n < endpoint->inputClusters().count(); n++) {
|
||||||
|
|||||||
@ -238,42 +238,6 @@ void ZigbeeNode::setConnected(bool connected)
|
|||||||
emit connectedChanged(m_connected);
|
emit connectedChanged(m_connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//void ZigbeeNode::identify()
|
|
||||||
//{
|
|
||||||
// QByteArray data;
|
|
||||||
// QDataStream stream(&data, QIODevice::WriteOnly);
|
|
||||||
// stream << m_shortAddress;
|
|
||||||
// stream << static_cast<quint8>(0);
|
|
||||||
|
|
||||||
// ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeManagementLqiRequest, data));
|
|
||||||
// request.setExpectedAdditionalMessageType(Zigbee::MessageTypeManagementLqiResponse);
|
|
||||||
// request.setDescription("Node link quality request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
|
|
||||||
// request.setTimoutIntervall(10000);
|
|
||||||
|
|
||||||
// ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
|
||||||
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestLinkQuality);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void ZigbeeNode::toggle(int addressMode)
|
|
||||||
//{
|
|
||||||
// QByteArray data;
|
|
||||||
// QDataStream stream(&data, QIODevice::WriteOnly);
|
|
||||||
// stream << static_cast<quint8>(addressMode); // adress mode
|
|
||||||
// stream << m_shortAddress;
|
|
||||||
// stream << static_cast<quint8>(1); // source endpoint
|
|
||||||
// stream << static_cast<quint8>(1); // destination endpoint
|
|
||||||
// stream << static_cast<quint8>(2); // command toggle
|
|
||||||
|
|
||||||
// ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeCluserOnOff, data));
|
|
||||||
// request.setDescription("Toggle request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
|
|
||||||
|
|
||||||
// ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
|
||||||
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onToggleFinished);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ZigbeeNode::setShortAddress(const quint16 &shortAddress)
|
void ZigbeeNode::setShortAddress(const quint16 &shortAddress)
|
||||||
{
|
{
|
||||||
m_shortAddress = shortAddress;
|
m_shortAddress = shortAddress;
|
||||||
@ -587,6 +551,7 @@ QDebug operator<<(QDebug debug, ZigbeeNode *node)
|
|||||||
{
|
{
|
||||||
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
|
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
|
||||||
debug.nospace().noquote() << ", " << node->extendedAddress().toString();
|
debug.nospace().noquote() << ", " << node->extendedAddress().toString();
|
||||||
|
debug.nospace().noquote() << ", " << node->nodeType();
|
||||||
debug.nospace().noquote() << ")";
|
debug.nospace().noquote() << ")";
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -147,6 +147,8 @@ public:
|
|||||||
QList<PowerSource> availablePowerSources() const;
|
QList<PowerSource> availablePowerSources() const;
|
||||||
PowerLevel powerLevel() const;
|
PowerLevel powerLevel() const;
|
||||||
|
|
||||||
|
virtual void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_connected = false;
|
bool m_connected = false;
|
||||||
State m_state = StateUninitialized;
|
State m_state = StateUninitialized;
|
||||||
|
|||||||
@ -70,6 +70,21 @@ void ZigbeeNodeEndpoint::setDeviceVersion(quint8 deviceVersion)
|
|||||||
m_deviceVersion = deviceVersion;
|
m_deviceVersion = deviceVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ZigbeeNodeEndpoint::manufacturerName() const
|
||||||
|
{
|
||||||
|
return m_manufacturerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ZigbeeNodeEndpoint::modelIdentifier() const
|
||||||
|
{
|
||||||
|
return m_modelIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ZigbeeNodeEndpoint::softwareBuildId() const
|
||||||
|
{
|
||||||
|
return m_softwareBuildId;
|
||||||
|
}
|
||||||
|
|
||||||
QList<ZigbeeCluster *> ZigbeeNodeEndpoint::inputClusters() const
|
QList<ZigbeeCluster *> ZigbeeNodeEndpoint::inputClusters() const
|
||||||
{
|
{
|
||||||
return m_inputClusters.values();
|
return m_inputClusters.values();
|
||||||
@ -151,8 +166,10 @@ QDebug operator<<(QDebug debug, ZigbeeNodeEndpoint *endpoint)
|
|||||||
debug.nospace().noquote() << ", " << endpoint->profile();
|
debug.nospace().noquote() << ", " << endpoint->profile();
|
||||||
if (endpoint->profile() == Zigbee::ZigbeeProfileLightLink) {
|
if (endpoint->profile() == Zigbee::ZigbeeProfileLightLink) {
|
||||||
debug.nospace().noquote() << ", " << static_cast<Zigbee::LightLinkDevice>(endpoint->deviceId());
|
debug.nospace().noquote() << ", " << static_cast<Zigbee::LightLinkDevice>(endpoint->deviceId());
|
||||||
} else {
|
} else if (endpoint->profile() == Zigbee::ZigbeeProfileHomeAutomation) {
|
||||||
debug.nospace().noquote() << ", " << static_cast<Zigbee::HomeAutomationDevice>(endpoint->deviceId());
|
debug.nospace().noquote() << ", " << static_cast<Zigbee::HomeAutomationDevice>(endpoint->deviceId());
|
||||||
|
} else if (endpoint->profile() == Zigbee::ZigbeeProfileGreenPower) {
|
||||||
|
debug.nospace().noquote() << ", " << static_cast<Zigbee::GreenPowerDevice>(endpoint->deviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.nospace().noquote() << ")";
|
debug.nospace().noquote() << ")";
|
||||||
|
|||||||
@ -420,3 +420,81 @@ QColor ZigbeeUtils::interpolateColorFromColorTemperature(int colorTemperature, i
|
|||||||
// FIXME: interpolate between the selected index and the next color for more accuracy if required
|
// FIXME: interpolate between the selected index and the next color for more accuracy if required
|
||||||
return colorTemperatureScale.at(closestColorIndex);
|
return colorTemperatureScale.at(closestColorIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeClusterAttributeReport ZigbeeUtils::parseAttributeReport(const QByteArray &data)
|
||||||
|
{
|
||||||
|
QByteArray dataCopy = data;
|
||||||
|
quint8 sequenceNumber = 0;
|
||||||
|
quint16 sourceAddress = 0;
|
||||||
|
quint8 endpointId = 0;
|
||||||
|
quint16 clusterId = 0;
|
||||||
|
quint16 attributeId = 0;
|
||||||
|
quint8 attributeStatus = 0;
|
||||||
|
quint8 attributDataType = 0;
|
||||||
|
quint16 dataSize = 0;
|
||||||
|
|
||||||
|
QDataStream stream(&dataCopy, QIODevice::ReadOnly);
|
||||||
|
stream >> sequenceNumber >> sourceAddress >> endpointId >> clusterId >> attributeId >> attributeStatus >> attributDataType >> dataSize;
|
||||||
|
|
||||||
|
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(attributDataType);
|
||||||
|
QByteArray attributeData = data.right(dataSize);
|
||||||
|
|
||||||
|
if (attributeData.length() != dataSize) {
|
||||||
|
//qCWarning(dcZigbeeNetwork()) << "HACK" << attributeData.length() << "!=" << dataSize;
|
||||||
|
// Note: the NXP firmware for JN5169 has a bug here and does not send the attributeStatus.
|
||||||
|
// Repars data without attribute status
|
||||||
|
sequenceNumber = 0;
|
||||||
|
sourceAddress = 0;
|
||||||
|
endpointId = 0;
|
||||||
|
clusterId = 0;
|
||||||
|
attributeId = 0;
|
||||||
|
attributeStatus = 0;
|
||||||
|
attributDataType = 0;
|
||||||
|
dataSize = 0;
|
||||||
|
|
||||||
|
QDataStream alternativeStream(&dataCopy, QIODevice::ReadOnly);
|
||||||
|
alternativeStream >> sequenceNumber >> sourceAddress >> endpointId >> clusterId >> attributeId >> attributDataType >> dataSize;
|
||||||
|
|
||||||
|
dataType = static_cast<Zigbee::DataType>(attributDataType);
|
||||||
|
attributeData = data.right(dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << "Attribute read response:";
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Source address:" << ZigbeeUtils::convertUint16ToHexString(sourceAddress);
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " End point:" << ZigbeeUtils::convertByteToHexString(endpointId);
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Cluster:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Attribut id:" << ZigbeeUtils::convertUint16ToHexString(attributeId);
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Attribut status:" << static_cast<Zigbee::ZigbeeStatus>(attributeStatus);
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Attribut data type:" << dataType;
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Attribut size:" << dataSize;
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Data:" << ZigbeeUtils::convertByteArrayToHexString(attributeData);
|
||||||
|
|
||||||
|
// switch (dataType) {
|
||||||
|
// case Zigbee::CharString:
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Data(converted)" << QString::fromUtf8(attributeData);
|
||||||
|
// break;
|
||||||
|
// case Zigbee::Bool:
|
||||||
|
// qCDebug(dcZigbeeNetwork()) << " Data(converted)" << static_cast<bool>(attributeData.at(0));
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// ZigbeeNodeNxp *node = qobject_cast<ZigbeeNodeNxp *>(getZigbeeNode(sourceAddress));
|
||||||
|
// if (!node) {
|
||||||
|
// qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data.";
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
ZigbeeClusterAttributeReport attributeReport;
|
||||||
|
attributeReport.sourceAddress = sourceAddress;
|
||||||
|
attributeReport.endpointId = endpointId;
|
||||||
|
attributeReport.clusterId = static_cast<Zigbee::ClusterId>(clusterId);
|
||||||
|
attributeReport.attributeId = attributeId;
|
||||||
|
attributeReport.attributeStatus = static_cast<Zigbee::ZigbeeStatus>(attributeStatus);
|
||||||
|
attributeReport.dataType = dataType;
|
||||||
|
attributeReport.data = attributeData;
|
||||||
|
return attributeReport;
|
||||||
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
#include <QBitArray>
|
#include <QBitArray>
|
||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
|
#include "zigbeecluster.h"
|
||||||
|
|
||||||
class ZigbeeUtils
|
class ZigbeeUtils
|
||||||
{
|
{
|
||||||
@ -73,6 +74,8 @@ public:
|
|||||||
// Color temperature interpolation
|
// Color temperature interpolation
|
||||||
static QColor interpolateColorFromColorTemperature(int colorTemperature, int minValue, int maxValue);
|
static QColor interpolateColorFromColorTemperature(int colorTemperature, int minValue, int maxValue);
|
||||||
|
|
||||||
|
static ZigbeeClusterAttributeReport parseAttributeReport(const QByteArray &data);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ZIGBEEUTILS_H
|
#endif // ZIGBEEUTILS_H
|
||||||
|
|||||||
Reference in New Issue
Block a user