From 0abeaa197bb84e3d2dcd19c71f7af2df16aeab92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Mon, 13 May 2019 18:26:32 +0200 Subject: [PATCH] Finish initalization phase of NXP network manager --- libnymea-zigbee/zigbeeaddress.h | 2 +- libnymea-zigbee/zigbeebridgecontroller.cpp | 9 + libnymea-zigbee/zigbeebridgecontroller.h | 1 + libnymea-zigbee/zigbeenetwork.cpp | 102 +++++++- libnymea-zigbee/zigbeenetwork.h | 25 +- libnymea-zigbee/zigbeenetworkmanager.cpp | 239 ++++++++++-------- libnymea-zigbee/zigbeenetworkmanager.h | 15 +- libnymea-zigbee/zigbeenode.cpp | 75 ++++++ libnymea-zigbee/zigbeenode.h | 27 +- .../zigbeesecurityconfiguration.cpp | 16 ++ libnymea-zigbee/zigbeesecurityconfiguration.h | 6 +- 11 files changed, 392 insertions(+), 125 deletions(-) diff --git a/libnymea-zigbee/zigbeeaddress.h b/libnymea-zigbee/zigbeeaddress.h index 5589ba7..a8dd01c 100644 --- a/libnymea-zigbee/zigbeeaddress.h +++ b/libnymea-zigbee/zigbeeaddress.h @@ -21,7 +21,7 @@ public: ZigbeeAddress &operator=(const ZigbeeAddress &other); bool operator<(const ZigbeeAddress &other) const; bool operator==(const ZigbeeAddress &other) const; - inline bool operator!=(const ZigbeeAddress &other) const; + bool operator!=(const ZigbeeAddress &other) const; private: quint64 m_address; diff --git a/libnymea-zigbee/zigbeebridgecontroller.cpp b/libnymea-zigbee/zigbeebridgecontroller.cpp index 82c0c03..a837c9e 100644 --- a/libnymea-zigbee/zigbeebridgecontroller.cpp +++ b/libnymea-zigbee/zigbeebridgecontroller.cpp @@ -26,6 +26,15 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandResetController() return sendRequest(request); } +ZigbeeInterfaceReply *ZigbeeBridgeController::commandSoftResetController() +{ + ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeZllFactoryNew, QByteArray())); + request.setDescription("Soft reset controller"); + request.setTimoutIntervall(5000); + + return sendRequest(request); +} + ZigbeeInterfaceReply *ZigbeeBridgeController::commandErasePersistantData() { ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeErasePersistentData, QByteArray())); diff --git a/libnymea-zigbee/zigbeebridgecontroller.h b/libnymea-zigbee/zigbeebridgecontroller.h index c081950..8a07d84 100644 --- a/libnymea-zigbee/zigbeebridgecontroller.h +++ b/libnymea-zigbee/zigbeebridgecontroller.h @@ -21,6 +21,7 @@ public: // Direct commands ZigbeeInterfaceReply *commandResetController(); + ZigbeeInterfaceReply *commandSoftResetController(); ZigbeeInterfaceReply *commandErasePersistantData(); ZigbeeInterfaceReply *commandGetVersion(); ZigbeeInterfaceReply *commandSetExtendedPanId(quint64 extendedPanId); diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index ac1c80a..f35afca 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -1,3 +1,4 @@ +#include "zigbeeutils.h" #include "zigbeenetwork.h" #include "loggingcategory.h" @@ -23,6 +24,20 @@ ZigbeeNetwork::Error ZigbeeNetwork::error() const return m_error; } +QString ZigbeeNetwork::settingsFilenName() const +{ + return m_settingsFileName; +} + +void ZigbeeNetwork::setSettingsFileName(const QString &settingsFileName) +{ + if (m_settingsFileName == settingsFileName) + return; + + m_settingsFileName = settingsFileName; + emit settingsFileNameChanged(m_settingsFileName); +} + QString ZigbeeNetwork::serialPortName() const { return m_serialPortName; @@ -30,7 +45,11 @@ QString ZigbeeNetwork::serialPortName() const void ZigbeeNetwork::setSerialPortName(const QString &serialPortName) { + if (m_serialPortName == serialPortName) + return; + m_serialPortName = serialPortName; + emit serialPortNameChanged(m_serialPortName); } qint32 ZigbeeNetwork::serialBaudrate() const @@ -40,7 +59,11 @@ qint32 ZigbeeNetwork::serialBaudrate() const void ZigbeeNetwork::setSerialBaudrate(qint32 baudrate) { + if (m_serialBaudrate == baudrate) + return; + m_serialBaudrate = baudrate; + emit serialBaudrateChanged(m_serialBaudrate); } quint64 ZigbeeNetwork::extendedPanId() const @@ -50,7 +73,11 @@ quint64 ZigbeeNetwork::extendedPanId() const void ZigbeeNetwork::setExtendedPanId(quint64 extendedPanId) { + if (m_extendedPanId == extendedPanId) + return; + m_extendedPanId = extendedPanId; + emit extendedPanIdChanged(m_extendedPanId); } uint ZigbeeNetwork::channel() const @@ -60,7 +87,11 @@ uint ZigbeeNetwork::channel() const void ZigbeeNetwork::setChannel(uint channel) { + if (m_channel == channel) + return; + m_channel = channel; + emit channelChanged(m_channel); } ZigbeeSecurityConfiguration ZigbeeNetwork::securityConfiguration() const @@ -70,7 +101,11 @@ ZigbeeSecurityConfiguration ZigbeeNetwork::securityConfiguration() const void ZigbeeNetwork::setSecurityConfiguration(const ZigbeeSecurityConfiguration &securityConfiguration) { + if (m_securityConfiguration == securityConfiguration) + return; + m_securityConfiguration = securityConfiguration; + emit securityConfigurationChanged(m_securityConfiguration); } QList ZigbeeNetwork::nodes() const @@ -78,7 +113,12 @@ QList ZigbeeNetwork::nodes() const return m_nodes; } -ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) +ZigbeeNode *ZigbeeNetwork::coordinatorNode() const +{ + return getZigbeeNode(0); +} + +ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const { foreach (ZigbeeNode *node, m_nodes) { if (node->shortAddress() == shortAddress) { @@ -89,7 +129,7 @@ ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) return nullptr; } -ZigbeeNode *ZigbeeNetwork::getZigbeeNode(ZigbeeAddress address) +ZigbeeNode *ZigbeeNetwork::getZigbeeNode(ZigbeeAddress address) const { foreach (ZigbeeNode *node, m_nodes) { if (node->extendedAddress() == address) { @@ -100,6 +140,59 @@ ZigbeeNode *ZigbeeNetwork::getZigbeeNode(ZigbeeAddress address) return nullptr; } +void ZigbeeNetwork::saveNetwork() +{ + qCDebug(dcZigbeeNetwork()) << "Save current network configuration to" << m_settingsFileName; + QSettings settings(m_settingsFileName, QSettings::IniFormat, this); + settings.beginGroup("Network"); + settings.setValue("panId", extendedPanId()); + settings.setValue("channel", channel()); + settings.endGroup(); + + settings.beginWriteArray("Nodes"); + for (int i = 0; i < nodes().count(); i++) { + settings.setArrayIndex(i); + settings.setValue("nwkAddress", nodes().at(i)->shortAddress()); + settings.setValue("ieeeAddress", nodes().at(i)->extendedAddress().toString()); + // TODO: save the rest of the node + } + settings.endArray(); +} + +void ZigbeeNetwork::loadNetwork() +{ + qCDebug(dcZigbeeNetwork()) << "Load current network configuration from" << m_settingsFileName; + QSettings settings(m_settingsFileName, QSettings::IniFormat, this); + settings.beginGroup("Network"); + quint64 extendedPanId = static_cast(settings.value("panId", 0).toUInt()); + if (extendedPanId == 0) { + extendedPanId = ZigbeeUtils::generateRandomPanId(); + qCDebug(dcZigbeeNetwork()) << "Create new PAN id" << extendedPanId; + } + setExtendedPanId(extendedPanId); + setChannel(settings.value("channel", 0).toUInt()); + settings.endGroup(); + + settings.beginReadArray("Nodes"); + for (int i = 0; i < nodes().count(); i++) { + settings.setArrayIndex(i); + ZigbeeNode *node = new ZigbeeNode(this); + node->setShortAddress(static_cast(settings.value("nwkAddress", 0).toUInt())); + node->setExtendedAddress(ZigbeeAddress(settings.value("ieeeAddress").toString())); + + // TODO: load the rest of the node + } + settings.endArray(); + + qCDebug(dcZigbeeNetwork()) << "PAN Id:" << m_extendedPanId << ZigbeeUtils::convertUint64ToHexString(m_extendedPanId); + qCDebug(dcZigbeeNetwork()) << "Channel" << m_channel; + + qCDebug(dcZigbeeNetwork()) << "Nodes:"; + foreach (ZigbeeNode *node, nodes()) { + qCDebug(dcZigbeeNetwork()) << " - " << node; + } +} + void ZigbeeNetwork::addNode(ZigbeeNode *node) { if (m_nodes.contains(node)) { @@ -109,6 +202,7 @@ void ZigbeeNetwork::addNode(ZigbeeNode *node) m_nodes.append(node); emit nodeAdded(node); + saveNetwork(); } void ZigbeeNetwork::removeNode(ZigbeeNode *node) @@ -120,6 +214,7 @@ void ZigbeeNetwork::removeNode(ZigbeeNode *node) m_nodes.removeAll(node); emit nodeRemoved(node); + saveNetwork(); } void ZigbeeNetwork::setState(ZigbeeNetwork::State state) @@ -130,6 +225,9 @@ void ZigbeeNetwork::setState(ZigbeeNetwork::State state) qCDebug(dcZigbeeNetwork()) << "State changed" << state; m_state = state; emit stateChanged(m_state); + + if (state == StateRunning) saveNetwork(); + if (state == StateStarting) loadNetwork(); } void ZigbeeNetwork::setError(ZigbeeNetwork::Error error) diff --git a/libnymea-zigbee/zigbeenetwork.h b/libnymea-zigbee/zigbeenetwork.h index b2802d5..7b85934 100644 --- a/libnymea-zigbee/zigbeenetwork.h +++ b/libnymea-zigbee/zigbeenetwork.h @@ -2,6 +2,7 @@ #define ZIGBEENETWORK_H #include +#include #include "zigbeenode.h" #include "zigbeesecurityconfiguration.h" @@ -26,7 +27,8 @@ public: enum Error { ErrorNoError, - ErrorHardwareUnavailable + ErrorHardwareUnavailable, + ErrorZigbeeError }; Q_ENUM(Error) @@ -37,6 +39,9 @@ public: Error error() const; + QString settingsFilenName() const; + void setSettingsFileName(const QString &settingsFileName); + // Serial port configuration QString serialPortName() const; void setSerialPortName(const QString &serialPortName); @@ -56,8 +61,9 @@ public: QList nodes() const; - ZigbeeNode *getZigbeeNode(quint16 shortAddress); - ZigbeeNode *getZigbeeNode(ZigbeeAddress address); + ZigbeeNode *coordinatorNode() const; + ZigbeeNode *getZigbeeNode(quint16 shortAddress) const; + ZigbeeNode *getZigbeeNode(ZigbeeAddress address) const; private: ControllerType m_controllerType = ControlerTypeNxp; @@ -74,8 +80,12 @@ private: ZigbeeSecurityConfiguration m_securityConfiguration; ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator; + QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf"; QList m_nodes; + void saveNetwork(); + void loadNetwork(); + protected: void addNode(ZigbeeNode *node); void removeNode(ZigbeeNode *node); @@ -84,9 +94,18 @@ protected: void setError(Error error); signals: + void settingsFileNameChanged(const QString &settingsFileName); + void serialPortNameChanged(const QString &serialPortName); + void serialBaudrateChanged(qint32 serialBaudrate); + + void extendedPanIdChanged(quint64 extendedPanId); + void channelChanged(uint channel); + void securityConfigurationChanged(const ZigbeeSecurityConfiguration &securityConfiguration); + void nodeAdded(ZigbeeNode *node); void nodeRemoved(ZigbeeNode *node); + void permitJoiningChanged(bool permitJoining); void stateChanged(State state); void errorOccured(Error error); diff --git a/libnymea-zigbee/zigbeenetworkmanager.cpp b/libnymea-zigbee/zigbeenetworkmanager.cpp index 80cbf81..f6713ce 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.cpp +++ b/libnymea-zigbee/zigbeenetworkmanager.cpp @@ -9,30 +9,6 @@ ZigbeeNetworkManager::ZigbeeNetworkManager(QObject *parent) : ZigbeeNetwork(ZigbeeNetwork::ControlerTypeNxp, parent) { - - //connect(controller(), &ZigbeeBridgeController::messageReceived, this, &ZigbeeNetworkManager::onMessageReceived); - - //Q_UNUSED(channel) - // if (controller()->available()) { - // qCDebug(dcZigbeeNetwork()) << "Bridge controller started successfully on" << controller; - // } else { - // qCCritical(dcZigbeeNetwork()) << "The zigbee controller is not available on" << controller; - // return; - // } - - // QSettings settings; - // qCDebug(dcZigbeeNetwork()) << "Loading settings from" << settings.fileName(); - // settings.beginGroup("Network"); - // m_extendedPanId = static_cast(settings.value("panId", 0).toLongLong()); - // qCDebug(dcZigbeeNetwork()) << "Loading saved pan id" << m_extendedPanId; - // if (m_extendedPanId == 0) { - // m_extendedPanId = generateRandomPanId(); - // settings.setValue("panId", m_extendedPanId); - // } - // settings.endGroup(); - - // qCDebug(dcZigbeeNetwork()) << "PAN Id:" << m_extendedPanId << ZigbeeUtils::convertUint64ToHexString(m_extendedPanId); - // // Create channel mask // // Note: normal number passed, that specific channel will be used || Bitfield: all channels would be 0x07FFF800 // quint32 channelMask = 0; @@ -43,10 +19,6 @@ ZigbeeNetworkManager::ZigbeeNetworkManager(QObject *parent) : // qCDebug(dcZigbeeNetwork()) << "Using channel" << channel << "for the zigbee network."; // } - // loadNetwork(); - // resetController(); - // getVersion(); - // init(); } QString ZigbeeNetworkManager::controllerVersion() const @@ -59,33 +31,52 @@ bool ZigbeeNetworkManager::networkRunning() const return state() == ZigbeeNetwork::StateRunning; } +bool ZigbeeNetworkManager::permitJoining() const +{ + return m_permitJoining; +} + +void ZigbeeNetworkManager::setPermitJoining(bool permitJoining) +{ + if (m_permitJoining == permitJoining) + return; + + ZigbeeInterfaceReply *reply = m_controller->commandPermitJoin(0, (permitJoining ? 255 : 0)); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPermitJoiningFinished); +} + void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState state) { if (m_startingState == state) return; - qCDebug(dcZigbeeNetwork()) << state; m_startingState = state; switch (m_startingState) { case StartingStateNone: break; case StartingStateErase: { + m_networkRunning = false; + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Erase persistant data"; ZigbeeInterfaceReply *reply = m_controller->commandErasePersistantData(); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandErasePersistentDataFinished); break; } case StartingStateReset: { + m_networkRunning = false; + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Reset controller"; ZigbeeInterfaceReply *reply = m_controller->commandResetController(); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandResetControllerFinished); break; } case StartingStateGetVersion: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get controller version"; ZigbeeInterfaceReply *reply = m_controller->commandGetVersion(); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetVersionFinished); break; } case StartingStateSetPanId: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set PAN ID"; if (extendedPanId() == 0) { setExtendedPanId(ZigbeeUtils::generateRandomPanId()); } @@ -96,6 +87,7 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState case StartingStateSetChannel: { // Create channel mask // Note: normal number passed, that specific channel will be used || Bitfield: all channels would be 0x07FFF800 + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set channel mask"; quint32 channelMask = 0; if (channel() == 0) { qCDebug(dcZigbeeNetwork()) << "Autoselect quitest channel for the zigbee network."; @@ -108,26 +100,43 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState break; } case StartingStateSetSecurity: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set security configuration"; ZigbeeInterfaceReply *reply = m_controller->commandSetSecurityStateAndKey(4, 0, 1, "5A6967426565416C6C69616E63653039"); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetSecurityFinished); break; } + case StartingStateSetNodeType: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set node type"; + ZigbeeInterfaceReply *reply = m_controller->commandSetNodeType(ZigbeeNode::NodeTypeCoordinator); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetNodeTypeFinished); + break; + } case StartingStateStartNetwork: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Starting network"; ZigbeeInterfaceReply *reply = m_controller->commandStartNetwork(); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandStartNetworkFinished); break; } + case StartingStateGetPermitJoinStatus: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Get permit join status"; + ZigbeeInterfaceReply *reply = m_controller->commandGetPermitJoinStatus(); + connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished); + break; + } case StartingStateReadeNodeDescriptor: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator node descriptor"; ZigbeeInterfaceReply *reply = m_controller->commandNodeDescriptorRequest(shortAddress()); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished); break; } case StartingStateReadSimpleDescriptor: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator simple descriptor"; ZigbeeInterfaceReply *reply = m_controller->commandSimpleDescriptorRequest(shortAddress(), endPoint()); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished); break; } case StartingStateReadPowerDescriptor: { + qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator power descriptor"; ZigbeeInterfaceReply *reply = m_controller->commandPowerDescriptorRequest(shortAddress()); connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished); break; @@ -135,40 +144,6 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState } } - -//void ZigbeeNetworkManager::parseNetworkFormed(const QByteArray &data) -//{ -// // Parse network status -// quint8 networkStatus = static_cast(data.at(0)); -// QString networkStatusString; - -// if (networkStatus == 0) { -// networkStatusString = "joined"; -// } else if (networkStatus == 1) { -// networkStatusString = "created"; -// } else if (networkStatus >= 128 && networkStatus <= 244) { -// networkStatusString = "failed: Zigbee event code: " + QString::number(networkStatus); -// } else { -// networkStatusString = "unknown"; -// } - -// quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(data.mid(1, 2)); -// quint64 extendedAddress = ZigbeeUtils::convertByteArrayToUint64(data.mid(3, 8)); - -// // Parse network channel -// quint8 channel = static_cast(data.at(11)); - -// qCDebug(dcZigbeeNetwork()).noquote() << "Network" << networkStatusString; -// qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); -// qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress); -// qCDebug(dcZigbeeNetwork()) << " Channel:" << channel; - -// // Set the node information -// setShortAddress(shortAddress); -// setExtendedAddress(ZigbeeAddress(extendedAddress)); - -//} - //void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile) //{ @@ -207,6 +182,19 @@ void ZigbeeNetworkManager::onCommandResetControllerFinished() qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; } +void ZigbeeNetworkManager::onCommandSoftResetControllerFinished() +{ + ZigbeeInterfaceReply *reply = static_cast(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::onCommandErasePersistentDataFinished() { ZigbeeInterfaceReply *reply = static_cast(sender()); @@ -276,7 +264,7 @@ void ZigbeeNetworkManager::onCommandSetChannelMaskFinished() if (m_startingState == StartingStateSetChannel) setStartingState(StartingStateSetSecurity); } -void ZigbeeNetworkManager::onCommandSetDeviceTypeFinished() +void ZigbeeNetworkManager::onCommandSetNodeTypeFinished() { ZigbeeInterfaceReply *reply = static_cast(sender()); reply->deleteLater(); @@ -287,6 +275,7 @@ void ZigbeeNetworkManager::onCommandSetDeviceTypeFinished() } qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + if (m_startingState == StartingStateSetNodeType) setStartingState(StartingStateStartNetwork); } void ZigbeeNetworkManager::onCommandStartNetworkFinished() @@ -302,7 +291,7 @@ void ZigbeeNetworkManager::onCommandStartNetworkFinished() qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; qCDebug(dcZigbeeController()) << reply->additionalMessage(); processNetworkFormed(reply->additionalMessage()); - if (m_startingState == StartingStateStartNetwork) setStartingState(StartingStateReadeNodeDescriptor); + if (m_startingState == StartingStateStartNetwork) setStartingState(StartingStateGetPermitJoinStatus); } void ZigbeeNetworkManager::onCommandStartScanFinished() @@ -332,6 +321,11 @@ void ZigbeeNetworkManager::onCommandGetPermitJoiningStatusFinished() qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; qCDebug(dcZigbeeController()) << reply->additionalMessage(); + + m_permitJoining = static_cast(reply->additionalMessage().data().at(0)); + emit permitJoiningChanged(m_permitJoining); + + if (m_startingState == StartingStateGetPermitJoinStatus) setStartingState(StartingStateReadeNodeDescriptor); } void ZigbeeNetworkManager::onCommandPermitJoiningFinished() @@ -345,6 +339,10 @@ void ZigbeeNetworkManager::onCommandPermitJoiningFinished() } 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() @@ -372,7 +370,7 @@ void ZigbeeNetworkManager::onCommandSetSecurityFinished() } qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; - if (m_startingState == StartingStateSetSecurity) setStartingState(StartingStateStartNetwork); + if (m_startingState == StartingStateSetSecurity) setStartingState(StartingStateSetNodeType); } void ZigbeeNetworkManager::onCommandNetworkAddressRequestFinished() @@ -446,16 +444,29 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me quint8 networkStatus = static_cast(data.at(0)); QString networkStatusString; + bool success = false; + if (networkStatus == 0) { networkStatusString = "joined"; + success = true; } else if (networkStatus == 1) { networkStatusString = "created"; + success = true; } else if (networkStatus >= 128 && networkStatus <= 244) { networkStatusString = "failed: Zigbee event code: " + QString::number(networkStatus); } else { networkStatusString = "unknown"; } + if (!success) { + qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatusString; + setError(ErrorZigbeeError); + setStartingState(StartingStateNone); + setState(StateDisconnected); + m_networkRunning = false; + return; + } + quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(data.mid(1, 2)); quint64 extendedAddress = ZigbeeUtils::convertByteArrayToUint64(data.mid(3, 8)); @@ -467,13 +478,14 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress); qCDebug(dcZigbeeNetwork()) << " Channel:" << channel; + m_networkRunning = true; + // Set the node information setShortAddress(shortAddress); setExtendedAddress(ZigbeeAddress(extendedAddress)); setChannel(channel); addNode(this); - } void ZigbeeNetworkManager::onCommandEnableWhitelistFinished() @@ -500,6 +512,7 @@ void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished() } qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; + qCDebug(dcZigbeeController()) << reply->additionalMessage(); quint8 sequenceNumber = static_cast(reply->additionalMessage().data().at(0)); quint8 status = static_cast(reply->additionalMessage().data().at(1)); @@ -544,55 +557,52 @@ void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished() node->setMaximumTxSize(maximalTxSize); node->setMaximumBufferSize(maxBufferSize); node->setServerMask(serverMask); - node->setDescriptorFlag(descriptorFlag); node->setMacCapabilitiesFlag(macFlags); + node->setDescriptorFlag(descriptorFlag); // Parse bit field - bool isCoordinator = ((bitField >> 0) & 0x0001); - bool isRouter = ((bitField >> 1) & 0x0001); - bool isEndDevice = ((bitField >> 2) & 0x0001); + // 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device + if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { + node->setNodeType(NodeTypeCoordinator); + } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) { + node->setNodeType(NodeTypeCoordinator); + } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { + node->setNodeType(NodeTypeEndDevice); + } node->setComplexDescriptorAvailable((bitField >> 3) & 0x0001); node->setUserDescriptorAvailable((bitField >> 4) & 0x0001); - if (isCoordinator && !isRouter && !isEndDevice) { - node->setNodeType(NodeTypeCoordinator); - } else if (!isCoordinator && isRouter && !isEndDevice) { - node->setNodeType(NodeTypeRouter); - } else if (!isCoordinator && !isRouter && isEndDevice) { - node->setNodeType(NodeTypeEndDevice); - } - - - // qCDebug(dcZigbeeNetwork()) << "Node descriptor:"; - // qCDebug(dcZigbeeNetwork()) << " Node type:" << node->nodeType(); - // qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); - // qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); - // qCDebug(dcZigbeeNetwork()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); - // qCDebug(dcZigbeeNetwork()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode); - // qCDebug(dcZigbeeNetwork()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumRxSize()); - // qCDebug(dcZigbeeNetwork()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumTxSize()); - // qCDebug(dcZigbeeNetwork()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask); - // qCDebug(dcZigbeeNetwork()) << " Primary Trust center:" << m_isPrimaryTrustCenter; - // qCDebug(dcZigbeeNetwork()) << " Backup Trust center:" << m_isBackupTrustCenter; - // qCDebug(dcZigbeeNetwork()) << " Primary Binding cache:" << m_isPrimaryBindingCache; - // qCDebug(dcZigbeeNetwork()) << " Backup Binding cache:" << m_isBackupBindingCache; - // qCDebug(dcZigbeeNetwork()) << " Primary Discovery cache:" << m_isPrimaryDiscoveryCache; - // qCDebug(dcZigbeeNetwork()) << " Backup Discovery cache:" << m_isBackupDiscoveryCache; - // qCDebug(dcZigbeeNetwork()) << " Network Manager:" << m_isNetworkManager; - // qCDebug(dcZigbeeNetwork()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag); - // qCDebug(dcZigbeeNetwork()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable; - // qCDebug(dcZigbeeNetwork()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable; - // qCDebug(dcZigbeeNetwork()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags); - // qCDebug(dcZigbeeNetwork()) << " Receiver on when idle:" << m_receiverOnWhenIdle; - // qCDebug(dcZigbeeNetwork()) << " Security capability:" << m_securityCapability; - // qCDebug(dcZigbeeNetwork()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maxBufferSize); - // qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField); - // qCDebug(dcZigbeeNetwork()) << " Is coordinator:" << isCoordinator; - // qCDebug(dcZigbeeNetwork()) << " Is router:" << isRouter; - // qCDebug(dcZigbeeNetwork()) << " Is end device:" << isEndDevice; - // qCDebug(dcZigbeeNetwork()) << " Complex desciptor available:" << complexDescriptorAvailable; - // qCDebug(dcZigbeeNetwork()) << " User desciptor available:" << userDescriptorAvailable; + qCDebug(dcZigbeeNetwork()) << "Node descriptor:"; + qCDebug(dcZigbeeNetwork()) << " Node type:" << node->nodeType(); + qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber); + qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status); + qCDebug(dcZigbeeNetwork()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); + qCDebug(dcZigbeeNetwork()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode); + qCDebug(dcZigbeeNetwork()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumRxSize()); + qCDebug(dcZigbeeNetwork()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumTxSize()); + qCDebug(dcZigbeeNetwork()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(node->maximumBufferSize()); + qCDebug(dcZigbeeNetwork()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask); + qCDebug(dcZigbeeNetwork()) << " Primary Trust center:" << node->isPrimaryTrustCenter(); + qCDebug(dcZigbeeNetwork()) << " Backup Trust center:" << node->isBackupTrustCenter(); + qCDebug(dcZigbeeNetwork()) << " Primary Binding cache:" << node->isPrimaryBindingCache(); + qCDebug(dcZigbeeNetwork()) << " Backup Binding cache:" << node->isBackupBindingCache(); + qCDebug(dcZigbeeNetwork()) << " Primary Discovery cache:" << node->isPrimaryDiscoveryCache(); + qCDebug(dcZigbeeNetwork()) << " Backup Discovery cache:" << node->isBackupDiscoveryCache(); + qCDebug(dcZigbeeNetwork()) << " Network Manager:" << node->isNetworkManager(); + qCDebug(dcZigbeeNetwork()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag); + qCDebug(dcZigbeeNetwork()) << " Extended active endpoint list available:" << node->extendedActiveEndpointListAvailable(); + qCDebug(dcZigbeeNetwork()) << " Extended simple descriptor list available:" << node->extendedSimpleDescriptorListAvailable(); + qCDebug(dcZigbeeNetwork()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags); + qCDebug(dcZigbeeNetwork()) << " Alternate PAN coordinator:" << node->alternatePanCoordinator(); + qCDebug(dcZigbeeNetwork()) << " Device type:" << node->deviceType(); + qCDebug(dcZigbeeNetwork()) << " Power source flag main power:" << node->powerSourceFlagMainPower(); + qCDebug(dcZigbeeNetwork()) << " Receiver on when idle:" << node->receiverOnWhenIdle(); + qCDebug(dcZigbeeNetwork()) << " Security capability:" << node->securityCapability(); + qCDebug(dcZigbeeNetwork()) << " Allocate address:" << node->allocateAddress(); + qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField); + qCDebug(dcZigbeeNetwork()) << " Complex desciptor available:" << node->complexDescriptorAvailable(); + qCDebug(dcZigbeeNetwork()) << " User desciptor available:" << node->userDescriptorAvailable(); if (m_startingState == StartingStateReadeNodeDescriptor) setStartingState(StartingStateReadSimpleDescriptor); } @@ -1083,6 +1093,12 @@ void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessag break; } + if (m_startingState == StartingStateReset) { + qCDebug(dcZigbeeNetwork()) << "Reset finished."; + if (m_networkRunning) { + setStartingState(StartingStateGetPermitJoinStatus); + } + } } void ZigbeeNetworkManager::startNetwork() @@ -1103,7 +1119,7 @@ void ZigbeeNetworkManager::startNetwork() } else { // Reset setState(StateStarting); - setStartingState(StartingStateErase); + setStartingState(StartingStateReset); } } @@ -1158,10 +1174,11 @@ void ZigbeeNetworkManager::onControllerAvailableChanged(bool available) if (!available) { setError(ErrorHardwareUnavailable); setState(StateDisconnected); + setStartingState(StartingStateNone); } else { setError(ErrorNoError); setState(StateStarting); - setStartingState(StartingStateErase); + setStartingState(StartingStateReset); } } diff --git a/libnymea-zigbee/zigbeenetworkmanager.h b/libnymea-zigbee/zigbeenetworkmanager.h index f26cccf..fb1c711 100644 --- a/libnymea-zigbee/zigbeenetworkmanager.h +++ b/libnymea-zigbee/zigbeenetworkmanager.h @@ -18,6 +18,11 @@ public: bool networkRunning() const; + // Note: Follwoing methods should be abstract + bool permitJoining() const; + void setPermitJoining(bool permitJoining); + + private: enum StartingState { StartingStateNone, @@ -27,7 +32,9 @@ private: StartingStateSetPanId, StartingStateSetChannel, StartingStateSetSecurity, + StartingStateSetNodeType, StartingStateStartNetwork, + StartingStateGetPermitJoinStatus, StartingStateReadeNodeDescriptor, StartingStateReadSimpleDescriptor, StartingStateReadPowerDescriptor @@ -39,8 +46,11 @@ private: StartingState m_startingState = StartingStateNone; void setStartingState(StartingState state); + bool m_permitJoining = false; + bool m_networkRunning = false; + signals: - void runningChanged(const bool &running); + void permitJoiningChanged(bool permitJoining); private slots: void onMessageReceived(const ZigbeeInterfaceMessage &message); @@ -48,11 +58,12 @@ private slots: // Controller command finished slots void onCommandResetControllerFinished(); + void onCommandSoftResetControllerFinished(); void onCommandErasePersistentDataFinished(); void onCommandGetVersionFinished(); void onCommandSetExtendedPanIdFinished(); void onCommandSetChannelMaskFinished(); - void onCommandSetDeviceTypeFinished(); + void onCommandSetNodeTypeFinished(); void onCommandStartNetworkFinished(); void onCommandStartScanFinished(); void onCommandGetPermitJoiningStatusFinished(); diff --git a/libnymea-zigbee/zigbeenode.cpp b/libnymea-zigbee/zigbeenode.cpp index fb4450d..177aecd 100644 --- a/libnymea-zigbee/zigbeenode.cpp +++ b/libnymea-zigbee/zigbeenode.cpp @@ -75,6 +75,81 @@ quint8 ZigbeeNode::maximumBufferSize() const return m_maximumBufferSize; } +bool ZigbeeNode::isPrimaryTrustCenter() const +{ + return m_isPrimaryTrustCenter; +} + +bool ZigbeeNode::isBackupTrustCenter() const +{ + return m_isBackupTrustCenter; +} + +bool ZigbeeNode::isPrimaryBindingCache() const +{ + return m_isPrimaryBindingCache; +} + +bool ZigbeeNode::isBackupBindingCache() const +{ + return m_isBackupBindingCache; +} + +bool ZigbeeNode::isPrimaryDiscoveryCache() const +{ + return m_isPrimaryDiscoveryCache; +} + +bool ZigbeeNode::isBackupDiscoveryCache() const +{ + return m_isBackupDiscoveryCache; +} + +bool ZigbeeNode::isNetworkManager() const +{ + return m_isNetworkManager; +} + +bool ZigbeeNode::extendedActiveEndpointListAvailable() const +{ + return m_extendedActiveEndpointListAvailable; +} + +bool ZigbeeNode::extendedSimpleDescriptorListAvailable() const +{ + return m_extendedSimpleDescriptorListAvailable; +} + +bool ZigbeeNode::alternatePanCoordinator() const +{ + return m_alternatePanCoordinator; +} + +ZigbeeNode::DeviceType ZigbeeNode::deviceType() const +{ + return m_deviceType; +} + +bool ZigbeeNode::powerSourceFlagMainPower() const +{ + return m_powerSourceFlagMainPower; +} + +bool ZigbeeNode::receiverOnWhenIdle() const +{ + return m_receiverOnWhenIdle; +} + +bool ZigbeeNode::securityCapability() const +{ + return m_securityCapability; +} + +bool ZigbeeNode::allocateAddress() const +{ + return m_allocateAddress; +} + ZigbeeNode::PowerMode ZigbeeNode::powerMode() const { return m_powerMode; diff --git a/libnymea-zigbee/zigbeenode.h b/libnymea-zigbee/zigbeenode.h index d81f884..f8bb671 100644 --- a/libnymea-zigbee/zigbeenode.h +++ b/libnymea-zigbee/zigbeenode.h @@ -10,6 +10,7 @@ class ZigbeeNode : public QObject { Q_OBJECT + friend class ZigbeeNetwork; friend class ZigbeeNetworkManager; public: @@ -82,17 +83,33 @@ public: quint16 maximumTxSize() const; quint8 maximumBufferSize() const; + // Server Mask + bool isPrimaryTrustCenter() const; + bool isBackupTrustCenter() const; + bool isPrimaryBindingCache() const; + bool isBackupBindingCache() const; + bool isPrimaryDiscoveryCache() const; + bool isBackupDiscoveryCache() const; + bool isNetworkManager() const; + + // Descriptor capability + bool extendedActiveEndpointListAvailable() const; + bool extendedSimpleDescriptorListAvailable() const; + + // Mac capabilities flag + bool alternatePanCoordinator() const; + DeviceType deviceType() const; + bool powerSourceFlagMainPower() const; + bool receiverOnWhenIdle() const; + bool securityCapability() const; + bool allocateAddress() const; + // Information from node power descriptor PowerMode powerMode() const; PowerSource powerSource() const; QList availablePowerSources() const; PowerLevel powerLevel() const; - // Node specific zigbee commands -// void init(); -// void identify(); -// void toggle(int addressMode); - private: quint16 m_shortAddress = 0; ZigbeeAddress m_extendedAddress; diff --git a/libnymea-zigbee/zigbeesecurityconfiguration.cpp b/libnymea-zigbee/zigbeesecurityconfiguration.cpp index 2ce5787..1049624 100644 --- a/libnymea-zigbee/zigbeesecurityconfiguration.cpp +++ b/libnymea-zigbee/zigbeesecurityconfiguration.cpp @@ -5,6 +5,12 @@ ZigbeeSecurityConfiguration::ZigbeeSecurityConfiguration() } +ZigbeeSecurityConfiguration::ZigbeeSecurityConfiguration(const ZigbeeSecurityConfiguration &other) +{ + m_networkKey = other.networkKey(); + m_globalTrustCenterLinkKey = other.networkKey(); +} + QString ZigbeeSecurityConfiguration::networkKey() const { return m_networkKey; @@ -24,3 +30,13 @@ void ZigbeeSecurityConfiguration::setGlobalTrustCenterlinkKey(const QString &glo { m_globalTrustCenterLinkKey = globalTrustCenterLinkKey; } + +bool ZigbeeSecurityConfiguration::operator==(const ZigbeeSecurityConfiguration &other) const +{ + return m_networkKey == other.networkKey() && m_globalTrustCenterLinkKey == other.globalTrustCenterLinkKey(); +} + +bool ZigbeeSecurityConfiguration::operator!=(const ZigbeeSecurityConfiguration &other) const +{ + return !operator==(other); +} diff --git a/libnymea-zigbee/zigbeesecurityconfiguration.h b/libnymea-zigbee/zigbeesecurityconfiguration.h index 8f18c80..3b08835 100644 --- a/libnymea-zigbee/zigbeesecurityconfiguration.h +++ b/libnymea-zigbee/zigbeesecurityconfiguration.h @@ -6,7 +6,8 @@ class ZigbeeSecurityConfiguration { public: - ZigbeeSecurityConfiguration(); + explicit ZigbeeSecurityConfiguration(); + ZigbeeSecurityConfiguration(const ZigbeeSecurityConfiguration &other); QString networkKey() const; void setNetworkKey(const QString &networkKey); @@ -14,6 +15,9 @@ public: QString globalTrustCenterLinkKey() const; void setGlobalTrustCenterlinkKey(const QString & globalTrustCenterLinkKey); + bool operator==(const ZigbeeSecurityConfiguration &other) const; + bool operator!=(const ZigbeeSecurityConfiguration &other) const; + private: // This is the local network key QString m_networkKey;