commit
b55b215ab2
|
|
@ -1,11 +1,13 @@
|
|||
# nymea-zigbee
|
||||
----------------------
|
||||
|
||||
This repository contains the nymea-zigbee library and tools.
|
||||
|
||||
# Supported hardware
|
||||
|
||||
## NXP
|
||||
Currently the only supported hardware is from NXP, but the tool will be designed to support also other hardware modules.
|
||||
|
||||
## NXP
|
||||
* JN5168 (SoM)
|
||||
* JN5169 (USB Stick)
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,19 @@ void ZigbeeNetworkManager::setPermitJoining(bool permitJoining)
|
|||
return;
|
||||
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandPermitJoin(0, (permitJoining ? 255 : 0));
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPermitJoiningFinished);
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply, permitJoining](){
|
||||
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." << permitJoining;
|
||||
|
||||
// Read the permit joining status back in order to update the state
|
||||
readPermitJoinStatus();
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState state)
|
||||
|
|
@ -67,8 +79,7 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState
|
|||
}
|
||||
case StartingStateGetVersion: {
|
||||
qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get controller version";
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandGetVersion();
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetVersionFinished);
|
||||
readControllerVersion();
|
||||
break;
|
||||
}
|
||||
case StartingStateSetPanId: {
|
||||
|
|
@ -115,8 +126,7 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState
|
|||
}
|
||||
case StartingStateGetPermitJoinStatus: {
|
||||
qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get permit join status";
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandGetPermitJoinStatus();
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished);
|
||||
readPermitJoinStatus();
|
||||
break;
|
||||
}
|
||||
case StartingStateReadeNodeDescriptor: {
|
||||
|
|
@ -140,6 +150,57 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState
|
|||
}
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::readControllerVersion()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandGetVersion();
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->additionalMessage().data().count() != 4) {
|
||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << ":" << "Invalid payload size";
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||
|
||||
// Parse version
|
||||
quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2));
|
||||
quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2));
|
||||
|
||||
m_controllerFirmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion);
|
||||
qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion;
|
||||
|
||||
if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::readPermitJoinStatus()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = m_controller->commandGetPermitJoinStatus();
|
||||
connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->status() != ZigbeeInterfaceReply::Success) {
|
||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << reply->additionalMessage();
|
||||
|
||||
m_permitJoining = static_cast<bool>(reply->additionalMessage().data().at(0));
|
||||
emit permitJoiningChanged(m_permitJoining);
|
||||
|
||||
if (m_startingState == StartingStateGetPermitJoinStatus) setStartingState(StartingStateReadeNodeDescriptor);
|
||||
});
|
||||
}
|
||||
|
||||
//void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile)
|
||||
//{
|
||||
|
||||
|
|
@ -209,33 +270,6 @@ void ZigbeeNetworkManager::onCommandErasePersistentDataFinished()
|
|||
}
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onCommandGetVersionFinished()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (reply->additionalMessage().data().count() != 4) {
|
||||
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << ":" << "Invalid payload size";
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
|
||||
|
||||
// Parse version
|
||||
quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2));
|
||||
quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2));
|
||||
|
||||
m_controllerFirmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion);
|
||||
qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion;
|
||||
|
||||
if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onCommandSetExtendedPanIdFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
|
|
@ -309,42 +343,6 @@ void ZigbeeNetworkManager::onCommandStartScanFinished()
|
|||
processNetworkFormed(reply->additionalMessage());
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished()
|
||||
{
|
||||
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();
|
||||
|
||||
m_permitJoining = static_cast<bool>(reply->additionalMessage().data().at(0));
|
||||
emit permitJoiningChanged(m_permitJoining);
|
||||
|
||||
if (m_startingState == StartingStateGetPermitJoinStatus) setStartingState(StartingStateReadeNodeDescriptor);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onCommandPermitJoiningFinished()
|
||||
{
|
||||
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";
|
||||
|
||||
// Read the permit joining status back in order to update the state
|
||||
ZigbeeInterfaceReply *getJoiningReply = m_controller->commandGetPermitJoinStatus();
|
||||
connect(getJoiningReply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkManager::onCommandRequestMatchDescriptorFinished()
|
||||
{
|
||||
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
|
||||
|
|
@ -473,10 +471,10 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me
|
|||
quint8 channel = static_cast<quint8>(data.at(11));
|
||||
|
||||
qCDebug(dcZigbeeNetwork()).noquote() << "Network" << networkStatusString;
|
||||
qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId();
|
||||
qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
|
||||
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress);
|
||||
qCDebug(dcZigbeeNetwork()) << " Channel:" << channel;
|
||||
qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId();
|
||||
qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining();
|
||||
|
||||
m_networkRunning = true;
|
||||
|
|
@ -829,6 +827,7 @@ void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
|
|||
if (m_startingState == StartingStateReadPowerDescriptor) {
|
||||
setStartingState(StartingStateNone);
|
||||
setState(StateRunning);
|
||||
readControllerVersion();
|
||||
foreach (ZigbeeNode *node, nodes()) {
|
||||
node->setConnected(true);
|
||||
}
|
||||
|
|
@ -1091,16 +1090,41 @@ void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &m
|
|||
|
||||
void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &message)
|
||||
{
|
||||
quint8 sequenceNumber = static_cast<quint8>(message.data().at(0));
|
||||
quint16 sourceAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2));
|
||||
quint8 endPoint = static_cast<quint8>(message.data().at(3));
|
||||
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(4, 2));
|
||||
quint16 attributeId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(6, 2));
|
||||
quint8 attributDataType = static_cast<quint8>(message.data().at(8));
|
||||
QByteArray data = message.data();
|
||||
quint8 sequenceNumber = 0;
|
||||
quint16 sourceAddress = 0;
|
||||
quint8 endPoint = 0;
|
||||
quint16 clusterId = 0;
|
||||
quint16 attributeId = 0;
|
||||
quint8 attributeStatus = 0;
|
||||
quint8 attributDataType = 0;
|
||||
quint16 dataSize = 0;
|
||||
|
||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||
stream >> sequenceNumber >> sourceAddress >> endPoint >> clusterId >> attributeId >> attributeStatus >> attributDataType >> dataSize;
|
||||
|
||||
quint16 attributeSize = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(9, 2));
|
||||
QByteArray data = message.data().mid(11);
|
||||
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(attributDataType);
|
||||
QByteArray attributeData = data.left(dataSize);
|
||||
|
||||
if (attributeData.length() != dataSize) {
|
||||
qCCritical(dcZigbeeNetwork()) << "HACK";
|
||||
// Note: the NXP firmware for JN5169 has a bug here and does not send the attributeStatus.
|
||||
// Repars data without attribute status
|
||||
sequenceNumber = 0;
|
||||
sourceAddress = 0;
|
||||
endPoint = 0;
|
||||
clusterId = 0;
|
||||
attributeId = 0;
|
||||
attributeStatus = 0;
|
||||
attributDataType = 0;
|
||||
dataSize = 0;
|
||||
|
||||
QDataStream alternativeStream(&data, QIODevice::ReadOnly);
|
||||
alternativeStream >> sequenceNumber >> sourceAddress >> endPoint >> clusterId >> attributeId >> attributDataType >> dataSize;
|
||||
|
||||
dataType = static_cast<Zigbee::DataType>(attributDataType);
|
||||
attributeData = data.left(dataSize);
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Attribute report:";
|
||||
qCDebug(dcZigbeeNetwork()) << " SQN:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
|
||||
|
|
@ -1109,7 +1133,7 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
|
|||
qCDebug(dcZigbeeNetwork()) << " Cluster:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||
qCDebug(dcZigbeeNetwork()) << " Attribut id:" << ZigbeeUtils::convertUint16ToHexString(attributeId);
|
||||
qCDebug(dcZigbeeNetwork()) << " Attribut data type:" << dataType;
|
||||
qCDebug(dcZigbeeNetwork()) << " Attribut size:" << attributeSize;
|
||||
qCDebug(dcZigbeeNetwork()) << " Attribut size:" << dataSize;
|
||||
qCDebug(dcZigbeeNetwork()) << " Data:" << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||
|
||||
switch (dataType) {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ private:
|
|||
bool m_networkRunning = false;
|
||||
bool m_factoryResetting = false;
|
||||
|
||||
void readControllerVersion();
|
||||
void readPermitJoinStatus();
|
||||
|
||||
signals:
|
||||
void permitJoiningChanged(bool permitJoining);
|
||||
|
||||
|
|
@ -65,14 +68,11 @@ private slots:
|
|||
void onCommandResetControllerFinished();
|
||||
void onCommandSoftResetControllerFinished();
|
||||
void onCommandErasePersistentDataFinished();
|
||||
void onCommandGetVersionFinished();
|
||||
void onCommandSetExtendedPanIdFinished();
|
||||
void onCommandSetChannelMaskFinished();
|
||||
void onCommandSetNodeTypeFinished();
|
||||
void onCommandStartNetworkFinished();
|
||||
void onCommandStartScanFinished();
|
||||
void onCommandGetPermitJoiningStatusFinished();
|
||||
void onCommandPermitJoiningFinished();
|
||||
void onCommandEnableWhitelistFinished();
|
||||
|
||||
void onCommandNodeDescriptorRequestFinished();
|
||||
|
|
|
|||
Loading…
Reference in New Issue