Add read binding tables for testing
parent
6f04230028
commit
66637cc389
|
|
@ -29,6 +29,7 @@
|
|||
#include "zigbeenetworkreply.h"
|
||||
#include "loggingcategory.h"
|
||||
#include "zigbeenetwork.h"
|
||||
#include "zigbeeutils.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
|
|
@ -124,8 +125,17 @@ void ZigbeeClusterOnOff::processDataIndication(ZigbeeClusterLibrary::Frame frame
|
|||
case CommandToggle:
|
||||
emit commandSent(CommandToggle);
|
||||
break;
|
||||
case CommandOnWithTimedOff: {
|
||||
QByteArray payload = frame.payload;
|
||||
QDataStream payloadStream(&payload, QIODevice::ReadOnly);
|
||||
payloadStream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 acceptOnlyWhenOnInt = 0; quint16 onTime; quint16 offTime;
|
||||
payloadStream >> acceptOnlyWhenOnInt >> onTime >> offTime;
|
||||
emit commandOnWithTimedOffSent(static_cast<bool>(acceptOnlyWhenOnInt), onTime, offTime);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
qCWarning(dcZigbeeCluster()) << "Unhandled command sent from" << m_node << m_endpoint << this << command;
|
||||
qCWarning(dcZigbeeCluster()) << "Unhandled command sent from" << m_node << m_endpoint << this << command << ZigbeeUtils::convertByteArrayToHexString(frame.payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ signals:
|
|||
|
||||
// Client cluster signals
|
||||
void commandSent(Command command);
|
||||
|
||||
// On and off time is in 1/10 seconds
|
||||
void commandOnWithTimedOffSent(bool acceptOnlyWhenOn, quint16 onTime, quint16 offTime);
|
||||
};
|
||||
|
||||
#endif // ZIGBEECLUSTERONOFF_H
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "zigbeedeviceobject.h"
|
||||
#include "zigbeenetwork.h"
|
||||
#include "loggingcategory.h"
|
||||
#include "zigbeedeviceprofile.h"
|
||||
#include "zigbeeutils.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QPointer>
|
||||
|
|
@ -396,7 +398,7 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLqi(quint8 startIndex)
|
|||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << startIndex;
|
||||
stream << transactionSequenceNumber << startIndex;
|
||||
|
||||
// Set the ZDO frame as APS request payload
|
||||
request.setAsdu(asdu);
|
||||
|
|
@ -431,6 +433,53 @@ ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLqi(quint8 startIndex)
|
|||
|
||||
|
||||
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
// We received the confirmation but not yet the indication
|
||||
});
|
||||
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtBind(quint8 startIndex)
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request management bind table from" << m_node << "start index" << startIndex;
|
||||
|
||||
// Build APS request
|
||||
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::MgmtBindRequest);
|
||||
|
||||
// Generate a new transaction sequence number for this device object
|
||||
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << transactionSequenceNumber << startIndex;
|
||||
|
||||
// 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()) {
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Successfully received response for" << static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId());
|
||||
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
|
@ -536,5 +585,5 @@ void ZigbeeDeviceObject::processApsDataIndication(const Zigbee::ApsdeDataIndicat
|
|||
return;
|
||||
}
|
||||
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Unhandled ZDO indication" << m_node << asdu;
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Unhandled ZDO indication" << m_node << indication << asdu;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
// Management request
|
||||
ZigbeeDeviceObjectReply *requestMgmtLeaveNetwork(bool rejoin = false, bool removeChildren = false);
|
||||
ZigbeeDeviceObjectReply *requestMgmtLqi(quint8 startIndex = 0x00);
|
||||
|
||||
ZigbeeDeviceObjectReply *requestMgmtBind(quint8 startIndex = 0x00);
|
||||
|
||||
// TODO: write all requests
|
||||
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::Adpu &deviceAdpu)
|
|||
debug.nospace() << "DeviceAdpu(SQN: " << deviceAdpu.transactionSequenceNumber << ", ";
|
||||
debug.nospace() << deviceAdpu.status << ", ";
|
||||
debug.nospace() << ZigbeeUtils::convertUint16ToHexString(deviceAdpu.addressOfInterest) << ", ";
|
||||
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")";
|
||||
debug.nospace() << "Payload: " << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")";
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
|
|
@ -262,3 +262,22 @@ QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::PowerDescriptor &powe
|
|||
debug.nospace() << " Power level: " << powerDescriptor.powerLevel;
|
||||
return debug;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::BindingTableListRecord &bindingTableListRecord)
|
||||
{
|
||||
debug.nospace() << "BindingTableListRecord(" << bindingTableListRecord.sourceAddress.toString() << ", ";
|
||||
debug.nospace() << "source endpoint: " << bindingTableListRecord.sourceEndpoint << ", ";
|
||||
debug.nospace() << "cluster: " << static_cast<ZigbeeClusterLibrary::ClusterId>(bindingTableListRecord.clusterId) << " --> ";
|
||||
switch (bindingTableListRecord.destinationAddressMode) {
|
||||
case Zigbee::DestinationAddressModeGroup:
|
||||
debug.nospace() << "destination address (group): " << ZigbeeUtils::convertUint16ToHexString(bindingTableListRecord.destinationAddressShort) << ") ";
|
||||
break;
|
||||
case Zigbee::DestinationAddressModeIeeeAddress:
|
||||
debug.nospace() << "destination address (unicast): " << bindingTableListRecord.destinationAddress.toString() << ", ";
|
||||
debug.nospace() << "destination endpoint: " << bindingTableListRecord.destinationEndpoint << ") ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return debug;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <QObject>
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeeaddress.h"
|
||||
|
||||
class ZigbeeDeviceProfile
|
||||
{
|
||||
|
|
@ -276,6 +277,17 @@ public:
|
|||
PowerLevel powerLevel = PowerLevelFull;
|
||||
} PowerDescriptor;
|
||||
|
||||
typedef struct BindingTableListRecord {
|
||||
ZigbeeAddress sourceAddress;
|
||||
quint8 sourceEndpoint;
|
||||
quint16 clusterId;
|
||||
Zigbee::DestinationAddressMode destinationAddressMode; // Note: group or unicast
|
||||
quint16 destinationAddressShort; // Only for destination address 0x01
|
||||
ZigbeeAddress destinationAddress; // Only for destination address 0x03
|
||||
quint8 destinationEndpoint; // Only for destination address 0x03
|
||||
} BindingTableListRecord;
|
||||
|
||||
|
||||
static NodeDescriptor parseNodeDescriptor(const QByteArray &payload);
|
||||
static MacCapabilities parseMacCapabilities(quint8 macCapabilitiesFlag);
|
||||
static ServerMask parseServerMask(quint16 serverMaskFlag);
|
||||
|
|
@ -290,5 +302,6 @@ QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::MacCapabilities &macC
|
|||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::ServerMask &serverMask);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::DescriptorCapabilities &descriptorCapabilities);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::PowerDescriptor &powerDescriptor);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::BindingTableListRecord &bindingTableListRecord);
|
||||
|
||||
#endif // ZIGBEEDEVICEPROFILE_H
|
||||
|
|
|
|||
|
|
@ -154,6 +154,58 @@ void ZigbeeNode::startInitialization()
|
|||
initNodeDescriptor();
|
||||
}
|
||||
|
||||
void ZigbeeNode::readBindingTableEntries()
|
||||
{
|
||||
ZigbeeDeviceObjectReply * reply = deviceObject()->requestMgmtBind();
|
||||
connect(reply, &ZigbeeDeviceObjectReply::finished, this, [=](){
|
||||
if (reply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Failed to read binding table" << reply->error();
|
||||
return;
|
||||
}
|
||||
|
||||
// The request finished, but we received a ZDP error.
|
||||
if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) {
|
||||
qCWarning(dcZigbeeNode()) << this << "failed to read node descriptor" << reply->responseAdpu().status;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Bind table payload" << ZigbeeUtils::convertByteArrayToHexString(reply->responseData());
|
||||
QByteArray response = reply->responseData();
|
||||
QDataStream stream(&response, QIODevice::ReadOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 sqn; quint8 statusInt; quint8 entriesCount; quint8 startIndex; quint8 bindingTableListCount;
|
||||
stream >> sqn >> statusInt >> entriesCount >> startIndex >> bindingTableListCount;
|
||||
ZigbeeDeviceProfile::Status status = static_cast<ZigbeeDeviceProfile::Status>(statusInt);
|
||||
qCDebug(dcZigbeeDeviceObject()) << "SQN:" << sqn << status << "entries:" << entriesCount << "index:" << startIndex << "list count:" << bindingTableListCount;
|
||||
|
||||
QList<ZigbeeDeviceProfile::BindingTableListRecord> bindingTableRecords;
|
||||
for (int i = 0; i < bindingTableListCount; i++) {
|
||||
quint64 sourceAddress; quint8 addressMode;
|
||||
ZigbeeDeviceProfile::BindingTableListRecord record;
|
||||
stream >> sourceAddress;
|
||||
record.sourceAddress = ZigbeeAddress(sourceAddress);
|
||||
|
||||
stream >> record.sourceEndpoint >> record.clusterId >> addressMode;
|
||||
record.destinationAddressMode = static_cast<Zigbee::DestinationAddressMode>(addressMode);
|
||||
|
||||
if (addressMode == Zigbee::DestinationAddressModeGroup) {
|
||||
stream >> record.destinationAddressShort;
|
||||
} else if (addressMode == Zigbee::DestinationAddressModeIeeeAddress) {
|
||||
quint64 destinationAddressIeee;
|
||||
stream >> destinationAddressIeee >> record.destinationEndpoint;
|
||||
record.destinationAddress = ZigbeeAddress(destinationAddressIeee);
|
||||
} else {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Invalid destination address mode in binding table record.";
|
||||
break;
|
||||
}
|
||||
qCDebug(dcZigbeeDeviceObject()) << record;
|
||||
bindingTableRecords << record;
|
||||
}
|
||||
|
||||
// TODO: continue reading if there are more entries
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNode::initNodeDescriptor()
|
||||
{
|
||||
qCDebug(dcZigbeeNode()) << "Requst node descriptor from" << this;
|
||||
|
|
@ -636,6 +688,6 @@ QDebug operator<<(QDebug debug, ZigbeeNode *node)
|
|||
{
|
||||
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
|
||||
debug.nospace().noquote() << ", " << node->extendedAddress().toString();
|
||||
debug.nospace().noquote() << ") ";
|
||||
return debug;
|
||||
debug.nospace().noquote() << ")";
|
||||
return debug.space().quote();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ public:
|
|||
// This method starts the node initialization phase (read descriptors and endpoints)
|
||||
void startInitialization();
|
||||
|
||||
void readBindingTableEntries();
|
||||
|
||||
private:
|
||||
ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent = nullptr);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue