Merge PR #15: Add develco profile and manufacturer and manufacturer specific cluster methods
This commit is contained in:
commit
0a63e2f101
@ -34,8 +34,26 @@ ZigbeeClusterBinaryInput::ZigbeeClusterBinaryInput(ZigbeeNetwork *network, Zigbe
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ZigbeeClusterBinaryInput::presentValue() const
|
||||||
|
{
|
||||||
|
return m_presentValue;
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeClusterBinaryInput::setAttribute(const ZigbeeClusterAttribute &attribute)
|
void ZigbeeClusterBinaryInput::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);
|
||||||
|
|
||||||
|
// Parse the information for convenience
|
||||||
|
if (attribute.id() == AttributePresentValue) {
|
||||||
|
bool valueOk = false;
|
||||||
|
bool value = attribute.dataType().toBool(&valueOk);
|
||||||
|
if (valueOk) {
|
||||||
|
m_presentValue = value;
|
||||||
|
qCDebug(dcZigbeeCluster()) << "Binary input state changed on" << m_node << m_endpoint << this << m_presentValue;
|
||||||
|
emit presentValueChanged(m_presentValue);
|
||||||
|
} else {
|
||||||
|
qCWarning(dcZigbeeCluster()) << "Failed to parse attribute data" << m_node << m_endpoint << this << attribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,14 @@ public:
|
|||||||
|
|
||||||
explicit ZigbeeClusterBinaryInput(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
explicit ZigbeeClusterBinaryInput(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
bool presentValue() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void presentValueChanged(bool presentValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_presentValue = false;
|
||||||
|
|
||||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -51,6 +51,11 @@ void ZigbeeClusterIlluminanceMeasurment::setAttribute(const ZigbeeClusterAttribu
|
|||||||
bool valueOk = false;
|
bool valueOk = false;
|
||||||
quint16 value = attribute.dataType().toUInt16(&valueOk);
|
quint16 value = attribute.dataType().toUInt16(&valueOk);
|
||||||
if (valueOk) {
|
if (valueOk) {
|
||||||
|
if (value == 0xffff) {
|
||||||
|
qCDebug(dcZigbeeCluster()) << m_node << m_endpoint << this << "received invalid measurement value. Not updating the attribute.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_illuminance = value;
|
m_illuminance = value;
|
||||||
qCDebug(dcZigbeeCluster()) << "Illuminance changed on" << m_node << m_endpoint << this << m_illuminance << "lux";
|
qCDebug(dcZigbeeCluster()) << "Illuminance changed on" << m_node << m_endpoint << this << m_illuminance << "lux";
|
||||||
emit illuminanceChanged(m_illuminance);
|
emit illuminanceChanged(m_illuminance);
|
||||||
|
|||||||
@ -56,6 +56,11 @@ void ZigbeeClusterPressureMeasurement::setAttribute(const ZigbeeClusterAttribute
|
|||||||
bool valueOk = false;
|
bool valueOk = false;
|
||||||
qint16 value = attribute.dataType().toInt16(&valueOk);
|
qint16 value = attribute.dataType().toInt16(&valueOk);
|
||||||
if (valueOk) {
|
if (valueOk) {
|
||||||
|
if (value == static_cast<qint16>(0x8000)) {
|
||||||
|
qCDebug(dcZigbeeCluster()) << m_node << m_endpoint << this << "received invalid measurement value. Not updating the attribute.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_pressure = value / 10.0;
|
m_pressure = value / 10.0;
|
||||||
qCDebug(dcZigbeeCluster()) << "Pressure changed on" << m_node << m_endpoint << this << m_pressure << "kPa";
|
qCDebug(dcZigbeeCluster()) << "Pressure changed on" << m_node << m_endpoint << this << m_pressure << "kPa";
|
||||||
emit pressureChanged(m_pressure);
|
emit pressureChanged(m_pressure);
|
||||||
@ -64,6 +69,11 @@ void ZigbeeClusterPressureMeasurement::setAttribute(const ZigbeeClusterAttribute
|
|||||||
bool valueOk = false;
|
bool valueOk = false;
|
||||||
qint16 value = attribute.dataType().toInt16(&valueOk);
|
qint16 value = attribute.dataType().toInt16(&valueOk);
|
||||||
if (valueOk) {
|
if (valueOk) {
|
||||||
|
if (value == static_cast<qint16>(0x8000)) {
|
||||||
|
qCDebug(dcZigbeeCluster()) << m_node << m_endpoint << this << "received invalid measurement value. Not updating the attribute.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_pressureScaled = value / 10.0;
|
m_pressureScaled = value / 10.0;
|
||||||
qCDebug(dcZigbeeCluster()) << "Pressure scaled changed on" << m_node << m_endpoint << this << m_pressureScaled << "Pa";
|
qCDebug(dcZigbeeCluster()) << "Pressure scaled changed on" << m_node << m_endpoint << this << m_pressureScaled << "Pa";
|
||||||
emit pressureScaledChanged(m_pressureScaled);
|
emit pressureScaledChanged(m_pressureScaled);
|
||||||
|
|||||||
@ -51,6 +51,11 @@ void ZigbeeClusterRelativeHumidityMeasurement::setAttribute(const ZigbeeClusterA
|
|||||||
bool valueOk = false;
|
bool valueOk = false;
|
||||||
quint16 value = attribute.dataType().toUInt16(&valueOk);
|
quint16 value = attribute.dataType().toUInt16(&valueOk);
|
||||||
if (valueOk) {
|
if (valueOk) {
|
||||||
|
if (value == 0xffff) {
|
||||||
|
qCDebug(dcZigbeeCluster()) << m_node << m_endpoint << this << "received invalid measurement value. Not updating the attribute.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_humidity = value / 100.0;
|
m_humidity = value / 100.0;
|
||||||
qCDebug(dcZigbeeCluster()) << "Humidity changed on" << m_node << m_endpoint << this << m_humidity << "%";
|
qCDebug(dcZigbeeCluster()) << "Humidity changed on" << m_node << m_endpoint << this << m_humidity << "%";
|
||||||
emit humidityChanged(m_humidity);
|
emit humidityChanged(m_humidity);
|
||||||
|
|||||||
@ -51,6 +51,11 @@ void ZigbeeClusterTemperatureMeasurement::setAttribute(const ZigbeeClusterAttrib
|
|||||||
bool valueOk = false;
|
bool valueOk = false;
|
||||||
qint16 value = attribute.dataType().toInt16(&valueOk);
|
qint16 value = attribute.dataType().toInt16(&valueOk);
|
||||||
if (valueOk) {
|
if (valueOk) {
|
||||||
|
if (value == static_cast<qint16>(0x8000)) {
|
||||||
|
qCDebug(dcZigbeeCluster()) << m_node << m_endpoint << this << "received invalid measurement value. Not updating the attribute.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_temperature = value / 100.0;
|
m_temperature = value / 100.0;
|
||||||
qCDebug(dcZigbeeCluster()) << "Temperature changed on" << m_node << m_endpoint << this << m_temperature << "°C";
|
qCDebug(dcZigbeeCluster()) << "Temperature changed on" << m_node << m_endpoint << this << m_temperature << "°C";
|
||||||
emit temperatureChanged(m_temperature);
|
emit temperatureChanged(m_temperature);
|
||||||
|
|||||||
@ -96,7 +96,7 @@ void ZigbeeCluster::setAttribute(const ZigbeeClusterAttribute &attribute)
|
|||||||
updateOrAddAttribute(attribute);
|
updateOrAddAttribute(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes, quint16 manufacturerCode)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeCluster()) << "Read attributes from" << m_node << m_endpoint << this << attributes;
|
qCDebug(dcZigbeeCluster()) << "Read attributes from" << m_node << m_endpoint << this << attributes;
|
||||||
|
|
||||||
@ -108,10 +108,10 @@ ZigbeeClusterReply *ZigbeeCluster::readAttributes(QList<quint16> attributes)
|
|||||||
stream << attribute;
|
stream << attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
return executeGlobalCommand(ZigbeeClusterLibrary::CommandReadAttributes, payload);
|
return executeGlobalCommand(ZigbeeClusterLibrary::CommandReadAttributes, payload, manufacturerCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterReply *ZigbeeCluster::writeAttributes(QList<ZigbeeClusterLibrary::WriteAttributeRecord> writeAttributeRecords)
|
ZigbeeClusterReply *ZigbeeCluster::writeAttributes(QList<ZigbeeClusterLibrary::WriteAttributeRecord> writeAttributeRecords, quint16 manufacturerCode)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeCluster()) << "Write attributes on" << m_node << m_endpoint << this;
|
qCDebug(dcZigbeeCluster()) << "Write attributes on" << m_node << m_endpoint << this;
|
||||||
QByteArray payload;
|
QByteArray payload;
|
||||||
@ -119,10 +119,10 @@ ZigbeeClusterReply *ZigbeeCluster::writeAttributes(QList<ZigbeeClusterLibrary::W
|
|||||||
payload += ZigbeeClusterLibrary::buildWriteAttributeRecord(writeAttributeRecord);
|
payload += ZigbeeClusterLibrary::buildWriteAttributeRecord(writeAttributeRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
return executeGlobalCommand(ZigbeeClusterLibrary::CommandWriteAttributes, payload);
|
return executeGlobalCommand(ZigbeeClusterLibrary::CommandWriteAttributes, payload, manufacturerCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeClusterReply *ZigbeeCluster::configureReporting(QList<ZigbeeClusterLibrary::AttributeReportingConfiguration> reportingConfigurations)
|
ZigbeeClusterReply *ZigbeeCluster::configureReporting(QList<ZigbeeClusterLibrary::AttributeReportingConfiguration> reportingConfigurations, quint16 manufacturerCode)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeCluster()) << "Configure reporting on" << m_node << m_endpoint << this << reportingConfigurations;
|
qCDebug(dcZigbeeCluster()) << "Configure reporting on" << m_node << m_endpoint << this << reportingConfigurations;
|
||||||
|
|
||||||
@ -131,11 +131,11 @@ ZigbeeClusterReply *ZigbeeCluster::configureReporting(QList<ZigbeeClusterLibrary
|
|||||||
payload += ZigbeeClusterLibrary::buildAttributeReportingConfiguration(reportingConfiguration);
|
payload += ZigbeeClusterLibrary::buildAttributeReportingConfiguration(reportingConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
return executeGlobalCommand(ZigbeeClusterLibrary::CommandConfigureReporting, payload);
|
return executeGlobalCommand(ZigbeeClusterLibrary::CommandConfigureReporting, payload, manufacturerCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZigbeeClusterReply *ZigbeeCluster::executeGlobalCommand(quint8 command, const QByteArray &payload)
|
ZigbeeClusterReply *ZigbeeCluster::executeGlobalCommand(quint8 command, const QByteArray &payload, quint16 manufacturerCode)
|
||||||
{
|
{
|
||||||
// Build the request
|
// Build the request
|
||||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||||
@ -145,7 +145,12 @@ ZigbeeClusterReply *ZigbeeCluster::executeGlobalCommand(quint8 command, const QB
|
|||||||
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
||||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeGlobal;
|
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeGlobal;
|
||||||
frameControl.manufacturerSpecific = false;
|
if (manufacturerCode != 0) {
|
||||||
|
frameControl.manufacturerSpecific = true;
|
||||||
|
} else {
|
||||||
|
frameControl.manufacturerSpecific = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_direction == Direction::Server) {
|
if (m_direction == Direction::Server) {
|
||||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||||
} else {
|
} else {
|
||||||
@ -157,6 +162,9 @@ ZigbeeClusterReply *ZigbeeCluster::executeGlobalCommand(quint8 command, const QB
|
|||||||
ZigbeeClusterLibrary::Header header;
|
ZigbeeClusterLibrary::Header header;
|
||||||
header.frameControl = frameControl;
|
header.frameControl = frameControl;
|
||||||
header.command = command;
|
header.command = command;
|
||||||
|
if (manufacturerCode != 0) {
|
||||||
|
header.manufacturerCode = manufacturerCode;
|
||||||
|
}
|
||||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||||
|
|
||||||
// Put them together
|
// Put them together
|
||||||
@ -186,7 +194,6 @@ ZigbeeClusterReply *ZigbeeCluster::executeGlobalCommand(quint8 command, const QB
|
|||||||
return zclReply;
|
return zclReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZigbeeClusterReply *ZigbeeCluster::createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame)
|
ZigbeeClusterReply *ZigbeeCluster::createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame)
|
||||||
{
|
{
|
||||||
ZigbeeClusterReply *zclReply = new ZigbeeClusterReply(request, frame, this);
|
ZigbeeClusterReply *zclReply = new ZigbeeClusterReply(request, frame, this);
|
||||||
@ -394,7 +401,7 @@ void ZigbeeCluster::finishZclReply(ZigbeeClusterReply *zclReply)
|
|||||||
m_pendingReplies.remove(zclReply->transactionSequenceNumber());
|
m_pendingReplies.remove(zclReply->transactionSequenceNumber());
|
||||||
qCDebug(dcZigbeeCluster()) << "ZigbeeClusterReply finished" << zclReply->request() << zclReply->requestFrame() << zclReply->responseFrame();
|
qCDebug(dcZigbeeCluster()) << "ZigbeeClusterReply finished" << zclReply->request() << zclReply->requestFrame() << zclReply->responseFrame();
|
||||||
// FIXME: Set the status
|
// FIXME: Set the status
|
||||||
zclReply->finished();
|
emit zclReply->finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeCluster::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
void ZigbeeCluster::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
||||||
|
|||||||
@ -90,12 +90,9 @@ public:
|
|||||||
ZigbeeClusterAttribute attribute(quint16 attributeId);
|
ZigbeeClusterAttribute attribute(quint16 attributeId);
|
||||||
|
|
||||||
// ZCL global commands
|
// ZCL global commands
|
||||||
ZigbeeClusterReply *readAttributes(QList<quint16> attributes);
|
ZigbeeClusterReply *readAttributes(QList<quint16> attributes, quint16 manufacturerCode = 0x0000);
|
||||||
ZigbeeClusterReply *writeAttributes(QList<ZigbeeClusterLibrary::WriteAttributeRecord> writeAttributeRecords);
|
ZigbeeClusterReply *writeAttributes(QList<ZigbeeClusterLibrary::WriteAttributeRecord> writeAttributeRecords, quint16 manufacturerCode = 0x0000);
|
||||||
ZigbeeClusterReply *configureReporting(QList<ZigbeeClusterLibrary::AttributeReportingConfiguration> reportingConfigurations);
|
ZigbeeClusterReply *configureReporting(QList<ZigbeeClusterLibrary::AttributeReportingConfiguration> reportingConfigurations, quint16 manufacturerCode = 0x0000);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ZigbeeNetwork *m_network = nullptr;
|
ZigbeeNetwork *m_network = nullptr;
|
||||||
@ -112,7 +109,8 @@ protected:
|
|||||||
QHash<quint8, ZigbeeClusterReply *> m_pendingReplies;
|
QHash<quint8, ZigbeeClusterReply *> m_pendingReplies;
|
||||||
|
|
||||||
// Global commands
|
// Global commands
|
||||||
ZigbeeClusterReply *executeGlobalCommand(quint8 command, const QByteArray &payload = QByteArray());
|
ZigbeeClusterReply *executeGlobalCommand(quint8 command, const QByteArray &payload = QByteArray(), quint16 manufacturerCode = 0x0000);
|
||||||
|
ZigbeeClusterReply *executeManufacturerSpecificGlobalCommand(quint8 command, quint16 manufacturerCode, const QByteArray &payload = QByteArray());
|
||||||
|
|
||||||
// Cluster specific
|
// Cluster specific
|
||||||
ZigbeeClusterReply *createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame);
|
ZigbeeClusterReply *createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame);
|
||||||
|
|||||||
@ -55,6 +55,7 @@ public:
|
|||||||
ZigbeeProfilePersonalHomeHospitalCare = 0x0108,
|
ZigbeeProfilePersonalHomeHospitalCare = 0x0108,
|
||||||
ZigbeeProfileAdvancedMetering = 0x0109,
|
ZigbeeProfileAdvancedMetering = 0x0109,
|
||||||
ZigbeeProfileLightLink = 0xC05E,
|
ZigbeeProfileLightLink = 0xC05E,
|
||||||
|
ZigbeeProfileDevelco = 0xC0C9,
|
||||||
ZigbeeProfileGreenPower = 0xA1E0
|
ZigbeeProfileGreenPower = 0xA1E0
|
||||||
};
|
};
|
||||||
Q_ENUM(ZigbeeProfile)
|
Q_ENUM(ZigbeeProfile)
|
||||||
@ -286,6 +287,7 @@ public:
|
|||||||
Chipcon = 0x1001,
|
Chipcon = 0x1001,
|
||||||
Ember = 0x1003,
|
Ember = 0x1003,
|
||||||
Philips = 0x100b,
|
Philips = 0x100b,
|
||||||
|
Develco = 0x1015,
|
||||||
Ikea = 0x117C,
|
Ikea = 0x117C,
|
||||||
FeiBit = 0x117E
|
FeiBit = 0x117E
|
||||||
};
|
};
|
||||||
|
|||||||
@ -53,7 +53,6 @@ ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) :
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
m_reachableRefreshTimer = new QTimer(this);
|
m_reachableRefreshTimer = new QTimer(this);
|
||||||
m_reachableRefreshTimer->setInterval(120000);
|
m_reachableRefreshTimer->setInterval(120000);
|
||||||
m_reachableRefreshTimer->setSingleShot(false);
|
m_reachableRefreshTimer->setSingleShot(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user