Implement cluster creation and handle some things for out of spec devices
This commit is contained in:
parent
511d9c641a
commit
9174ff39c4
BIN
docs/JN-AN-1216-ZigBee-3-0-IoT-ControlBridge-UserGuide.pdf
Normal file → Executable file
BIN
docs/JN-AN-1216-ZigBee-3-0-IoT-ControlBridge-UserGuide.pdf
Normal file → Executable file
Binary file not shown.
@ -29,6 +29,7 @@
|
||||
|
||||
Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
||||
|
||||
@ -199,7 +199,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandActiveEndpointsRequest(q
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeActiveEndpointRequest, data));
|
||||
request.setDescription("Get active endpoints");
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeActiveEndpointResponse);
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -214,7 +214,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandRequestLinkQuality(quint
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeManagementLqiRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeManagementLqiResponse);
|
||||
request.setDescription("Request link quality request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -301,7 +301,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandAuthenticateDevice(const
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeAuthenticateDeviceRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeAuthenticateDeviceResponse);
|
||||
request.setDescription(QString("Authenticate device %1").arg(ieeeAddress.toString()));
|
||||
request.setTimoutIntervall(2000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -315,7 +315,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandNodeDescriptorRequest(qu
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
|
||||
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -330,7 +330,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandSimpleDescriptorRequest(
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSimpleDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeSimpleDescriptorResponse);
|
||||
request.setDescription("Simple node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress) + " endpoint " + QString::number(endpoint));
|
||||
request.setTimoutIntervall(10000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -344,7 +344,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandPowerDescriptorRequest(q
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypePowerDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypePowerDescriptorResponse);
|
||||
request.setDescription("Node power descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -359,7 +359,24 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandUserDescriptorRequest(qu
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeUserDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeUserDescriptorResponse);
|
||||
request.setDescription("Node user descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress) + " " + ZigbeeUtils::convertUint16ToHexString(address));
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
|
||||
ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandFactoryResetNode(quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(0x02);
|
||||
stream << shortAddress;
|
||||
stream << sourceEndpoint;
|
||||
stream << destinationEndpoint;
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageBasicResetFactoryDefaults, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageBasicResetFactoryDefaultsResponse);
|
||||
request.setDescription("Factory reset node " + ZigbeeUtils::convertUint16ToHexString(shortAddress) + " " + ZigbeeUtils::convertByteToHexString(destinationEndpoint));
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -398,44 +415,41 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandReadAttributeRequest(qui
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeReadAttributeRequest, data));
|
||||
//request.setExpectedAdditionalMessageType(Zigbee::MessageTypeReadAttributeResponse);
|
||||
request.setDescription("Read attribute request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
|
||||
ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandConfigureReportingRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, QList<quint16> attributes, bool manufacturerSpecific, quint16 manufacturerId)
|
||||
ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandConfigureReportingRequest(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, ZigbeeCluster *cluster, quint8 direction, bool manufacturerSpecific, quint16 manufacturerId, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << addressMode;
|
||||
stream << shortAddress;
|
||||
stream << sourceEndpoint;
|
||||
stream << destinationEndpoint;
|
||||
stream << static_cast<quint16>(cluster->clusterId());
|
||||
stream << addressMode; // [0]
|
||||
stream << shortAddress; // [1] [2]
|
||||
stream << sourceEndpoint; // [3]
|
||||
stream << destinationEndpoint; // [4]
|
||||
stream << static_cast<quint16>(cluster->clusterId()); // [5] [6]
|
||||
|
||||
// 0: server -> client, 1: client -> server
|
||||
if (cluster->direction() == ZigbeeCluster::Input) {
|
||||
stream << static_cast<quint8>(1);
|
||||
} else {
|
||||
stream << static_cast<quint8>(0);
|
||||
}
|
||||
|
||||
if (manufacturerSpecific) {
|
||||
stream << static_cast<quint8>(1);
|
||||
} else {
|
||||
stream << static_cast<quint8>(0);
|
||||
}
|
||||
|
||||
stream << manufacturerId;
|
||||
stream << static_cast<quint8>(attributes.count());
|
||||
for (int i = 0; i < attributes.count(); i++) {
|
||||
stream << attributes.at(i);
|
||||
stream << direction;// [7]
|
||||
stream << static_cast<quint8>(manufacturerSpecific); // [8]
|
||||
stream << manufacturerId; // [9] [10]
|
||||
stream << static_cast<quint8>(reportConfigurations.count()); // [11]
|
||||
for (int i = 0; i < reportConfigurations.count(); i++) {
|
||||
// Configuration report
|
||||
stream << reportConfigurations.at(i).direction;
|
||||
stream << static_cast<quint8>(reportConfigurations.at(i).dataType);
|
||||
stream << reportConfigurations.at(i).attributeId;
|
||||
stream << reportConfigurations.at(i).minInterval;
|
||||
stream << reportConfigurations.at(i).maxInterval;
|
||||
stream << reportConfigurations.at(i).timeout;
|
||||
stream << reportConfigurations.at(i).change;
|
||||
}
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeConfigReportingRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeConfigReportingResponse);
|
||||
request.setDescription("Configure reporting request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
@ -452,7 +466,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandIdentify(quint8 addressM
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeIdentifySend, data));
|
||||
request.setDescription("Identify request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
|
||||
request.setTimoutIntervall(5000);
|
||||
request.setTimoutIntervall(12000);
|
||||
|
||||
return sendRequest(request);
|
||||
}
|
||||
|
||||
@ -77,8 +77,10 @@ public:
|
||||
ZigbeeInterfaceReply *commandPowerDescriptorRequest(quint16 shortAddress);
|
||||
ZigbeeInterfaceReply *commandUserDescriptorRequest(quint16 shortAddress, quint16 address);
|
||||
|
||||
ZigbeeInterfaceReply *commandFactoryResetNode(quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint);
|
||||
|
||||
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, 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 *commandIdentify(quint8 addressMode, quint16 shortAddress, quint8 sourceEndpoint, quint8 destinationEndpoint, quint16 duration);
|
||||
|
||||
ZigbeeInterfaceReply *commandBindGroup(const ZigbeeAddress &sourceAddress, quint8 sourceEndpoint, quint16 clusterId, quint16 destinationAddress, quint8 destinationEndpoint);
|
||||
|
||||
@ -131,7 +131,7 @@ void ZigbeeNetworkNxp::setStartingState(ZigbeeNetworkNxp::StartingState state)
|
||||
if (channel() == 0) {
|
||||
qCDebug(dcZigbeeNetwork()) << "Autoselect quitest channel for the zigbee network. FIXME: currently hardcoded to 13 due to firmware error.";
|
||||
quint32 channelMask = 0;
|
||||
channelMask |= 1 << (13);
|
||||
channelMask |= 1 << (14);
|
||||
reply = m_controller->commandSetChannelMask(channelMask);
|
||||
} else {
|
||||
quint32 channelMask = 0;
|
||||
@ -675,19 +675,22 @@ void ZigbeeNetworkNxp::processAttributeReport(const ZigbeeInterfaceMessage &mess
|
||||
break;
|
||||
}
|
||||
|
||||
ZigbeeNode *node = getZigbeeNode(sourceAddress);
|
||||
ZigbeeNodeNxp *node = qobject_cast<ZigbeeNodeNxp *>(getZigbeeNode(sourceAddress));
|
||||
if (!node) {
|
||||
qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data.";
|
||||
return;
|
||||
}
|
||||
|
||||
ZigbeeNodeEndpointNxp *endpoint = qobject_cast<ZigbeeNodeEndpointNxp *>(node->getEndpoint(endpointId));
|
||||
if (!endpoint) {
|
||||
qCWarning(dcZigbeeNetwork()) << "There is no endpoint for this attribute report.";
|
||||
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;
|
||||
|
||||
endpoint->setClusterAttribute(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeClusterAttribute(attributeId, dataType, attributeData));
|
||||
node->setClusterAttributeReport(attributeReport);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkNxp::processReadAttributeResponse(const ZigbeeInterfaceMessage &message)
|
||||
@ -751,19 +754,23 @@ void ZigbeeNetworkNxp::processReadAttributeResponse(const ZigbeeInterfaceMessage
|
||||
break;
|
||||
}
|
||||
|
||||
ZigbeeNode *node = getZigbeeNode(sourceAddress);
|
||||
|
||||
ZigbeeNodeNxp *node = qobject_cast<ZigbeeNodeNxp *>(getZigbeeNode(sourceAddress));
|
||||
if (!node) {
|
||||
qCWarning(dcZigbeeNode()) << "Received an attribute report from an unknown node. Ignoring data.";
|
||||
return;
|
||||
}
|
||||
|
||||
ZigbeeNodeEndpointNxp *endpoint = qobject_cast<ZigbeeNodeEndpointNxp *>(node->getEndpoint(endpointId));
|
||||
if (!endpoint) {
|
||||
qCWarning(dcZigbeeNetwork()) << "There is no endpoint for this attribute report.";
|
||||
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;
|
||||
|
||||
endpoint->setClusterAttribute(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeClusterAttribute(attributeId, dataType, attributeData));
|
||||
node->setClusterAttributeReport(attributeReport);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkNxp::processLeaveIndication(const ZigbeeInterfaceMessage &message)
|
||||
|
||||
@ -57,12 +57,12 @@ ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::readAttribute(ZigbeeCluster *cluster,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::configureReporting(ZigbeeCluster *cluster, QList<quint16> attributes)
|
||||
ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations)
|
||||
{
|
||||
qCDebug(dcZigbeeNode()) << "Configure reporting" << node() << cluster << attributes;
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandConfigureReportingRequest(0x00, node()->shortAddress(), 0x01,
|
||||
endpointId(), cluster, attributes,
|
||||
false, node()->manufacturerCode());
|
||||
qCDebug(dcZigbeeNode()) << "Configure reporting" << node();
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandConfigureReportingRequest(0x02, node()->shortAddress(), 0x01,
|
||||
endpointId(), cluster, 0x01,
|
||||
false, node()->manufacturerCode(), reportConfigurations);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){
|
||||
reply->deleteLater();
|
||||
|
||||
@ -95,6 +95,24 @@ ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::identify(quint16 seconds)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::factoryReset()
|
||||
{
|
||||
qCDebug(dcZigbeeNode()) << "Factory reset" << this;
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandFactoryResetNode(node()->shortAddress(), 0x01, endpointId());
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||
});
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::bindGroup(Zigbee::ClusterId clusterId, quint16 destinationAddress, quint8 destinationEndpoint)
|
||||
{
|
||||
qCDebug(dcZigbeeNode()) << "Bind group" << node() << clusterId << ZigbeeUtils::convertUint16ToHexString(destinationAddress) << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
|
||||
@ -291,10 +309,31 @@ ZigbeeNetworkReply *ZigbeeNodeEndpointNxp::sendMoveToSaturation(quint8 saturatio
|
||||
|
||||
void ZigbeeNodeEndpointNxp::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
foreach (ZigbeeCluster *cluster, m_inputClusters) {
|
||||
if (cluster->clusterId() == clusterId) {
|
||||
cluster->setAttribute(attribute);
|
||||
emit clusterAttributeChanged(cluster, attribute);
|
||||
}
|
||||
// Check if this cluster is an input cluster
|
||||
if (hasInputCluster(clusterId)) {
|
||||
ZigbeeCluster *cluster = getInputCluster(clusterId);
|
||||
cluster->setAttribute(attribute);
|
||||
emit clusterAttributeChanged(cluster, attribute);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this cluster is an output cluster
|
||||
if (hasOutputCluster(clusterId)) {
|
||||
ZigbeeCluster *cluster = getOutputCluster(clusterId);
|
||||
cluster->setAttribute(attribute);
|
||||
emit clusterAttributeChanged(cluster, attribute);
|
||||
return;
|
||||
}
|
||||
|
||||
// There is no cluster yet. Create it as output cluster if this is not the basic cluster
|
||||
ZigbeeCluster *cluster = nullptr;
|
||||
if (clusterId == Zigbee::ClusterIdBasic) {
|
||||
cluster = new ZigbeeCluster(clusterId, ZigbeeCluster::Input, this);
|
||||
addInputCluster(cluster);
|
||||
} else {
|
||||
cluster = new ZigbeeCluster(clusterId, ZigbeeCluster::Output, this);
|
||||
addOutputCluster(cluster);
|
||||
}
|
||||
cluster->setAttribute(attribute);
|
||||
emit clusterAttributeChanged(cluster, attribute);
|
||||
}
|
||||
|
||||
@ -44,8 +44,10 @@ public:
|
||||
explicit ZigbeeNodeEndpointNxp(ZigbeeBridgeControllerNxp *controller, ZigbeeNode *node, quint8 endpoint, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeNetworkReply *readAttribute(ZigbeeCluster *cluster, QList<quint16> attributes) override;
|
||||
ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList<quint16> attributes) override;
|
||||
ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations) override;
|
||||
|
||||
ZigbeeNetworkReply *identify(quint16 seconds) override;
|
||||
ZigbeeNetworkReply *factoryReset() override;
|
||||
ZigbeeNetworkReply *bindGroup(Zigbee::ClusterId clusterId, quint16 destinationAddress, quint8 destinationEndpoint) override;
|
||||
ZigbeeNetworkReply *bindUnicast(Zigbee::ClusterId clusterId, const ZigbeeAddress &destinationAddress, quint8 destinationEndpoint) override;
|
||||
ZigbeeNetworkReply *sendOnOffClusterCommand(ZigbeeCluster::OnOffClusterCommand command) override;
|
||||
|
||||
@ -177,7 +177,12 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
||||
quint8 deviceVersion = (bitField >> 4);
|
||||
qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertByteToHexString(bitField) << deviceVersion;
|
||||
|
||||
ZigbeeNodeEndpointNxp *endpoint = new ZigbeeNodeEndpointNxp(m_controller, this, endpointId, this);
|
||||
ZigbeeNodeEndpointNxp *endpoint = qobject_cast<ZigbeeNodeEndpointNxp *>(getEndpoint(endpointId));
|
||||
if (!endpoint) {
|
||||
endpoint = new ZigbeeNodeEndpointNxp(m_controller, this, endpointId, this);
|
||||
m_endpoints.append(endpoint);
|
||||
}
|
||||
|
||||
endpoint->setProfile(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||
endpoint->setDeviceId(deviceId);
|
||||
endpoint->setDeviceVersion(deviceVersion);
|
||||
@ -187,7 +192,9 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
||||
for (int i = 0; i < inputClusterCount; i+=1) {
|
||||
quint16 clusterId = 0;
|
||||
stream >> clusterId;
|
||||
endpoint->addInputCluster(new ZigbeeCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input, endpoint));
|
||||
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||
endpoint->addInputCluster(new ZigbeeCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input, endpoint));
|
||||
}
|
||||
qCDebug(dcZigbeeNetwork()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||
}
|
||||
|
||||
@ -201,11 +208,11 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
||||
|
||||
quint16 clusterId = 0;
|
||||
stream >> clusterId;
|
||||
endpoint->addOutputCluster(new ZigbeeCluster(static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
||||
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||
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));
|
||||
}
|
||||
|
||||
m_endpoints.append(endpoint);
|
||||
}
|
||||
|
||||
m_uninitializedEndpoints.removeAll(endpointId);
|
||||
@ -217,23 +224,16 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
||||
}
|
||||
break;
|
||||
case InitStateReadClusterAttributes:
|
||||
if (shortAddress() == 0x0000) {
|
||||
qCDebug(dcZigbeeNode()) << "No need to read the endpoint baisc clusters of the coordinator node";
|
||||
setState(StateInitialized);
|
||||
break;
|
||||
}
|
||||
|
||||
// if (shortAddress() == 0x0000) {
|
||||
// qCDebug(dcZigbeeNode()) << "No need to read the endpoint baisc clusters of the coordinator node";
|
||||
// setState(StateInitialized);
|
||||
// break;
|
||||
// }
|
||||
|
||||
foreach (ZigbeeNodeEndpoint *endpoint, m_endpoints) {
|
||||
|
||||
// Read basic cluster
|
||||
qCDebug(dcZigbeeNode()) << "Read basic cluster for endpoint" << endpoint;
|
||||
QList<quint16> attributes;
|
||||
attributes.append(ZigbeeCluster::BasicAttributeZclVersion);
|
||||
attributes.append(ZigbeeCluster::BasicAttributeManufacturerName);
|
||||
attributes.append(ZigbeeCluster::BasicAttributeModelIdentifier);
|
||||
attributes.append(ZigbeeCluster::BasicAttributePowerSource);
|
||||
attributes.append(ZigbeeCluster::BasicAttributeSwBuildId);
|
||||
|
||||
ZigbeeCluster *basicCluster = endpoint->getInputCluster(Zigbee::ClusterIdBasic);
|
||||
if (!basicCluster) {
|
||||
@ -242,46 +242,29 @@ void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
|
||||
return;
|
||||
}
|
||||
|
||||
QList<quint16> attributes;
|
||||
attributes.append(ZigbeeCluster::BasicAttributeZclVersion);
|
||||
attributes.append(ZigbeeCluster::BasicAttributeManufacturerName);
|
||||
// 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.
|
||||
if (!basicCluster->hasAttribute(ZigbeeCluster::BasicAttributeModelIdentifier))
|
||||
attributes.append(ZigbeeCluster::BasicAttributeModelIdentifier);
|
||||
|
||||
attributes.append(ZigbeeCluster::BasicAttributePowerSource);
|
||||
attributes.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](){
|
||||
reply->deleteLater();
|
||||
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
||||
}
|
||||
|
||||
|
||||
// QList<quint16> attributes;
|
||||
// attributes.append(ZigbeeCluster::BasicAttributePowerSource);
|
||||
// attributes.append(ZigbeeCluster::BasicAttributeLocationDescription);
|
||||
// attributes.append(ZigbeeCluster::BasicAttributePhysicalEnvironment);
|
||||
// attributes.append(ZigbeeCluster::BasicAttributeDeviceEnabled);
|
||||
// attributes.append(ZigbeeCluster::BasicAttributeAlarmMask);
|
||||
// attributes.append(ZigbeeCluster::BasicAttributeDisableLocalConfig);
|
||||
// attributes.append(ZigbeeCluster::BasicAttributeSwBuildId);
|
||||
|
||||
|
||||
// ZigbeeInterfaceReply *reply2 = m_controller->commandReadAttributeRequest(0x02, shortAddress(),
|
||||
// 0x01, endpoint->endpointId(),
|
||||
// basicCluster,
|
||||
// attributes,
|
||||
// false,
|
||||
// manufacturerCode());
|
||||
// connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply2, endpoint](){
|
||||
// reply2->deleteLater();
|
||||
// if (reply2->status() != ZigbeeInterfaceReply::Success) {
|
||||
// qCWarning(dcZigbeeController()) << "Could not" << reply2->request().description() << reply2->status() << reply2->statusErrorMessage();
|
||||
// }
|
||||
|
||||
// });
|
||||
|
||||
|
||||
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Reading basic cluster attributes finished successfully for" << endpoint;
|
||||
qCDebug(dcZigbeeNode()) << "The device should response with multiple attribute read notifications.";
|
||||
setState(StateInitialized);
|
||||
@ -303,3 +286,20 @@ ZigbeeNodeEndpoint *ZigbeeNodeNxp::createNodeEndpoint(quint8 endpointId, QObject
|
||||
{
|
||||
return new ZigbeeNodeEndpointNxp(m_controller, this, endpointId, parent);
|
||||
}
|
||||
|
||||
void ZigbeeNodeNxp::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report)
|
||||
{
|
||||
if (report.attributeStatus != Zigbee::ZigbeeStatusSuccess) {
|
||||
qCWarning(dcZigbeeNode()) << this << "Got incalid status report" << report.endpointId << report.clusterId << report.attributeId << report.attributeStatus;
|
||||
return;
|
||||
}
|
||||
|
||||
ZigbeeNodeEndpointNxp *endpoint = qobject_cast<ZigbeeNodeEndpointNxp *>(getEndpoint(report.endpointId));
|
||||
if (!endpoint) {
|
||||
qCDebug(dcZigbeeNetwork()) << "Recived attribute report but there is no endpoint on this node yet. Create it...";
|
||||
endpoint = new ZigbeeNodeEndpointNxp(m_controller, this, report.endpointId, this);
|
||||
m_endpoints.append(endpoint);
|
||||
}
|
||||
|
||||
endpoint->setClusterAttribute(report.clusterId, ZigbeeClusterAttribute(report.attributeId, report.dataType, report.data));
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "zigbeenode.h"
|
||||
#include "zigbeenodeendpointnxp.h"
|
||||
#include "zigbeebridgecontrollernxp.h"
|
||||
|
||||
class ZigbeeNodeNxp : public ZigbeeNode
|
||||
@ -59,6 +60,7 @@ private:
|
||||
QList<quint8> m_uninitializedEndpoints;
|
||||
|
||||
void setInitState(InitState initState);
|
||||
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
|
||||
|
||||
protected:
|
||||
void startInitialization() override;
|
||||
|
||||
@ -27,13 +27,14 @@
|
||||
|
||||
#include "zigbeeutils.h"
|
||||
#include "zigbeecluster.h"
|
||||
#include "loggingcategory.h"
|
||||
|
||||
ZigbeeCluster::ZigbeeCluster(Zigbee::ClusterId clusterId, Direction direction, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_clusterId(clusterId),
|
||||
m_direction(direction)
|
||||
{
|
||||
|
||||
qCDebug(dcZigbeeCluster()) << "Create cluster" << ZigbeeUtils::convertUint16ToHexString(clusterId) << direction;
|
||||
}
|
||||
|
||||
ZigbeeCluster::Direction ZigbeeCluster::direction() const
|
||||
@ -71,10 +72,12 @@ ZigbeeClusterAttribute ZigbeeCluster::attribute(quint16 id)
|
||||
|
||||
void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
if (hasAttribute(attribute.id())) {
|
||||
if (hasAttribute(attribute.id())) {
|
||||
qCDebug(dcZigbeeCluster()) << this << "update attribute" << attribute;
|
||||
m_attributes[attribute.id()] = attribute;
|
||||
emit attributeChanged(attribute);
|
||||
} else {
|
||||
qCDebug(dcZigbeeCluster()) << this << "add attribute" << attribute;
|
||||
m_attributes.insert(attribute.id(), attribute);
|
||||
emit attributeChanged(attribute);
|
||||
}
|
||||
|
||||
@ -33,6 +33,27 @@
|
||||
#include "zigbee.h"
|
||||
#include "zigbeeclusterattribute.h"
|
||||
|
||||
struct ZigbeeClusterReportConfigurationRecord {
|
||||
quint8 direction;
|
||||
Zigbee::DataType dataType;
|
||||
quint16 attributeId;
|
||||
quint16 minInterval;
|
||||
quint16 maxInterval;
|
||||
quint16 timeout;
|
||||
quint8 change;
|
||||
};
|
||||
|
||||
struct ZigbeeClusterAttributeReport {
|
||||
quint16 sourceAddress;
|
||||
quint8 endpointId;
|
||||
Zigbee::ClusterId clusterId;
|
||||
quint16 attributeId;
|
||||
Zigbee::ZigbeeStatus attributeStatus;
|
||||
Zigbee::DataType dataType;
|
||||
QByteArray data;
|
||||
};
|
||||
|
||||
|
||||
class ZigbeeCluster : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -199,6 +199,8 @@ private:
|
||||
bool m_extendedActiveEndpointListAvailable = false;
|
||||
bool m_extendedSimpleDescriptorListAvailable = false;
|
||||
|
||||
virtual void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) = 0;
|
||||
|
||||
protected:
|
||||
ZigbeeNode(QObject *parent = nullptr);
|
||||
|
||||
|
||||
@ -75,11 +75,14 @@ public:
|
||||
|
||||
// Attribute methods
|
||||
virtual ZigbeeNetworkReply *readAttribute(ZigbeeCluster *cluster, QList<quint16> attributes) = 0;
|
||||
virtual ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList<quint16> attributes) = 0;
|
||||
virtual ZigbeeNetworkReply *configureReporting(ZigbeeCluster *cluster, QList<ZigbeeClusterReportConfigurationRecord> reportConfigurations) = 0;
|
||||
|
||||
// Identify
|
||||
virtual ZigbeeNetworkReply *identify(quint16 seconds) = 0;
|
||||
|
||||
// Reset
|
||||
virtual ZigbeeNetworkReply *factoryReset() = 0;
|
||||
|
||||
// Binding
|
||||
virtual ZigbeeNetworkReply *bindGroup(Zigbee::ClusterId clusterId, quint16 destinationAddress, quint8 destinationEndpoint) = 0;
|
||||
virtual ZigbeeNetworkReply *bindUnicast(Zigbee::ClusterId clusterId, const ZigbeeAddress &destinationAddress, quint8 destinationEndpoint) = 0;
|
||||
|
||||
@ -416,8 +416,7 @@ QColor ZigbeeUtils::interpolateColorFromColorTemperature(int colorTemperature, i
|
||||
int intervalSize = maxValue - minValue;
|
||||
int intervalPosition = colorTemperature - minValue;
|
||||
double percentage = intervalPosition * 1.0 / intervalSize;
|
||||
//qWarning() << "Interpolate color" << intervalSize << intervalPosition << percentage;
|
||||
int closestColorIndex = qRound((colorTemperatureScale.count() - 1) * (1.0 - percentage));
|
||||
//qWarning() << "Colors size" << colorTemperatureScale.count() << "Color position according to percentage" << closestColorIndex;
|
||||
// FIXME: interpolate between the selected index and the next color for more accuracy if required
|
||||
return colorTemperatureScale.at(closestColorIndex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user