Implement lqi updating of nodes and finishe on/off and level cluster
parent
cdd7a1a1aa
commit
8f1043ba9f
|
|
@ -341,8 +341,8 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const Zigbee::Apsd
|
|||
return;
|
||||
}
|
||||
|
||||
// Let the node device object handle this (ZDP)
|
||||
node->deviceObject()->processApsDataIndication(indication);
|
||||
// Let the node handle this indication
|
||||
handleNodeIndication(node, indication);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication)
|
||||
|
|
@ -358,8 +358,8 @@ void ZigbeeNetworkDeconz::handleZigbeeClusterLibraryIndication(const Zigbee::Aps
|
|||
// FIXME: maybe remove this node since we might have removed it but it did not respond, or we not explicitly allowed it to join.
|
||||
return;
|
||||
}
|
||||
|
||||
node->handleZigbeeClusterLibraryIndication(indication);
|
||||
// Let the node handle this indication
|
||||
handleNodeIndication(node, indication);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
||||
|
|
|
|||
|
|
@ -140,17 +140,11 @@ void ZigbeeClusterLevelControl::processDataIndication(ZigbeeClusterLibrary::Fram
|
|||
// Read the payload which is
|
||||
Command command = static_cast<Command>(frame.header.command);
|
||||
qCDebug(dcZigbeeCluster()) << "Command sent from" << m_node << m_endpoint << this << command;
|
||||
switch (command) {
|
||||
default:
|
||||
qCWarning(dcZigbeeCluster()) << "Unhandled command sent from" << m_node << m_endpoint << this << command;
|
||||
break;
|
||||
}
|
||||
emit commandSent(command, frame.payload);
|
||||
}
|
||||
break;
|
||||
case Server:
|
||||
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,8 @@ protected:
|
|||
|
||||
signals:
|
||||
void currentLevelChanged(quint8 level);
|
||||
void commandSent(ZigbeeClusterLevelControl::Command command, const QByteArray ¶meter = QByteArray());
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,29 @@ ZigbeeClusterReply *ZigbeeClusterOnOff::commandToggle()
|
|||
return executeClusterCommand(ZigbeeClusterOnOff::CommandToggle);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterOnOff::commandOffWithEffect(ZigbeeClusterOnOff::Effect effect, quint8 effectVariant)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << static_cast<quint8>(effect) << effectVariant;
|
||||
return executeClusterCommand(ZigbeeClusterOnOff::CommandOffWithEffect, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterOnOff::commandOnWithRecallGlobalScene()
|
||||
{
|
||||
return executeClusterCommand(ZigbeeClusterOnOff::CommandOnWithRecallGlobalScene);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterOnOff::commandOnWithTimedOff(bool acceptOnlyWhenOn, quint16 onTime, quint16 offWaitTime)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << static_cast<quint8>(acceptOnlyWhenOn) << onTime << offWaitTime;
|
||||
return executeClusterCommand(ZigbeeClusterOnOff::CommandOnWithTimedOff, payload);
|
||||
}
|
||||
|
||||
void ZigbeeClusterOnOff::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||
|
|
|
|||
|
|
@ -64,14 +64,20 @@ public:
|
|||
};
|
||||
Q_ENUM(Command)
|
||||
|
||||
enum Effect {
|
||||
EffectDelayedAllOff = 0x00,
|
||||
EffectDyingLight = 0x01
|
||||
};
|
||||
Q_ENUM(Effect)
|
||||
|
||||
explicit ZigbeeClusterOnOff(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeClusterReply *commandOff();
|
||||
ZigbeeClusterReply *commandOn();
|
||||
ZigbeeClusterReply *commandToggle();
|
||||
// ZigbeeClusterReply *commandOffWithEffect();
|
||||
// ZigbeeClusterReply *commandOnWithRecallGlobalScene();
|
||||
// ZigbeeClusterReply *commandOnWithTimedOff();
|
||||
ZigbeeClusterReply *commandOffWithEffect(Effect effect, quint8 effectVariant = 0x00);
|
||||
ZigbeeClusterReply *commandOnWithRecallGlobalScene();
|
||||
ZigbeeClusterReply *commandOnWithTimedOff(bool acceptOnlyWhenOn, quint16 onTime, quint16 offWaitTime);
|
||||
|
||||
private:
|
||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||
|
|
|
|||
|
|
@ -224,6 +224,58 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestSimpleDescriptor(quint8 endp
|
|||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestBindIeeeAddress(quint8 sourceEndpointId, quint16 clusterId, const ZigbeeAddress &destinationIeeeAddress, quint8 destinationEndpointId)
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request bind ieee address from" << m_node << "endpoint" << clusterId << "to" << destinationIeeeAddress.toString() << destinationEndpointId;
|
||||
|
||||
// Build APS request
|
||||
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::BindRequest);
|
||||
|
||||
// Generate a new transaction sequence number for this device object
|
||||
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Build ZDO frame
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << transactionSequenceNumber;
|
||||
stream << m_node->extendedAddress().toUInt64();
|
||||
stream << sourceEndpointId;
|
||||
stream << clusterId;
|
||||
stream << static_cast<quint8>(Zigbee::DestinationAddressModeIeeeAddress);
|
||||
stream << destinationIeeeAddress.toUInt64();
|
||||
stream << destinationEndpointId;
|
||||
|
||||
// Set the ZDO frame as APS request payload
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// Create the device object reply and wait for the response indication
|
||||
ZigbeeDeviceObjectReply *zdoReply = createZigbeeDeviceObjectReply(request, transactionSequenceNumber);
|
||||
|
||||
// Send the request, on finished read the confirm information
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){
|
||||
if (!verifyNetworkError(zdoReply, networkReply)) {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId())
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zdoReply->isComplete()) {
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
// We received the confirmation but not yet the indication
|
||||
});
|
||||
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLeaveNetwork(bool rejoin, bool removeChildren)
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request management leave network from" << m_node << "rejoin" << rejoin << "remove children" << removeChildren;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public:
|
|||
// End device binding
|
||||
// ZigbeeDeviceObjectReply *requestBindGroup(quint16 clusterId, quint16 groupAddress, quint8 destinationEndpoint);
|
||||
// ZigbeeDeviceObjectReply *requestBindShortAddress();
|
||||
// ZigbeeDeviceObjectReply *requestBindIeeeAddress();
|
||||
ZigbeeDeviceObjectReply *requestBindIeeeAddress(quint8 sourceEndpointId, quint16 clusterId, const ZigbeeAddress &destinationIeeeAddress, quint8 destinationEndpointId);
|
||||
|
||||
|
||||
// Management request
|
||||
|
|
|
|||
|
|
@ -366,57 +366,6 @@ void ZigbeeNetwork::clearSettings()
|
|||
m_nodeType = ZigbeeDeviceProfile::NodeTypeCoordinator;
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::saveNode(ZigbeeNode *node)
|
||||
{
|
||||
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
|
||||
settings.beginGroup("Nodes");
|
||||
|
||||
// Save this node
|
||||
settings.beginGroup(node->extendedAddress().toString());
|
||||
settings.setValue("nwkAddress", node->shortAddress());
|
||||
|
||||
// Node descriptor
|
||||
settings.setValue("nodeDescriptorRaw", node->nodeDescriptor().descriptorRawData);
|
||||
|
||||
// Power descriptor
|
||||
settings.setValue("powerDescriptorFlag", node->powerDescriptor().powerDescriptoFlag);
|
||||
|
||||
settings.beginWriteArray("endpoints");
|
||||
for (int i = 0; i < node->endpoints().count(); i++) {
|
||||
ZigbeeNodeEndpoint *endpoint = node->endpoints().at(i);
|
||||
settings.setArrayIndex(i);
|
||||
settings.setValue("id", endpoint->endpointId());
|
||||
settings.setValue("profile", endpoint->profile());
|
||||
settings.setValue("deviceId", endpoint->deviceId());
|
||||
settings.setValue("deviceVersion", endpoint->deviceVersion());
|
||||
settings.setValue("manufacturerName", endpoint->manufacturerName());
|
||||
settings.setValue("modelIdentifier", endpoint->modelIdentifier());
|
||||
settings.setValue("softwareBuildId", endpoint->softwareBuildId());
|
||||
|
||||
settings.beginWriteArray("inputClusters");
|
||||
for (int n = 0; n < endpoint->inputClusters().count(); n++) {
|
||||
ZigbeeCluster *cluster = endpoint->inputClusters().at(n);
|
||||
settings.setArrayIndex(n);
|
||||
settings.setValue("clusterId", cluster->clusterId());
|
||||
}
|
||||
settings.endArray(); // inputClusters
|
||||
|
||||
settings.beginWriteArray("outputClusters");
|
||||
for (int n = 0; n < endpoint->outputClusters().count(); n++) {
|
||||
ZigbeeCluster *cluster = endpoint->outputClusters().at(n);
|
||||
settings.setArrayIndex(n);
|
||||
settings.setValue("clusterId", cluster->clusterId());
|
||||
}
|
||||
settings.endArray(); // outputClusters
|
||||
}
|
||||
|
||||
settings.endArray(); // endpoints
|
||||
|
||||
settings.endGroup(); // Node ieee address
|
||||
|
||||
settings.endGroup(); // Nodes
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::addNode(ZigbeeNode *node)
|
||||
{
|
||||
qCDebug(dcZigbeeNetwork()) << "Add node" << node;
|
||||
|
|
@ -483,6 +432,11 @@ bool ZigbeeNetwork::networkConfigurationAvailable() const
|
|||
return m_extendedPanId != 0 && m_channel != 0 && m_coordinatorNode;
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::handleNodeIndication(ZigbeeNode *node, const Zigbee::ApsdeDataIndication indication)
|
||||
{
|
||||
node->handleDataIndication(indication);
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNetwork::createNetworkReply(const ZigbeeNetworkRequest &request)
|
||||
{
|
||||
ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(request, this);
|
||||
|
|
|
|||
|
|
@ -155,7 +155,6 @@ protected:
|
|||
void saveNetwork();
|
||||
void loadNetwork();
|
||||
void clearSettings();
|
||||
void saveNode(ZigbeeNode *node);
|
||||
|
||||
void addNode(ZigbeeNode *node);
|
||||
void addUnitializedNode(ZigbeeNode *node);
|
||||
|
|
@ -166,6 +165,8 @@ protected:
|
|||
|
||||
bool networkConfigurationAvailable() const;
|
||||
|
||||
void handleNodeIndication(ZigbeeNode *node, const Zigbee::ApsdeDataIndication indication);
|
||||
|
||||
// Network reply methods
|
||||
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
||||
void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ ZigbeeNodeEndpoint *ZigbeeNode::getEndpoint(quint8 endpointId) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
quint8 ZigbeeNode::lqi() const
|
||||
{
|
||||
return m_lqi;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::NodeDescriptor ZigbeeNode::nodeDescriptor() const
|
||||
{
|
||||
return m_nodeDescriptor;
|
||||
|
|
@ -536,6 +541,24 @@ void ZigbeeNode::readSoftwareBuildId(ZigbeeClusterBasic *basicCluster)
|
|||
});
|
||||
}
|
||||
|
||||
void ZigbeeNode::handleDataIndication(const Zigbee::ApsdeDataIndication &indication)
|
||||
{
|
||||
if (indication.lqi != m_lqi) {
|
||||
m_lqi = indication.lqi;
|
||||
emit lqiChanged(m_lqi);
|
||||
}
|
||||
|
||||
|
||||
// Check if this indocation is related to any pending reply
|
||||
if (indication.profileId == Zigbee::ZigbeeProfileDevice) {
|
||||
deviceObject()->processApsDataIndication(indication);
|
||||
return;
|
||||
}
|
||||
|
||||
// Else let the node handle this indication
|
||||
handleZigbeeClusterLibraryIndication(indication);
|
||||
}
|
||||
|
||||
void ZigbeeNode::handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication)
|
||||
{
|
||||
qCDebug(dcZigbeeNode()) << "Processing ZCL indication" << indication;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ public:
|
|||
bool hasEndpoint(quint8 endpointId) const;
|
||||
ZigbeeNodeEndpoint *getEndpoint(quint8 endpointId) const;
|
||||
|
||||
quint8 lqi() const;
|
||||
|
||||
// Information from descriptors
|
||||
ZigbeeDeviceProfile::NodeDescriptor nodeDescriptor() const;
|
||||
ZigbeeDeviceProfile::MacCapabilities macCapabilities() const;
|
||||
|
|
@ -114,8 +116,7 @@ private:
|
|||
void readModelIdentifier(ZigbeeClusterBasic *basicCluster);
|
||||
void readSoftwareBuildId(ZigbeeClusterBasic *basicCluster);
|
||||
|
||||
|
||||
|
||||
void handleDataIndication(const Zigbee::ApsdeDataIndication &indication);
|
||||
|
||||
signals:
|
||||
void nodeInitializationFailed();
|
||||
|
|
|
|||
Loading…
Reference in New Issue