Add more node data and improve serial parsing
This commit is contained in:
parent
bbc9cb0ba1
commit
0255dfd792
@ -46,6 +46,10 @@ public:
|
||||
MessageTypeAuthenticateDeviceResponse = 0x8028,
|
||||
MessageTypeOutOfBandCommisioningDataRequest = 0x0029,
|
||||
MessageTypeOutOfBandCommisioningDataResponse = 0x8029,
|
||||
MessageTypeUserDescriptorSet = 0x002B,
|
||||
MessageTypeUserDescriptorNotify = 0x802B,
|
||||
MessageTypeUserDescriptorRequest = 0x002C,
|
||||
MessageTypeUserDescriptorResponse = 0x802C,
|
||||
|
||||
MessageTypeReset = 0x0011,
|
||||
MessageTypeErasePersistentData = 0x0012,
|
||||
@ -56,6 +60,8 @@ public:
|
||||
MessageTypeBindResponse = 0x8030,
|
||||
MessageTypeUnbind = 0x0031,
|
||||
MessageTypeUnbindResponse = 0x8031,
|
||||
MessageTypeComplexDescriptorRequest = 0x0034,
|
||||
MessageTypeComplexDescriptorResponse = 0x8034,
|
||||
|
||||
MessageTypeNetworkAdressRequest = 0x0040,
|
||||
MessageTypeNetworkAdressResponse = 0x8040,
|
||||
@ -400,6 +406,25 @@ public:
|
||||
};
|
||||
Q_ENUM(DataType)
|
||||
|
||||
enum Manufacturer {
|
||||
// RF4CE
|
||||
PanasonicRF4CE = 0x0001,
|
||||
SonyRF4CE = 0x0002,
|
||||
SamsungRF4CE = 0x0003,
|
||||
PhilipsRF4CE = 0x0004,
|
||||
FreescaleRF4CE = 0x0005,
|
||||
OkiSemiRF4CE = 0x0006,
|
||||
TiRF4CE = 0x0007,
|
||||
|
||||
// Manufacturer Codes for non RF4CE devices
|
||||
Cirronet = 0x1000,
|
||||
Chipcon = 0x1001,
|
||||
Ember = 0x1003,
|
||||
|
||||
};
|
||||
Q_ENUM(Manufacturer)
|
||||
|
||||
|
||||
///* Manufacturer Codes */
|
||||
///* Codes less than 0x1000 were issued for RF4CE */
|
||||
//#define ZBEE_MFG_CODE_PANASONIC_RF4CE 0x0001
|
||||
@ -412,7 +437,7 @@ public:
|
||||
|
||||
///* Manufacturer Codes for non RF4CE devices */
|
||||
//#define ZBEE_MFG_CODE_CIRRONET 0x1000
|
||||
//#define ZBEE_MFG_CODE_CHIPCON 0x1001
|
||||
//#define ZBEE_MFG_CODE_CHIPCON
|
||||
//#define ZBEE_MFG_CODE_EMBER 0x1002
|
||||
//#define ZBEE_MFG_CODE_NTS 0x1003
|
||||
//#define ZBEE_MFG_CODE_FREESCALE 0x1004
|
||||
|
||||
@ -7,7 +7,8 @@
|
||||
#include <QSettings>
|
||||
|
||||
ZigbeeNetworkManager::ZigbeeNetworkManager(const int &channel, const QString &serialPort, QObject *parent) :
|
||||
ZigbeeNode(new ZigbeeBridgeController(serialPort, parent), parent)
|
||||
ZigbeeNode(new ZigbeeBridgeController(serialPort, parent), parent),
|
||||
m_serialPort(serialPort)
|
||||
{
|
||||
connect(controller(), &ZigbeeBridgeController::messageReceived, this, &ZigbeeNetworkManager::onMessageReceived);
|
||||
|
||||
@ -20,7 +21,8 @@ ZigbeeNetworkManager::ZigbeeNetworkManager(const int &channel, const QString &se
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("Network");
|
||||
m_extendedPanId = static_cast<quint64>(settings.value("panId", 0).toUInt());
|
||||
m_extendedPanId = static_cast<quint64>(settings.value("panId", 0).toLongLong());
|
||||
qCDebug(dcZigbee()) << "Loading saved pan id" << m_extendedPanId;
|
||||
if (m_extendedPanId == 0) {
|
||||
m_extendedPanId = generateRandomPanId();
|
||||
settings.setValue("panId", m_extendedPanId);
|
||||
@ -39,24 +41,19 @@ ZigbeeNetworkManager::ZigbeeNetworkManager(const int &channel, const QString &se
|
||||
qCDebug(dcZigbee()) << "Using channel" << channel << "for the zigbee network.";
|
||||
}
|
||||
|
||||
// // Call init methods
|
||||
// erasePersistentData();
|
||||
// //resetController();
|
||||
// getVersion();
|
||||
// setExtendedPanId(m_extendedPanId);
|
||||
// setChannelMask(channelMask);
|
||||
// setDeviceType(NodeTypeCoordinator);
|
||||
// startNetwork();
|
||||
loadNetwork();
|
||||
resetController();
|
||||
getVersion();
|
||||
init();
|
||||
}
|
||||
|
||||
bool ZigbeeNetworkManager::isAvailable() const
|
||||
{
|
||||
if (m_controller){
|
||||
return m_controller->available();
|
||||
}
|
||||
|
||||
// //startScan();
|
||||
// //getPermitJoiningStatus();
|
||||
// enableWhitelist();
|
||||
// permitJoining();
|
||||
// //getPermitJoiningStatus();
|
||||
|
||||
// //startScan();
|
||||
// initiateTouchLink();
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ZigbeeNetworkManager::controllerVersion() const
|
||||
@ -64,6 +61,11 @@ QString ZigbeeNetworkManager::controllerVersion() const
|
||||
return m_controllerVersion;
|
||||
}
|
||||
|
||||
QString ZigbeeNetworkManager::serialPort() const
|
||||
{
|
||||
return m_serialPort;
|
||||
}
|
||||
|
||||
QList<ZigbeeNode *> ZigbeeNetworkManager::nodeList() const
|
||||
{
|
||||
return m_nodeList;
|
||||
@ -102,28 +104,8 @@ void ZigbeeNetworkManager::parseNetworkFormed(const QByteArray &data)
|
||||
networkStatusString = "unknown";
|
||||
}
|
||||
|
||||
|
||||
// Parse short network address
|
||||
quint16 shortAddress = data.at(1);
|
||||
shortAddress <<= 8;
|
||||
shortAddress |= data.at(2);
|
||||
|
||||
// Parse extended network address
|
||||
quint64 extendedAddress = data.at(3);
|
||||
extendedAddress <<= 8;
|
||||
extendedAddress |= data.at(4);
|
||||
extendedAddress <<= 8;
|
||||
extendedAddress |= data.at(5);
|
||||
extendedAddress <<= 8;
|
||||
extendedAddress |= data.at(6);
|
||||
extendedAddress <<= 8;
|
||||
extendedAddress |= data.at(7);
|
||||
extendedAddress <<= 8;
|
||||
extendedAddress |= data.at(8);
|
||||
extendedAddress <<= 8;
|
||||
extendedAddress |= data.at(9);
|
||||
extendedAddress <<= 8;
|
||||
extendedAddress |= data.at(10);
|
||||
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(data.mid(1, 2));
|
||||
quint64 extendedAddress = ZigbeeUtils::convertByteArrayToUint64(data.mid(3, 8));
|
||||
|
||||
// Parse network channel
|
||||
quint8 channel = static_cast<quint8>(data.at(11));
|
||||
@ -219,7 +201,7 @@ void ZigbeeNetworkManager::setExtendedPanId(const quint64 &panId)
|
||||
stream << panId;
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetExtendetPanId, data));
|
||||
request.setDescription("Set extended PAN ID " + QString::number(panId) + " " + ZigbeeUtils::convertUint64ToHexString(panId));
|
||||
request.setDescription("Set extended PAN id " + QString::number(panId) + " " + ZigbeeUtils::convertUint64ToHexString(panId));
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onSetExtendedPanIdFinished);
|
||||
@ -227,6 +209,10 @@ void ZigbeeNetworkManager::setExtendedPanId(const quint64 &panId)
|
||||
|
||||
void ZigbeeNetworkManager::setChannelMask(const quint32 &channelMask)
|
||||
{
|
||||
// Note: 10 < value < 27 -> using sinle channel value
|
||||
// 0x07fff800 select from all channels 11 - 26
|
||||
// 0x2108800 primary zigbee light link channels 11, 15, 20, 25
|
||||
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << channelMask;
|
||||
@ -285,12 +271,13 @@ void ZigbeeNetworkManager::startScan()
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onStartScanFinished);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::permitJoining(quint16 targetAddress, const quint8 advertisingIntervall)
|
||||
void ZigbeeNetworkManager::permitJoining(quint16 targetAddress, const quint8 advertisingIntervall, bool tcSignificance)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << targetAddress;
|
||||
stream << advertisingIntervall;
|
||||
stream << static_cast<quint8>(tcSignificance);
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypePermitJoiningRequest, data));
|
||||
request.setDescription("Permit joining request on " + ZigbeeUtils::convertUint16ToHexString(targetAddress) + " for " + QString::number(advertisingIntervall) + "[s]");
|
||||
@ -299,6 +286,23 @@ void ZigbeeNetworkManager::permitJoining(quint16 targetAddress, const quint8 adv
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onPermitJoiningFinished);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::requestLinkQuality()
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << shortAddress();
|
||||
stream << static_cast<quint8>(0);
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeManagementLqiRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeManagementLqiResponse);
|
||||
request.setDescription("Request link quality request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress()));
|
||||
request.setTimoutIntervall(5000);
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onRequestLinkQualityFinished);
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::getPermitJoiningStatus()
|
||||
{
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeGetPermitJoining));
|
||||
@ -337,25 +341,40 @@ void ZigbeeNetworkManager::touchLinkFactoryReset()
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onTouchLinkFactoryResetFinished);
|
||||
}
|
||||
|
||||
|
||||
void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile)
|
||||
void ZigbeeNetworkManager::networkAddressRequest(quint16 targetAddress, quint64 extendedAddress)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << targetAddress;
|
||||
stream << extendedAddress;
|
||||
stream << static_cast<quint8>(1);
|
||||
stream << static_cast<quint8>(0);
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNetworkAdressRequest, data));
|
||||
request.setDescription("Network address request on " + ZigbeeUtils::convertUint16ToHexString(targetAddress));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNetworkAdressResponse);
|
||||
request.setTimoutIntervall(1000);
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onNetworkAddressRequestFinished);
|
||||
}
|
||||
|
||||
|
||||
void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile)
|
||||
{
|
||||
|
||||
// TargetAddress profile InputClusterCount InputClusterList OutputClusterCount OutputClusterList
|
||||
|
||||
Q_UNUSED(profile)
|
||||
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << shortAddress;
|
||||
stream << static_cast<quint16>(profile);
|
||||
|
||||
// TODO: check what this does
|
||||
|
||||
// // Input clusters
|
||||
// stream << static_cast<quint8>(7);
|
||||
// stream << static_cast<quint16>(Zigbee::ClusterIdBasic);
|
||||
// stream << static_cast<quint16>(Zigbee::ClusterIdIdentify);
|
||||
// stream << static_cast<quint16>(Zigbee::ClusterIdGroups);
|
||||
// stream << static_cast<quint16>(Zigbee::ClusterIdScenes);
|
||||
// stream << static_cast<quint16>(Zigbee::ClusterIdOnOff);
|
||||
// stream << static_cast<quint16>(Zigbee::ClusterIdLevelControl);
|
||||
// stream << static_cast<quint16>(Zigbee::ClusterIdColorControl);
|
||||
stream << static_cast<quint16>(0xFFFF);
|
||||
stream << static_cast<quint8>(0);
|
||||
stream << static_cast<quint16>(0);
|
||||
stream << static_cast<quint8>(0);
|
||||
stream << static_cast<quint16>(0);
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeMatchDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeMatchDescriptorResponse);
|
||||
@ -366,6 +385,50 @@ void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, c
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onRequestMatchDescriptorFinished);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::setInitialSecurity(quint8 keyState, quint8 keySequence, quint8 keyType, const QString &key)
|
||||
{
|
||||
// Note: calls ZPS_vAplSecSetInitialSecurityState
|
||||
|
||||
// Key state:
|
||||
// ZPS_ZDO_PRECONFIGURED_LINK_KEY = 3
|
||||
// This key will be used to encrypt the network key. This is the master or manufacturer key
|
||||
|
||||
// ZPS_ZDO_ZLL_LINK_KEY = 4
|
||||
// This key will be generated by the trust center.
|
||||
|
||||
// Key Type:
|
||||
// ZPS_APS_UNIQUE_LINK_KEY =
|
||||
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << keyState;
|
||||
stream << keySequence;
|
||||
stream << keyType;
|
||||
stream << QByteArray::fromHex(key.toUtf8());
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetSecurity, data));
|
||||
request.setDescription("Set security configuration");
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onSetSecurityFinished);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::authenticateDevice(const ZigbeeAddress &ieeeAddress)
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << ieeeAddress.toUInt64();
|
||||
stream << QByteArray::fromHex("5A6967426565416C6C69616E63653039");
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeAuthenticateDeviceRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeAuthenticateDeviceResponse);
|
||||
request.setDescription(QString("Authenticate device %1").arg(ieeeAddress.toString()));
|
||||
request.setTimoutIntervall(5000);
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onAuthenticateDeviceFinished);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onResetControllerFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
@ -409,15 +472,9 @@ void ZigbeeNetworkManager::onGetVersionFinished()
|
||||
|
||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||
|
||||
// Parse major version
|
||||
quint16 majorVersion = reply->additionalMessage().data().at(0);
|
||||
majorVersion <<= 8;
|
||||
majorVersion |= reply->additionalMessage().data().at(1);
|
||||
|
||||
// Parse minor version
|
||||
quint16 minorVersion = reply->additionalMessage().data().at(2);
|
||||
minorVersion <<= 8;
|
||||
minorVersion |= reply->additionalMessage().data().at(3);
|
||||
// Parse version
|
||||
quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2));
|
||||
quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2));
|
||||
|
||||
m_controllerVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion);
|
||||
qCDebug(dcZigbee()) << "Version:" << m_controllerVersion;
|
||||
@ -540,6 +597,83 @@ void ZigbeeNetworkManager::onRequestMatchDescriptorFinished()
|
||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onSetSecurityFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
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";
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onNetworkAddressRequestFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
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";
|
||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||
|
||||
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
|
||||
quint8 statusCode = static_cast<quint8>(reply->additionalMessage().data().at(1));
|
||||
quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(2, 8));
|
||||
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(10, 2));
|
||||
quint8 deviceCount = static_cast<quint8>(reply->additionalMessage().data().at(12));
|
||||
quint8 startIndex = static_cast<quint8>(reply->additionalMessage().data().at(13));
|
||||
|
||||
qCDebug(dcZigbee()) << "Network address response:";
|
||||
qCDebug(dcZigbee()) << " SQN:" << sequenceNumber;
|
||||
qCDebug(dcZigbee()) << " Status:" << statusCode;
|
||||
qCDebug(dcZigbee()) << " Address:" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||
qCDebug(dcZigbee()) << " Extended address:" << ZigbeeAddress(ieeeAddress);
|
||||
qCDebug(dcZigbee()) << " Deice count:" << deviceCount;
|
||||
qCDebug(dcZigbee()) << " Start index:" << startIndex;
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onAuthenticateDeviceFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
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";
|
||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||
|
||||
quint64 gatewayIeeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(0, 8));
|
||||
QString encryptedKey = reply->additionalMessage().data().mid(8, 16).toHex();
|
||||
QByteArray mic = reply->additionalMessage().data().mid(24, 4);
|
||||
quint64 initiatorIeeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(28, 8));
|
||||
quint8 activeKeySequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(36));
|
||||
quint8 channel = static_cast<quint8>(reply->additionalMessage().data().at(37));
|
||||
quint16 shortPan = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(38, 2));
|
||||
quint64 extendedPanId = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(40, 8));
|
||||
|
||||
|
||||
qCDebug(dcZigbee()) << "Authentication response:";
|
||||
qCDebug(dcZigbee()) << " Gateways address:" << ZigbeeAddress(gatewayIeeeAddress);
|
||||
qCDebug(dcZigbee()) << " Key:" << encryptedKey;
|
||||
qCDebug(dcZigbee()) << " MIC:" << mic.toHex();
|
||||
qCDebug(dcZigbee()) << " Initiator address:" << ZigbeeAddress(initiatorIeeeAddress);
|
||||
qCDebug(dcZigbee()) << " Active key sequence number:" << activeKeySequenceNumber;
|
||||
qCDebug(dcZigbee()) << " Channel:" << channel;
|
||||
qCDebug(dcZigbee()) << " Short PAN ID:" << ZigbeeUtils::convertUint16ToHexString(shortPan);
|
||||
qCDebug(dcZigbee()) << " Extended PAN ID:" << extendedPanId << ZigbeeUtils::convertUint64ToHexString(extendedPanId);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onEnableWhitelistFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
@ -579,6 +713,68 @@ void ZigbeeNetworkManager::onTouchLinkFactoryResetFinished()
|
||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onRequestLinkQualityFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
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";
|
||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||
|
||||
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
|
||||
quint8 statusCode = static_cast<quint8>(reply->additionalMessage().data().at(1));
|
||||
quint8 neighborTableEntries = static_cast<quint8>(reply->additionalMessage().data().at(2));
|
||||
quint8 neighborTableListCount = static_cast<quint8>(reply->additionalMessage().data().at(3));
|
||||
quint8 startIndex = static_cast<quint8>(reply->additionalMessage().data().at(4));
|
||||
|
||||
qCDebug(dcZigbee()) << "LQI response:";
|
||||
qCDebug(dcZigbee()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(statusCode);
|
||||
qCDebug(dcZigbee()) << " Neighbor table entries:" << neighborTableEntries;
|
||||
qCDebug(dcZigbee()) << " Neighbor table list count:" << neighborTableListCount;
|
||||
qCDebug(dcZigbee()) << " Start index:" << startIndex;
|
||||
|
||||
int offset = 5;
|
||||
|
||||
// Note: according to docs, if the table has no neigbors the list will be empty
|
||||
if (neighborTableEntries == 0) {
|
||||
qCDebug(dcZigbee()) << " There are no neigbors";
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = startIndex; i < neighborTableListCount; i++) {
|
||||
|
||||
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(offset, 2));
|
||||
quint64 panId = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(offset + 2, 8));
|
||||
quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(reply->additionalMessage().data().mid(offset + 10, 8));
|
||||
quint8 depth = static_cast<quint8>(reply->additionalMessage().data().at(offset + 18));
|
||||
quint8 linkQuality = static_cast<quint8>(reply->additionalMessage().data().at(offset + 19));
|
||||
quint8 bitMap = static_cast<quint8>(reply->additionalMessage().data().at(offset + 20));
|
||||
|
||||
offset += 21;
|
||||
|
||||
qCDebug(dcZigbee()) << " Neighbor:" << i;
|
||||
qCDebug(dcZigbee()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||
qCDebug(dcZigbee()) << " PAN id:" << panId;
|
||||
qCDebug(dcZigbee()) << " Extended address:" << ZigbeeAddress(ieeeAddress);
|
||||
qCDebug(dcZigbee()) << " Depth:" << depth;
|
||||
qCDebug(dcZigbee()) << " Link quality:" << linkQuality;
|
||||
qCDebug(dcZigbee()) << " BitMap:" << ZigbeeUtils::convertByteToHexString(bitMap);
|
||||
|
||||
foreach (ZigbeeNode *node, m_nodeList) {
|
||||
if (node->extendedAddress() == ZigbeeAddress(ieeeAddress)) {
|
||||
node->setShortAddress(shortAddress);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::processLoggingMessage(const ZigbeeInterfaceMessage &message)
|
||||
{
|
||||
quint8 logLevel = static_cast<quint8>(message.data().at(0));
|
||||
@ -658,10 +854,10 @@ void ZigbeeNetworkManager::processNodeClusterList(const ZigbeeInterfaceMessage &
|
||||
|
||||
QByteArray clusterListData = message.data().right(message.data().count() - 3);
|
||||
|
||||
for (int i = 0; i < clusterListData.count(); i+=2) {
|
||||
for (int i = 0; i < clusterListData.count(); i += 2) {
|
||||
quint16 clusterId = clusterListData.at(i);
|
||||
clusterId <<= 8;
|
||||
clusterId |= clusterListData .at(i+1);
|
||||
clusterId |= clusterListData .at(i + 1);
|
||||
|
||||
qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||
}
|
||||
@ -671,14 +867,8 @@ void ZigbeeNetworkManager::processNodeAttributeList(const ZigbeeInterfaceMessage
|
||||
{
|
||||
quint8 sourceEndpoint = static_cast<quint8>(message.data().at(0));
|
||||
|
||||
quint16 profileId = static_cast<quint8>(message.data().at(1));
|
||||
profileId <<= 8;
|
||||
profileId |= static_cast<quint8>(message.data().at(2));
|
||||
|
||||
quint16 clusterId = static_cast<quint8>(message.data().at(3));
|
||||
clusterId <<= 8;
|
||||
clusterId |= static_cast<quint8>(message.data().at(4));
|
||||
|
||||
quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2));
|
||||
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2));
|
||||
|
||||
qCDebug(dcZigbeeController()) << "Node attribute list received:";
|
||||
qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint;
|
||||
@ -687,11 +877,8 @@ void ZigbeeNetworkManager::processNodeAttributeList(const ZigbeeInterfaceMessage
|
||||
|
||||
QByteArray attributeListData = message.data().right(message.data().count() - 5);
|
||||
|
||||
for (int i = 0; i < attributeListData.count(); i+=2) {
|
||||
quint16 attribute = attributeListData.at(i);
|
||||
attribute <<= 8;
|
||||
attribute |= attributeListData .at(i+1);
|
||||
|
||||
for (int i = 0; i < attributeListData.count(); i += 2) {
|
||||
quint16 attribute = ZigbeeUtils::convertByteArrayToUint16(attributeListData.mid(i, 2));
|
||||
qCDebug(dcZigbeeController()) << " Attribute:" << ZigbeeUtils::convertUint16ToHexString(attribute);
|
||||
}
|
||||
}
|
||||
@ -700,13 +887,8 @@ void ZigbeeNetworkManager::processNodeCommandIdList(const ZigbeeInterfaceMessage
|
||||
{
|
||||
quint8 sourceEndpoint = static_cast<quint8>(message.data().at(0));
|
||||
|
||||
quint16 profileId = static_cast<quint8>(message.data().at(1));
|
||||
profileId <<= 8;
|
||||
profileId |= static_cast<quint8>(message.data().at(2));
|
||||
|
||||
quint16 clusterId = static_cast<quint8>(message.data().at(3));
|
||||
clusterId <<= 8;
|
||||
clusterId |= static_cast<quint8>(message.data().at(4));
|
||||
quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2));
|
||||
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2));
|
||||
|
||||
qCDebug(dcZigbeeController()) << "Node command list received:";
|
||||
qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint;
|
||||
@ -723,27 +905,10 @@ void ZigbeeNetworkManager::processNodeCommandIdList(const ZigbeeInterfaceMessage
|
||||
|
||||
void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &message)
|
||||
{
|
||||
quint16 shortAddress = message.data().at(0);
|
||||
shortAddress <<= 8;
|
||||
shortAddress |= message.data().at(1);
|
||||
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(0, 2));
|
||||
quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(message.data().mid(2, 8));
|
||||
|
||||
quint64 ieeeAddress = message.data().at(2);
|
||||
ieeeAddress <<= 8;
|
||||
ieeeAddress |= message.data().at(3);
|
||||
ieeeAddress <<= 8;
|
||||
ieeeAddress |= message.data().at(4);
|
||||
ieeeAddress <<= 8;
|
||||
ieeeAddress |= message.data().at(5);
|
||||
ieeeAddress <<= 8;
|
||||
ieeeAddress |= message.data().at(6);
|
||||
ieeeAddress <<= 8;
|
||||
ieeeAddress |= message.data().at(7);
|
||||
ieeeAddress <<= 8;
|
||||
ieeeAddress |= message.data().at(8);
|
||||
ieeeAddress <<= 8;
|
||||
ieeeAddress |= message.data().at(9);
|
||||
|
||||
quint8 macCapability = message.data().at(10);
|
||||
quint8 macCapability = static_cast<quint8>(message.data().at(10));
|
||||
|
||||
qCDebug(dcZigbee()) << "Device announced:";
|
||||
qCDebug(dcZigbee()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||
@ -764,28 +929,14 @@ void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &m
|
||||
void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &message)
|
||||
{
|
||||
quint8 sequenceNumber = static_cast<quint8>(message.data().at(0));
|
||||
|
||||
quint16 sourceAddress = message.data().at(1);
|
||||
sourceAddress <<= 8;
|
||||
sourceAddress |= message.data().at(2);
|
||||
|
||||
quint16 sourceAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2));
|
||||
quint8 endPoint = static_cast<quint8>(message.data().at(3));
|
||||
|
||||
quint16 clusterId = message.data().at(4);
|
||||
clusterId <<= 8;
|
||||
clusterId |= message.data().at(5);
|
||||
|
||||
quint16 attributeId = message.data().at(6);
|
||||
attributeId <<= 8;
|
||||
attributeId |= message.data().at(7);
|
||||
|
||||
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(4, 2));
|
||||
quint16 attributeId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(6, 2));
|
||||
quint8 attributStatus = static_cast<quint8>(message.data().at(8));
|
||||
quint8 attributDataType = static_cast<quint8>(message.data().at(9));
|
||||
|
||||
quint16 attributeSize = message.data().at(10);
|
||||
attributeSize <<= 8;
|
||||
attributeSize |= message.data().at(11);
|
||||
|
||||
quint16 attributeSize = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(10, 2));
|
||||
QByteArray data = message.data().mid(12);
|
||||
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(attributDataType);
|
||||
|
||||
@ -805,7 +956,7 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
|
||||
qCDebug(dcZigbee()) << " Data(converted)" << QString::fromUtf8(data);
|
||||
break;
|
||||
case Zigbee::Bool:
|
||||
qCDebug(dcZigbee()) << " Data(converted)" << QVariant(data.toInt()).toBool();
|
||||
qCDebug(dcZigbee()) << " Data(converted)" << QVariant(data).toBool();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -817,17 +968,37 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
|
||||
|
||||
void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &message)
|
||||
{
|
||||
quint16 shortAddress = message.data().at(0);
|
||||
shortAddress <<= 8;
|
||||
shortAddress |= message.data().at(1);
|
||||
|
||||
quint8 rejoining = message.data().at(2);
|
||||
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(0, 2));
|
||||
quint8 rejoining = static_cast<quint8>(message.data().at(2));
|
||||
|
||||
qCDebug(dcZigbee()) << "Node leaving:" << ZigbeeUtils::convertUint16ToHexString(shortAddress) << rejoining;
|
||||
|
||||
// TODO: remove node
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessage &message)
|
||||
{
|
||||
if (message.data().isEmpty())
|
||||
return;
|
||||
|
||||
quint8 status = static_cast<quint8>(message.data().at(0));
|
||||
switch (status) {
|
||||
case 0:
|
||||
qCDebug(dcZigbee()) << "Restart provisioned: start up";
|
||||
break;
|
||||
case 2:
|
||||
qCDebug(dcZigbee()) << "Restart provisioned: NFN start";
|
||||
break;
|
||||
case 6:
|
||||
qCDebug(dcZigbee()) << "Restart provisioned: running";
|
||||
break;
|
||||
default:
|
||||
qCDebug(dcZigbee()) << "Restart provisioned: unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &message)
|
||||
{
|
||||
switch (message.messageType()) {
|
||||
@ -855,6 +1026,12 @@ void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &messa
|
||||
case Zigbee::MessageTypeLeaveIndication:
|
||||
processLeaveIndication(message);
|
||||
break;
|
||||
case Zigbee::MessageTypeNetworkJoinedFormed:
|
||||
parseNetworkFormed(message.data());
|
||||
break;
|
||||
case Zigbee::MessageTypeRestartProvisioned:
|
||||
processRestartProvisioned(message);
|
||||
break;
|
||||
default:
|
||||
qCDebug(dcZigbeeController()) << "Message received:" << message;
|
||||
break;
|
||||
|
||||
@ -13,9 +13,13 @@ class ZigbeeNetworkManager : public ZigbeeNode
|
||||
public:
|
||||
explicit ZigbeeNetworkManager(const int &channel = 0, const QString &serialPort = "/dev/ttyS0", QObject *parent = nullptr);
|
||||
|
||||
bool isAvailable() const;
|
||||
|
||||
QString controllerVersion() const;
|
||||
QString serialPort() const;
|
||||
QList<ZigbeeNode *> nodeList() const;
|
||||
quint64 extendedPanId() const;
|
||||
|
||||
bool networkRunning() const;
|
||||
|
||||
// Controller methods
|
||||
@ -24,12 +28,14 @@ public:
|
||||
void sendDataManagerAvailableResponse();
|
||||
void getVersion();
|
||||
void setExtendedPanId(const quint64 &panId);
|
||||
void setChannelMask(const quint32 &channelMask);
|
||||
void setChannelMask(const quint32 &channelMask = 0x07fff800);
|
||||
void setDeviceType(const NodeType &deviceType);
|
||||
void startNetwork();
|
||||
void startScan();
|
||||
|
||||
void permitJoining(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 254);
|
||||
void permitJoining(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 180, bool tcSignificance = false);
|
||||
|
||||
void requestLinkQuality();
|
||||
|
||||
void getPermitJoiningStatus();
|
||||
void enableWhitelist();
|
||||
@ -37,10 +43,17 @@ public:
|
||||
void initiateTouchLink();
|
||||
void touchLinkFactoryReset();
|
||||
|
||||
void networkAddressRequest(quint16 targetAddress, quint64 extendedAddress);
|
||||
|
||||
void requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile);
|
||||
|
||||
void setInitialSecurity(quint8 keyState, quint8 keySequence, quint8 keyType, const QString &key);
|
||||
|
||||
void authenticateDevice(const ZigbeeAddress &ieeeAddress);
|
||||
|
||||
private:
|
||||
ZigbeeBridgeController *m_controller = nullptr;
|
||||
QString m_serialPort;
|
||||
QString m_controllerVersion;
|
||||
quint64 m_extendedPanId = 0;
|
||||
|
||||
@ -76,8 +89,12 @@ private slots:
|
||||
|
||||
void onInitiateTouchLinkFinished();
|
||||
void onTouchLinkFactoryResetFinished();
|
||||
void onRequestLinkQualityFinished();
|
||||
|
||||
void onRequestMatchDescriptorFinished();
|
||||
void onSetSecurityFinished();
|
||||
void onNetworkAddressRequestFinished();
|
||||
void onAuthenticateDeviceFinished();
|
||||
|
||||
// Process controller notifications/messages
|
||||
void processLoggingMessage(const ZigbeeInterfaceMessage &message);
|
||||
@ -88,6 +105,7 @@ private slots:
|
||||
void processDeviceAnnounce(const ZigbeeInterfaceMessage &message);
|
||||
void processAttributeReport(const ZigbeeInterfaceMessage &message);
|
||||
void processLeaveIndication(const ZigbeeInterfaceMessage &message);
|
||||
void processRestartProvisioned(const ZigbeeInterfaceMessage &message);
|
||||
};
|
||||
|
||||
#endif // ZIGBEEMANAGER_H
|
||||
|
||||
@ -14,11 +14,56 @@ ZigbeeAddress ZigbeeNode::extendedAddress() const
|
||||
return m_extendedAddress;
|
||||
}
|
||||
|
||||
int ZigbeeNode::endPoint() const
|
||||
{
|
||||
return m_endPoint;
|
||||
}
|
||||
|
||||
ZigbeeNode::NodeType ZigbeeNode::nodeType() const
|
||||
{
|
||||
return m_nodeType;
|
||||
}
|
||||
|
||||
ZigbeeNode::FrequencyBand ZigbeeNode::frequencyBand() const
|
||||
{
|
||||
return m_frequencyBand;
|
||||
}
|
||||
|
||||
ZigbeeNode::Relationship ZigbeeNode::relationShip() const
|
||||
{
|
||||
return m_relationShip;
|
||||
}
|
||||
|
||||
Zigbee::ZigbeeProfile ZigbeeNode::profile() const
|
||||
{
|
||||
return m_profile;
|
||||
}
|
||||
|
||||
quint16 ZigbeeNode::manufacturerCode() const
|
||||
{
|
||||
return m_manufacturerCode;
|
||||
}
|
||||
|
||||
ZigbeeNode::PowerMode ZigbeeNode::powerMode() const
|
||||
{
|
||||
return m_powerMode;
|
||||
}
|
||||
|
||||
ZigbeeNode::PowerSource ZigbeeNode::powerSource() const
|
||||
{
|
||||
return m_powerSource;
|
||||
}
|
||||
|
||||
QList<ZigbeeNode::PowerSource> ZigbeeNode::availablePowerSources() const
|
||||
{
|
||||
return m_availablePowerSources;
|
||||
}
|
||||
|
||||
ZigbeeNode::PowerLevel ZigbeeNode::powerLevel() const
|
||||
{
|
||||
return m_powerLevel;
|
||||
}
|
||||
|
||||
void ZigbeeNode::init()
|
||||
{
|
||||
requestNodeDescription();
|
||||
@ -26,6 +71,40 @@ void ZigbeeNode::init()
|
||||
requestPowerDescriptor();
|
||||
}
|
||||
|
||||
|
||||
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::requestNodeDescription()
|
||||
{
|
||||
QByteArray data;
|
||||
@ -35,7 +114,7 @@ void ZigbeeNode::requestNodeDescription()
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
|
||||
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
|
||||
request.setTimoutIntervall(10000);
|
||||
request.setTimoutIntervall(5000);
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestNodeDescriptionFinished);
|
||||
@ -51,7 +130,7 @@ void ZigbeeNode::requestSimpleNodeDescription()
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSimpleDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeSimpleDescriptorResponse);
|
||||
request.setDescription("Simple node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
|
||||
request.setTimoutIntervall(10000);
|
||||
request.setTimoutIntervall(5000);
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestSimpleNodeDescriptionFinished);
|
||||
@ -66,12 +145,28 @@ void ZigbeeNode::requestPowerDescriptor()
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypePowerDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypePowerDescriptorResponse);
|
||||
request.setDescription("Node power descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
|
||||
request.setTimoutIntervall(10000);
|
||||
request.setTimoutIntervall(5000);
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestPowerDescriptorFinished);
|
||||
}
|
||||
|
||||
void ZigbeeNode::requestUserDescriptor()
|
||||
{
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << m_shortAddress;
|
||||
stream << static_cast<quint16>(0);
|
||||
|
||||
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeUserDescriptorRequest, data));
|
||||
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeUserDescriptorResponse);
|
||||
request.setDescription("Node user descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
|
||||
request.setTimoutIntervall(5000);
|
||||
|
||||
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestUserDescriptorFinished);
|
||||
}
|
||||
|
||||
ZigbeeNode::ZigbeeNode(ZigbeeBridgeController *controller, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_controller(controller)
|
||||
@ -137,20 +232,86 @@ void ZigbeeNode::onRequestNodeDescriptionFinished()
|
||||
bitField <<= 8;
|
||||
bitField |= reply->additionalMessage().data().at(16);
|
||||
|
||||
// TODO: find node for short address and set data
|
||||
// Set node data
|
||||
m_manufacturerCode = manufacturerCode;
|
||||
m_maximalRxSize = maximalRxSize;
|
||||
m_maximalTxSize = maximalTxSize;
|
||||
|
||||
// Parse server mask
|
||||
m_isPrimaryTrustCenter = ((serverMask >> 0) & 0x0001);
|
||||
m_isBackupTrustCenter = ((serverMask >> 1) & 0x0001);
|
||||
m_isPrimaryBindingCache = ((serverMask >> 2) & 0x0001);
|
||||
m_isBackupBindingCache = ((serverMask >> 3) & 0x0001);
|
||||
m_isPrimaryDiscoveryCache = ((serverMask >> 4) & 0x0001);
|
||||
m_isBackupDiscoveryCache = ((serverMask >> 5) & 0x0001);
|
||||
m_isNetworkManager = ((serverMask >> 6) & 0x0001);
|
||||
|
||||
// Parse desciptor flag
|
||||
bool extendedActiveEndpointListAvailable = ((descriptorFlag >> 0) & 0x01);
|
||||
bool extendedSimpleDescriptorListAvailable = ((descriptorFlag >> 1) & 0x01);
|
||||
|
||||
// Parse MAC capabilities
|
||||
m_receiverOnWhenIdle = ((macFlags >> 3) & 0x01);
|
||||
m_securityCapability = ((macFlags >> 6) & 0x01);
|
||||
|
||||
// Parse bit field
|
||||
bool isCoordinator = ((bitField >> 0) & 0x0001);
|
||||
bool isRouter = ((bitField >> 1) & 0x0001);
|
||||
bool isEndDevice = ((bitField >> 2) & 0x0001);
|
||||
bool complexDescriptorAvailable = ((bitField >> 3) & 0x0001);
|
||||
bool userDescriptorAvailable = ((bitField >> 4) & 0x0001);
|
||||
|
||||
if (isCoordinator && !isRouter && !isEndDevice) {
|
||||
m_nodeType = NodeTypeCoordinator;
|
||||
} else if (!isCoordinator && isRouter && !isEndDevice) {
|
||||
m_nodeType = NodeTypeRouter;
|
||||
} else if (!isCoordinator && !isRouter && isEndDevice) {
|
||||
m_nodeType = NodeTypeEndDevice;
|
||||
} else {
|
||||
if (m_isNetworkManager) {
|
||||
m_nodeType = NodeTypeCoordinator;
|
||||
} else {
|
||||
m_nodeType = NodeTypeEndDevice;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Frequency always 2,4 GHz
|
||||
|
||||
qCDebug(dcZigbee()) << "Node descriptor:";
|
||||
qCDebug(dcZigbee()) << " Node type:" << m_nodeType;
|
||||
qCDebug(dcZigbee()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
||||
qCDebug(dcZigbee()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||
qCDebug(dcZigbee()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
|
||||
qCDebug(dcZigbee()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximalRxSize);
|
||||
qCDebug(dcZigbee()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximalTxSize);
|
||||
qCDebug(dcZigbee()) << " Server makk:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
|
||||
qCDebug(dcZigbee()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(m_maximalRxSize);
|
||||
qCDebug(dcZigbee()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(m_maximalTxSize);
|
||||
qCDebug(dcZigbee()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
|
||||
qCDebug(dcZigbee()) << " Primary Trust center:" << m_isPrimaryTrustCenter;
|
||||
qCDebug(dcZigbee()) << " Backup Trust center:" << m_isBackupTrustCenter;
|
||||
qCDebug(dcZigbee()) << " Primary Binding cache:" << m_isPrimaryBindingCache;
|
||||
qCDebug(dcZigbee()) << " Backup Binding cache:" << m_isBackupBindingCache;
|
||||
qCDebug(dcZigbee()) << " Primary Discovery cache:" << m_isPrimaryDiscoveryCache;
|
||||
qCDebug(dcZigbee()) << " Backup Discovery cache:" << m_isBackupDiscoveryCache;
|
||||
qCDebug(dcZigbee()) << " Network Manager:" << m_isNetworkManager;
|
||||
qCDebug(dcZigbee()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
|
||||
qCDebug(dcZigbee()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable;
|
||||
qCDebug(dcZigbee()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable;
|
||||
qCDebug(dcZigbee()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
|
||||
qCDebug(dcZigbee()) << " Receiver on when idle:" << m_receiverOnWhenIdle;
|
||||
qCDebug(dcZigbee()) << " Security capability:" << m_securityCapability;
|
||||
qCDebug(dcZigbee()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maxBufferSize);
|
||||
qCDebug(dcZigbee()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
|
||||
qCDebug(dcZigbee()) << " Is coordinator:" << isCoordinator;
|
||||
qCDebug(dcZigbee()) << " Is router:" << isRouter;
|
||||
qCDebug(dcZigbee()) << " Is end device:" << isEndDevice;
|
||||
qCDebug(dcZigbee()) << " Complex desciptor available:" << complexDescriptorAvailable;
|
||||
qCDebug(dcZigbee()) << " User desciptor available:" << userDescriptorAvailable;
|
||||
|
||||
|
||||
if (userDescriptorAvailable) {
|
||||
requestUserDescriptor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNode::onRequestSimpleNodeDescriptionFinished()
|
||||
@ -174,6 +335,12 @@ void ZigbeeNode::onRequestSimpleNodeDescriptionFinished()
|
||||
nwkAddress |= reply->additionalMessage().data().at(3);
|
||||
|
||||
quint8 length = static_cast<quint8>(reply->additionalMessage().data().at(4));
|
||||
|
||||
if (length == 0) {
|
||||
qCWarning(dcZigbee()) << "Length 0";
|
||||
return;
|
||||
}
|
||||
|
||||
quint8 endPoint = static_cast<quint8>(reply->additionalMessage().data().at(5));
|
||||
|
||||
quint16 profileId = reply->additionalMessage().data().at(6);
|
||||
@ -248,14 +415,128 @@ void ZigbeeNode::onRequestPowerDescriptorFinished()
|
||||
bitField <<= 8;
|
||||
bitField |= reply->additionalMessage().data().at(3);
|
||||
|
||||
// Bit 0 - 3 Power mode
|
||||
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
|
||||
// 0001: Receiver switched on periodically
|
||||
// 0010: Receiver switched on when stimulated, e.g. by pressing a button
|
||||
|
||||
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||
m_powerMode = PowerModeAlwaysOn;
|
||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||
m_powerMode = PowerModeOnPeriodically;
|
||||
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
|
||||
m_powerMode = PowerModeOnWhenStimulated;
|
||||
}
|
||||
|
||||
// Bit 4 - 7 Available power sources
|
||||
// Bit 0: Permanent mains supply
|
||||
// Bit 1: Rechargeable battery
|
||||
// Bit 2: Disposable battery
|
||||
// Bit 4: Reserved
|
||||
|
||||
if (ZigbeeUtils::checkBitUint16(bitField, 4)) {
|
||||
m_availablePowerSources.append(PowerSourcePermanentMainSupply);
|
||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 5)) {
|
||||
m_availablePowerSources.append(PowerSourceRecharchableBattery);
|
||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 6)) {
|
||||
m_availablePowerSources.append(PowerSourceDisposableBattery);
|
||||
}
|
||||
|
||||
// Bit 8 - 11 Active source: according to the same schema as available power sources
|
||||
if (ZigbeeUtils::checkBitUint16(bitField, 8)) {
|
||||
m_powerSource = PowerSourcePermanentMainSupply;
|
||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 9)) {
|
||||
m_powerSource = PowerSourceRecharchableBattery;
|
||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 10)) {
|
||||
m_powerSource = PowerSourceDisposableBattery;
|
||||
}
|
||||
|
||||
// Bit 12 - 15: Battery level if available
|
||||
// 0000: Critically low
|
||||
// 0100: Approximately 33%
|
||||
// 1000: Approximately 66%
|
||||
// 1100: Approximately 100% (near fully charged)
|
||||
|
||||
if (!ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||
m_powerLevel = PowerLevelCriticalLow;
|
||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||
m_powerLevel = PowerLevelLow;
|
||||
} else if (!ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||
m_powerLevel = PowerLevelOk;
|
||||
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
|
||||
m_powerLevel = PowerLevelFull;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbee()) << "Node power descriptor:";
|
||||
qCDebug(dcZigbee()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
||||
qCDebug(dcZigbee()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
|
||||
qCDebug(dcZigbee()) << " Power mode:" << m_powerMode;
|
||||
qCDebug(dcZigbee()) << " Available power sources:";
|
||||
foreach (const PowerSource &source, m_availablePowerSources) {
|
||||
qCDebug(dcZigbee()) << " " << source;
|
||||
}
|
||||
qCDebug(dcZigbee()) << " Power source:" << m_powerSource;
|
||||
qCDebug(dcZigbee()) << " Power level:" << m_powerLevel;
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNode::onRequestUserDescriptorFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
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";
|
||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||
|
||||
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
|
||||
quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
|
||||
|
||||
quint16 nwkAddress = reply->additionalMessage().data().at(2);
|
||||
nwkAddress <<= 8;
|
||||
nwkAddress |= reply->additionalMessage().data().at(3);
|
||||
|
||||
quint8 length = static_cast<quint8>(reply->additionalMessage().data().at(4));
|
||||
|
||||
QByteArray data;
|
||||
if (length > 0) {
|
||||
data = reply->additionalMessage().data().mid(5, length);
|
||||
}
|
||||
|
||||
qCDebug(dcZigbee()) << "User descriptor:";
|
||||
qCDebug(dcZigbee()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
|
||||
qCDebug(dcZigbee()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
|
||||
qCDebug(dcZigbee()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
|
||||
qCDebug(dcZigbee()) << " Data:" << data;
|
||||
}
|
||||
|
||||
void ZigbeeNode::onToggleFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
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";
|
||||
}
|
||||
|
||||
void ZigbeeNode::onIdentifyFinished()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, ZigbeeNode *node)
|
||||
{
|
||||
debug.nospace().noquote() << "Node(" << node->shortAddress() << ", " << node->extendedAddress().toString() << ") ";
|
||||
debug.nospace().noquote() << "Node(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << " | " << node->extendedAddress().toString() << ") ";
|
||||
debug.nospace().noquote() << " " << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << " | " << node->extendedAddress().toString() << ") ";
|
||||
return debug;
|
||||
}
|
||||
|
||||
@ -30,28 +30,97 @@ public:
|
||||
};
|
||||
Q_ENUM(FrequencyBand)
|
||||
|
||||
enum Relationship {
|
||||
Parent,
|
||||
Child,
|
||||
Sibling
|
||||
};
|
||||
Q_ENUM(Relationship)
|
||||
|
||||
enum PowerMode {
|
||||
PowerModeAlwaysOn,
|
||||
PowerModeOnPeriodically,
|
||||
PowerModeOnWhenStimulated
|
||||
};
|
||||
Q_ENUM(PowerMode)
|
||||
|
||||
enum PowerSource {
|
||||
PowerSourcePermanentMainSupply,
|
||||
PowerSourceRecharchableBattery,
|
||||
PowerSourceDisposableBattery
|
||||
};
|
||||
Q_ENUM(PowerSource)
|
||||
|
||||
enum PowerLevel {
|
||||
PowerLevelCriticalLow,
|
||||
PowerLevelLow,
|
||||
PowerLevelOk,
|
||||
PowerLevelFull
|
||||
};
|
||||
Q_ENUM(PowerLevel)
|
||||
|
||||
quint16 shortAddress() const;
|
||||
ZigbeeAddress extendedAddress() const;
|
||||
int endPoint() const;
|
||||
|
||||
// Information from node descriptor
|
||||
NodeType nodeType() const;
|
||||
FrequencyBand frequencyBand() const;
|
||||
Relationship relationShip() const;
|
||||
Zigbee::ZigbeeProfile profile() const;
|
||||
quint16 manufacturerCode() const;
|
||||
|
||||
bool canBeCoordinator() const;
|
||||
PowerMode powerMode() const;
|
||||
PowerSource powerSource() const;
|
||||
QList<PowerSource> availablePowerSources() const;
|
||||
PowerLevel powerLevel() const;
|
||||
|
||||
// Node specific zigbee commands
|
||||
void init();
|
||||
void identify();
|
||||
void toggle(int addressMode);
|
||||
|
||||
private:
|
||||
ZigbeeBridgeController *m_controller;
|
||||
|
||||
quint16 m_shortAddress = 0;
|
||||
ZigbeeAddress m_extendedAddress;
|
||||
NodeType m_nodeType;
|
||||
int m_endPoint = 0;
|
||||
|
||||
NodeType m_nodeType = NodeTypeRouter;
|
||||
FrequencyBand m_frequencyBand = FrequencyBand2400Mhz;
|
||||
Relationship m_relationShip = Parent;
|
||||
|
||||
Zigbee::ZigbeeProfile m_profile;
|
||||
quint16 m_manufacturerCode = 0;
|
||||
|
||||
quint16 m_maximalRxSize = 0;
|
||||
quint16 m_maximalTxSize = 0;
|
||||
|
||||
bool m_isPrimaryTrustCenter = false;
|
||||
bool m_isBackupTrustCenter = false;
|
||||
bool m_isPrimaryBindingCache = false;
|
||||
bool m_isBackupBindingCache = false;
|
||||
bool m_isPrimaryDiscoveryCache = false;
|
||||
bool m_isBackupDiscoveryCache = false;
|
||||
bool m_isNetworkManager = false;
|
||||
|
||||
// Power information
|
||||
PowerMode m_powerMode;
|
||||
PowerSource m_powerSource;
|
||||
QList<PowerSource> m_availablePowerSources;
|
||||
PowerLevel m_powerLevel;
|
||||
|
||||
// Mac capabilities
|
||||
bool m_receiverOnWhenIdle = false;
|
||||
bool m_securityCapability = false;
|
||||
|
||||
void requestNodeDescription();
|
||||
void requestSimpleNodeDescription();
|
||||
void requestPowerDescriptor();
|
||||
void requestUserDescriptor();
|
||||
|
||||
void saveToSettings();
|
||||
|
||||
protected:
|
||||
ZigbeeNode(ZigbeeBridgeController *controller, QObject *parent = nullptr);
|
||||
@ -67,7 +136,9 @@ private slots:
|
||||
void onRequestNodeDescriptionFinished();
|
||||
void onRequestSimpleNodeDescriptionFinished();
|
||||
void onRequestPowerDescriptorFinished();
|
||||
|
||||
void onRequestUserDescriptorFinished();
|
||||
void onToggleFinished();
|
||||
void onIdentifyFinished();
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
@ -27,6 +27,43 @@ QByteArray ZigbeeUtils::convertBitArrayToByteArray(const QBitArray &bitArray)
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
bool ZigbeeUtils::checkBitUint16(const quint16 &value, const int &bitNumber)
|
||||
{
|
||||
return value & (1 << bitNumber);
|
||||
}
|
||||
|
||||
quint16 ZigbeeUtils::convertByteArrayToUint16(const QByteArray &data)
|
||||
{
|
||||
Q_ASSERT_X(data.count() == 2, "converting data", "Invalid byte array size for converting to quint16");
|
||||
|
||||
quint16 value = static_cast<quint8>(data.at(0));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(1));
|
||||
return value;
|
||||
}
|
||||
|
||||
quint64 ZigbeeUtils::convertByteArrayToUint64(const QByteArray &data)
|
||||
{
|
||||
Q_ASSERT_X(data.count() == 8, "converting data", "Invalid byte array size for converting to quint64");
|
||||
|
||||
quint64 value = static_cast<quint8>(data.at(0));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(1));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(2));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(3));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(4));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(5));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(6));
|
||||
value <<= 8;
|
||||
value |= static_cast<quint8>(data.at(7));
|
||||
return value;
|
||||
}
|
||||
|
||||
QString ZigbeeUtils::convertByteToHexString(const quint8 &byte)
|
||||
{
|
||||
QString hexString(QStringLiteral("0x%1"));
|
||||
@ -39,7 +76,7 @@ QString ZigbeeUtils::convertByteArrayToHexString(const QByteArray &byteArray)
|
||||
QString hexString;
|
||||
for (int i = 0; i < byteArray.count(); i++) {
|
||||
hexString.append(convertByteToHexString((quint8)byteArray.at(i)));
|
||||
if (i != byteArray.count() -1) {
|
||||
if (i != byteArray.count() - 1) {
|
||||
hexString.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,10 @@ public:
|
||||
// Data utils
|
||||
QBitArray convertByteArrayToBitArray(const QByteArray &byteArray);
|
||||
QByteArray convertBitArrayToByteArray(const QBitArray &bitArray);
|
||||
static bool checkBitUint16(const quint16 &value, const int &bitNumber);
|
||||
|
||||
static quint16 convertByteArrayToUint16(const QByteArray &data);
|
||||
static quint64 convertByteArrayToUint64(const QByteArray &data);
|
||||
|
||||
// Debug utils
|
||||
static QString convertByteToHexString(const quint8 &byte);
|
||||
|
||||
@ -1,11 +1,16 @@
|
||||
#include "core.h"
|
||||
#include "loggingcategory.h"
|
||||
#include "QCoreApplication"
|
||||
#include "zigbeeutils.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
Core::Core(const QString &serialPort, const int &channel, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_serialPort(serialPort)
|
||||
{
|
||||
m_channelMask = 0;
|
||||
m_channelMask |= 1 << (channel);
|
||||
|
||||
m_manager = new ZigbeeNetworkManager(channel, m_serialPort, this);
|
||||
|
||||
// Set commands
|
||||
@ -20,11 +25,18 @@ Core::Core(const QString &serialPort, const int &channel, QObject *parent) :
|
||||
m_commands.append(TerminalCommand("reset", "Reset the zigbee controller"));
|
||||
m_commands.append(TerminalCommand("scan", "Start scanning for zigbee networks"));
|
||||
m_commands.append(TerminalCommand("version", "Print the version of the zigbee controll bridge firmware"));
|
||||
m_commands.append(TerminalCommand("network-info", "Print all information of the zigbee network."));
|
||||
m_commands.append(TerminalCommand("list-nodes", "List all nodes and information of the current network"));
|
||||
m_commands.append(TerminalCommand("permit-join", "Permit nodes to join the network"));
|
||||
m_commands.append(TerminalCommand("touch-link", "Initiate touch link pairing"));
|
||||
m_commands.append(TerminalCommand("reset-touchlink", "Touch link factory reset"));
|
||||
m_commands.append(TerminalCommand("whitelist", "Enable the white list joining"));
|
||||
m_commands.append(TerminalCommand("address-request", "Request network address on host node"));
|
||||
m_commands.append(TerminalCommand("matchdescriptor", "Request match descriptors"));
|
||||
m_commands.append(TerminalCommand("init-node", "Request simple descriptors"));
|
||||
m_commands.append(TerminalCommand("lqi", "Request link quality"));
|
||||
m_commands.append(TerminalCommand("toggle", "Request to toggle"));
|
||||
m_commands.append(TerminalCommand("authenticate", "Authenticate device with given IEEE address"));
|
||||
|
||||
TerminalCommander::instance()->setCommands(m_commands);
|
||||
TerminalCommander::instance()->start();
|
||||
@ -33,6 +45,17 @@ Core::Core(const QString &serialPort, const int &channel, QObject *parent) :
|
||||
connect(TerminalCommander::instance(), &TerminalCommander::finished, QCoreApplication::instance(), &QCoreApplication::quit);
|
||||
}
|
||||
|
||||
ZigbeeNode *Core::findNode(const QString &shortAddressString)
|
||||
{
|
||||
foreach (ZigbeeNode *node, m_manager->nodeList()) {
|
||||
if (ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) == shortAddressString) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Core::onCommandReceived(const QStringList &tokens)
|
||||
{
|
||||
TerminalCommand command;
|
||||
@ -68,30 +91,93 @@ void Core::onCommandReceived(const QStringList &tokens)
|
||||
m_manager->erasePersistentData();
|
||||
m_manager->getVersion();
|
||||
m_manager->setExtendedPanId(m_manager->extendedPanId());
|
||||
m_manager->setChannelMask(0);
|
||||
m_manager->setChannelMask(0x2108800);
|
||||
m_manager->setDeviceType(nodeType);
|
||||
// Note: this is the leaked philips ZLL master key
|
||||
m_manager->setInitialSecurity(3, 0, 1, "9F5595F10257C8A469CBF42BC93FEE31");
|
||||
m_manager->setInitialSecurity(4, 0, 1, "5A6967426565416C6C69616E63653039");
|
||||
|
||||
} else if (command.command() == "start") {
|
||||
m_manager->startNetwork();
|
||||
} else if (command.command() == "version") {
|
||||
m_manager->getVersion();
|
||||
} else if (command.command() == "network-info") {
|
||||
qCDebug(dcZigbee()).nospace().noquote() << "Network controller: " << m_manager->serialPort() << ", Bridge version: " << m_manager->controllerVersion();
|
||||
} else if (command.command() == "scan") {
|
||||
m_manager->startScan();
|
||||
} else if (command.command() == "reset") {
|
||||
m_manager->resetController();
|
||||
} else if (command.command() == "permit-join") {
|
||||
m_manager->permitJoining();
|
||||
m_manager->permitJoining(0xfffc, 180, true);
|
||||
} else if (command.command() == "touch-link") {
|
||||
m_manager->initiateTouchLink();
|
||||
} else if (command.command() == "touch-link-reset") {
|
||||
} else if (command.command() == "reset-touchlink") {
|
||||
m_manager->touchLinkFactoryReset();
|
||||
} else if (command.command() == "enable-whitelist") {
|
||||
} else if (command.command() == "whitelist") {
|
||||
m_manager->enableWhitelist();
|
||||
} else if (command.command() == "address-request") {
|
||||
if (tokens.count() == 1) {
|
||||
m_manager->networkAddressRequest(0, m_manager->extendedAddress().toUInt64());
|
||||
return;
|
||||
}
|
||||
ZigbeeNode *node = findNode(tokens.at(1));
|
||||
if (!node) {
|
||||
qCWarning(dcZigbee()) << "Could not find node with short address tokens.at(1)";
|
||||
return;
|
||||
}
|
||||
|
||||
m_manager->networkAddressRequest(node->shortAddress(), node->extendedAddress().toUInt64());
|
||||
|
||||
} else if (command.command() == "toggle") {
|
||||
if (tokens.count() < 3) {
|
||||
qCWarning(dcZigbee()) << "Please specify also the node short address and adressMode";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ZigbeeNode *node = findNode(tokens.at(1));
|
||||
if (!node) {
|
||||
qCWarning(dcZigbee()) << "Could not find node with short address tokens.at(1)";
|
||||
return;
|
||||
}
|
||||
|
||||
int addressMode = QString(tokens.at(2)).toInt();
|
||||
|
||||
node->toggle(addressMode);
|
||||
|
||||
} else if (command.command() == "lqi") {
|
||||
m_manager->requestLinkQuality();
|
||||
} else if (command.command() == "init-node") {
|
||||
if (tokens.count() == 1) {
|
||||
qCWarning(dcZigbee()) << "Please specify also the node short address";
|
||||
return;
|
||||
}
|
||||
|
||||
ZigbeeNode *node = findNode(tokens.at(1));
|
||||
if (!node) {
|
||||
qCWarning(dcZigbee()) << "Could not find node with short address tokens.at(1)";
|
||||
return;
|
||||
}
|
||||
|
||||
node->init();
|
||||
|
||||
} else if (command.command() == "matchdescriptor") {
|
||||
m_manager->requestMatchDescriptor(0x9004, Zigbee::ZigbeeProfileLightLink);
|
||||
//m_manager->requestMatchDescriptor(0xFFFD, Zigbee::ZigbeeProfileLightLink);
|
||||
|
||||
} else if (command.command() == "authenticate") {
|
||||
if (tokens.count() == 1) {
|
||||
qCWarning(dcZigbee()) << "Please specify also the node short address";
|
||||
return;
|
||||
}
|
||||
|
||||
m_manager->authenticateDevice(ZigbeeAddress(tokens.at(1)));
|
||||
|
||||
} else if (command.command() == "list-nodes") {
|
||||
qCDebug(dcZigbee()) << "--> Host:" << m_manager;
|
||||
|
||||
foreach (ZigbeeNode *node, m_manager->nodeList()) {
|
||||
qCDebug(dcZigbee()) << "-->" << node;
|
||||
qCDebug(dcZigbee()) << " -->" << node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,9 @@ private:
|
||||
ZigbeeNetworkManager *m_manager = nullptr;
|
||||
QList<TerminalCommand> m_commands;
|
||||
QString m_serialPort;
|
||||
quint32 m_channelMask = 0;
|
||||
|
||||
ZigbeeNode *findNode(const QString &shortAddressString);
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user