Improve startup procedure and node creation mechanism

This commit is contained in:
Simon Stürz 2019-05-14 21:27:07 +02:00
parent 0abeaa197b
commit 2922a87449
10 changed files with 67156 additions and 50 deletions

11
README.md Normal file
View File

@ -0,0 +1,11 @@
# nymea-zigbee
This repository contains the nymea-zigbee library and tools.
# Supported hardware
## NXP
* JN5168 (SoM)
* JN5169 (USB Stick)

File diff suppressed because one or more lines are too long

View File

@ -232,6 +232,7 @@ void ZigbeeInterface::disable()
delete m_serialPort; delete m_serialPort;
m_serialPort = nullptr; m_serialPort = nullptr;
setAvailable(false);
qCDebug(dcZigbeeInterface()) << "Interface disabled"; qCDebug(dcZigbeeInterface()) << "Interface disabled";
} }

View File

@ -261,7 +261,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandNodeDescriptorRequest(quint
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data)); ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse); request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress)); request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
request.setTimoutIntervall(5000); request.setTimoutIntervall(10000);
return sendRequest(request); return sendRequest(request);
} }
@ -275,7 +275,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSimpleDescriptorRequest(qui
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSimpleDescriptorRequest, data)); ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSimpleDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeSimpleDescriptorResponse); request.setExpectedAdditionalMessageType(Zigbee::MessageTypeSimpleDescriptorResponse);
request.setDescription("Simple node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress) + "endpoint " + QString::number(endpoint)); request.setDescription("Simple node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress) + " endpoint " + QString::number(endpoint));
request.setTimoutIntervall(5000); request.setTimoutIntervall(5000);
return sendRequest(request); return sendRequest(request);
@ -329,16 +329,24 @@ void ZigbeeBridgeController::onMessageReceived(const ZigbeeInterfaceMessage &mes
if (message.messageType() == Zigbee::MessageTypeStatus) { if (message.messageType() == Zigbee::MessageTypeStatus) {
// We have a status message for the current reply // We have a status message for the current reply
m_currentReply->setStatusMessage(message); m_currentReply->setStatusMessage(message);
qCDebug(dcZigbeeController()) << "Current request" << m_currentReply->request().description() << "status message received";
// TODO: check if success, if not, finish reply // TODO: check if success, if not, finish reply
} else if (m_currentReply->request().expectsAdditionalMessage() &&
} else if (message.messageType() == m_currentReply->request().expectedAdditionalMessageType()) { message.messageType() == m_currentReply->request().expectedAdditionalMessageType()) {
m_currentReply->setAdditionalMessage(message); m_currentReply->setAdditionalMessage(message);
qCDebug(dcZigbeeController()) << "Current request" << m_currentReply->request().description() << "additional message received";
} else {
// Not a reply related message
qCDebug(dcZigbeeController()) << "Current request" << m_currentReply->request().description() << "but not related message received";
emit messageReceived(message);
return;
} }
// Check if request is complete // Check if request is complete
if (m_currentReply->isComplete()) { if (m_currentReply->isComplete()) {
qCDebug(dcZigbeeController()) << "Current request" << m_currentReply->request().description() << "is complete!";
m_currentReply->setFinished(); m_currentReply->setFinished();
// Note: the request class has to take care about the reply object // Note: the request class has to take care about the reply object
m_currentReply = nullptr; m_currentReply = nullptr;
@ -347,10 +355,11 @@ void ZigbeeBridgeController::onMessageReceived(const ZigbeeInterfaceMessage &mes
return; return;
} }
} else {
// Not a reply message
emit messageReceived(message);
} }
// Not a reply message
emit messageReceived(message);
} }
void ZigbeeBridgeController::onReplyTimeout() void ZigbeeBridgeController::onReplyTimeout()

View File

@ -129,7 +129,7 @@ ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const
return nullptr; return nullptr;
} }
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(ZigbeeAddress address) const ZigbeeNode *ZigbeeNetwork::getZigbeeNode(const ZigbeeAddress &address) const
{ {
foreach (ZigbeeNode *node, m_nodes) { foreach (ZigbeeNode *node, m_nodes) {
if (node->extendedAddress() == address) { if (node->extendedAddress() == address) {
@ -140,6 +140,16 @@ ZigbeeNode *ZigbeeNetwork::getZigbeeNode(ZigbeeAddress address) const
return nullptr; return nullptr;
} }
bool ZigbeeNetwork::hasNode(quint16 shortAddress) const
{
return getZigbeeNode(shortAddress) != nullptr;
}
bool ZigbeeNetwork::hasNode(const ZigbeeAddress &address) const
{
return getZigbeeNode(address) != nullptr;
}
void ZigbeeNetwork::saveNetwork() void ZigbeeNetwork::saveNetwork()
{ {
qCDebug(dcZigbeeNetwork()) << "Save current network configuration to" << m_settingsFileName; qCDebug(dcZigbeeNetwork()) << "Save current network configuration to" << m_settingsFileName;
@ -149,6 +159,10 @@ void ZigbeeNetwork::saveNetwork()
settings.setValue("channel", channel()); settings.setValue("channel", channel());
settings.endGroup(); settings.endGroup();
settings.beginGroup("Nodes");
settings.remove("");
settings.endGroup();
settings.beginWriteArray("Nodes"); settings.beginWriteArray("Nodes");
for (int i = 0; i < nodes().count(); i++) { for (int i = 0; i < nodes().count(); i++) {
settings.setArrayIndex(i); settings.setArrayIndex(i);
@ -173,27 +187,38 @@ void ZigbeeNetwork::loadNetwork()
setChannel(settings.value("channel", 0).toUInt()); setChannel(settings.value("channel", 0).toUInt());
settings.endGroup(); settings.endGroup();
settings.beginReadArray("Nodes"); int nodesCount = settings.beginReadArray("Nodes");
for (int i = 0; i < nodes().count(); i++) { for (int i = 0; i < nodesCount; i++) {
settings.setArrayIndex(i); settings.setArrayIndex(i);
ZigbeeNode *node = new ZigbeeNode(this); ZigbeeNode *node = new ZigbeeNode(this);
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt())); node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
node->setExtendedAddress(ZigbeeAddress(settings.value("ieeeAddress").toString())); node->setExtendedAddress(ZigbeeAddress(settings.value("ieeeAddress").toString()));
// TODO: load the rest of the node // TODO: load the rest of the node
addNodeInternally(node);
} }
settings.endArray(); settings.endArray();
qCDebug(dcZigbeeNetwork()) << "PAN Id:" << m_extendedPanId << ZigbeeUtils::convertUint64ToHexString(m_extendedPanId); qCDebug(dcZigbeeNetwork()) << "Extended PAN Id:" << m_extendedPanId << ZigbeeUtils::convertUint64ToHexString(m_extendedPanId);
qCDebug(dcZigbeeNetwork()) << "Channel" << m_channel; qCDebug(dcZigbeeNetwork()) << "Channel" << m_channel;
qCDebug(dcZigbeeNetwork()) << QStringLiteral("Nodes: (%1)").arg(m_nodes.count());
qCDebug(dcZigbeeNetwork()) << "Nodes:";
foreach (ZigbeeNode *node, nodes()) { foreach (ZigbeeNode *node, nodes()) {
qCDebug(dcZigbeeNetwork()) << " - " << node; qCDebug(dcZigbeeNetwork()) << " - " << node;
} }
} }
void ZigbeeNetwork::addNode(ZigbeeNode *node) void ZigbeeNetwork::addNode(ZigbeeNode *node)
{
if (hasNode(node->extendedAddress())) {
qCWarning(dcZigbeeNetwork()) << "The node" << node << "has already been added.";
return;
}
m_nodes.append(node);
emit nodeAdded(node);
saveNetwork();
}
void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
{ {
if (m_nodes.contains(node)) { if (m_nodes.contains(node)) {
qCWarning(dcZigbeeNetwork()) << "The node" << node << "has already been added."; qCWarning(dcZigbeeNetwork()) << "The node" << node << "has already been added.";
@ -202,7 +227,6 @@ void ZigbeeNetwork::addNode(ZigbeeNode *node)
m_nodes.append(node); m_nodes.append(node);
emit nodeAdded(node); emit nodeAdded(node);
saveNetwork();
} }
void ZigbeeNetwork::removeNode(ZigbeeNode *node) void ZigbeeNetwork::removeNode(ZigbeeNode *node)
@ -217,6 +241,38 @@ void ZigbeeNetwork::removeNode(ZigbeeNode *node)
saveNetwork(); saveNetwork();
} }
void ZigbeeNetwork::removeNodeInternally(ZigbeeNode *node)
{
if (!m_nodes.contains(node)) {
qCWarning(dcZigbeeNetwork()) << "Try to remove node" << node << "but not in the node list.";
return;
}
m_nodes.removeAll(node);
emit nodeRemoved(node);
node->deleteLater();
}
void ZigbeeNetwork::clearSettings()
{
qCDebug(dcZigbeeNetwork()) << "Clear network settings";
// Reset network configurations
m_extendedPanId = 0;
m_channel = 0;
m_securityConfiguration.clear();
m_nodeType = ZigbeeNode::NodeTypeCoordinator;
qCDebug(dcZigbeeNetwork()) << "Remove zigbee nodes from network";
foreach (ZigbeeNode *node, m_nodes) {
removeNodeInternally(node);
}
qCDebug(dcZigbeeNetwork()) << "Clear network settings" << m_settingsFileName;
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
settings.clear();
}
void ZigbeeNetwork::setState(ZigbeeNetwork::State state) void ZigbeeNetwork::setState(ZigbeeNetwork::State state)
{ {
if (m_state == state) if (m_state == state)
@ -239,3 +295,4 @@ void ZigbeeNetwork::setError(ZigbeeNetwork::Error error)
m_error = error; m_error = error;
emit errorOccured(m_error); emit errorOccured(m_error);
} }

View File

@ -62,8 +62,13 @@ public:
QList<ZigbeeNode *> nodes() const; QList<ZigbeeNode *> nodes() const;
ZigbeeNode *coordinatorNode() const; ZigbeeNode *coordinatorNode() const;
ZigbeeNode *getZigbeeNode(quint16 shortAddress) const; ZigbeeNode *getZigbeeNode(quint16 shortAddress) const;
ZigbeeNode *getZigbeeNode(ZigbeeAddress address) const; ZigbeeNode *getZigbeeNode(const ZigbeeAddress &address) const;
bool hasNode(quint16 shortAddress) const;
bool hasNode(const ZigbeeAddress &address) const;
private: private:
ControllerType m_controllerType = ControlerTypeNxp; ControllerType m_controllerType = ControlerTypeNxp;
@ -88,7 +93,11 @@ private:
protected: protected:
void addNode(ZigbeeNode *node); void addNode(ZigbeeNode *node);
void addNodeInternally(ZigbeeNode *node);
void removeNode(ZigbeeNode *node); void removeNode(ZigbeeNode *node);
void removeNodeInternally(ZigbeeNode *node);
void clearSettings();
void setState(State state); void setState(State state);
void setError(Error error); void setError(Error error);
@ -112,6 +121,7 @@ signals:
public slots: public slots:
virtual void startNetwork() = 0; virtual void startNetwork() = 0;
virtual void stopNetwork() = 0; virtual void stopNetwork() = 0;
virtual void factoryResetNetwork() = 0;
}; };

View File

@ -9,21 +9,17 @@
ZigbeeNetworkManager::ZigbeeNetworkManager(QObject *parent) : ZigbeeNetworkManager::ZigbeeNetworkManager(QObject *parent) :
ZigbeeNetwork(ZigbeeNetwork::ControlerTypeNxp, parent) ZigbeeNetwork(ZigbeeNetwork::ControlerTypeNxp, parent)
{ {
// // Create channel mask
// // Note: normal number passed, that specific channel will be used || Bitfield: all channels would be 0x07FFF800
// quint32 channelMask = 0;
// if (channel == 0) {
// qCDebug(dcZigbeeNetwork()) << "Using quitest channel for the zigbee network.";
// } else {
// channelMask |= 1 << (channel);
// qCDebug(dcZigbeeNetwork()) << "Using channel" << channel << "for the zigbee network.";
// }
} }
QString ZigbeeNetworkManager::controllerVersion() const QString ZigbeeNetworkManager::controllerFirmwareVersion() const
{ {
return m_controllerVersion; return m_controllerFirmwareVersion;
}
ZigbeeBridgeController *ZigbeeNetworkManager::controller() const
{
return m_controller;
} }
bool ZigbeeNetworkManager::networkRunning() const bool ZigbeeNetworkManager::networkRunning() const
@ -180,6 +176,7 @@ void ZigbeeNetworkManager::onCommandResetControllerFinished()
} }
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
//if (m_startingState == StartingStateReset && !m_networkRunning) setStartingState(StartingStateGetVersion);
} }
void ZigbeeNetworkManager::onCommandSoftResetControllerFinished() void ZigbeeNetworkManager::onCommandSoftResetControllerFinished()
@ -205,8 +202,13 @@ void ZigbeeNetworkManager::onCommandErasePersistentDataFinished()
return; return;
} }
m_factoryResetting = false;
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
if (m_startingState == StartingStateErase) setStartingState(StartingStateReset); if (m_startingState == StartingStateErase) {
setStartingState(StartingStateReset);
// setState(StateStarting);
}
} }
void ZigbeeNetworkManager::onCommandGetVersionFinished() void ZigbeeNetworkManager::onCommandGetVersionFinished()
@ -230,8 +232,8 @@ void ZigbeeNetworkManager::onCommandGetVersionFinished()
quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2)); quint16 majorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(0, 2));
quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2)); quint16 minorVersion = ZigbeeUtils::convertByteArrayToUint16(reply->additionalMessage().data().mid(2, 2));
m_controllerVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion); m_controllerFirmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion);
qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerVersion; qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion;
if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId); if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId);
} }
@ -477,6 +479,9 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me
qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress); qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(extendedAddress);
qCDebug(dcZigbeeNetwork()) << " Channel:" << channel; qCDebug(dcZigbeeNetwork()) << " Channel:" << channel;
qCDebug(dcZigbeeNetwork()) << " Extended PAN ID:" << extendedPanId();
qCDebug(dcZigbeeNetwork()) << " Permit joining" << permitJoining();
m_networkRunning = true; m_networkRunning = true;
@ -928,7 +933,6 @@ void ZigbeeNetworkManager::processFactoryNewRestart(const ZigbeeInterfaceMessage
break; break;
} }
qCDebug(dcZigbeeNetwork()) << "Restart finished. Current controller state:" << controllerStatusString; qCDebug(dcZigbeeNetwork()) << "Restart finished. Current controller state:" << controllerStatusString;
if (m_startingState == StartingStateReset) setStartingState(StartingStateGetVersion); if (m_startingState == StartingStateReset) setStartingState(StartingStateGetVersion);
} }
@ -1002,24 +1006,35 @@ void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &m
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(0, 2)); quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(0, 2));
quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(message.data().mid(2, 8)); quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(message.data().mid(2, 8));
quint8 macCapability = static_cast<quint8>(message.data().at(10)); quint8 macCapabilitiesFlag = static_cast<quint8>(message.data().at(10));
qCDebug(dcZigbeeNetwork()) << "Device announced:"; qCDebug(dcZigbeeNetwork()) << "Device announced:";
qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress); qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress); qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress);
qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapability); qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag);
ZigbeeNode *node = new ZigbeeNode(this); ZigbeeNode *node = new ZigbeeNode(this);
node->setShortAddress(shortAddress); node->setShortAddress(shortAddress);
node->setExtendedAddress(ZigbeeAddress(ieeeAddress)); node->setExtendedAddress(ZigbeeAddress(ieeeAddress));
node->setMacCapabilitiesFlag(macCapabilitiesFlag);
qCDebug(dcZigbeeNetwork()) << " Node:" << node;
// FIXME: check if node already added, and if we have to update it // FIXME: check if node already added, and if we have to update it
// Start node initialization process
addNode(node); addNode(node);
//node->init(); ZigbeeInterfaceReply *reply = nullptr;
reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandAuthenticateDeviceFinished);
//saveNetwork(); reply = m_controller->commandNodeDescriptorRequest(node->shortAddress());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished);
reply = m_controller->commandSimpleDescriptorRequest(node->shortAddress(), endPoint());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished);
reply = m_controller->commandPowerDescriptorRequest(node->shortAddress());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished);
} }
void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &message) void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &message)
@ -1029,11 +1044,10 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
quint8 endPoint = static_cast<quint8>(message.data().at(3)); quint8 endPoint = static_cast<quint8>(message.data().at(3));
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(4, 2)); quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(4, 2));
quint16 attributeId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(6, 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(8));
quint8 attributDataType = static_cast<quint8>(message.data().at(9));
quint16 attributeSize = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(10, 2)); quint16 attributeSize = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(9, 2));
QByteArray data = message.data().mid(12); QByteArray data = message.data().mid(11);
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(attributDataType); Zigbee::DataType dataType = static_cast<Zigbee::DataType>(attributDataType);
qCDebug(dcZigbeeNetwork()) << "Attribute report:"; qCDebug(dcZigbeeNetwork()) << "Attribute report:";
@ -1042,7 +1056,6 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
qCDebug(dcZigbeeNetwork()) << " End point:" << ZigbeeUtils::convertByteToHexString(endPoint); qCDebug(dcZigbeeNetwork()) << " End point:" << ZigbeeUtils::convertByteToHexString(endPoint);
qCDebug(dcZigbeeNetwork()) << " Cluster:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId)); qCDebug(dcZigbeeNetwork()) << " Cluster:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
qCDebug(dcZigbeeNetwork()) << " Attribut id:" << ZigbeeUtils::convertUint16ToHexString(attributeId); qCDebug(dcZigbeeNetwork()) << " Attribut id:" << ZigbeeUtils::convertUint16ToHexString(attributeId);
qCDebug(dcZigbeeNetwork()) << " Attribut status:" << ZigbeeUtils::convertByteToHexString(attributStatus);
qCDebug(dcZigbeeNetwork()) << " Attribut data type:" << dataType; qCDebug(dcZigbeeNetwork()) << " Attribut data type:" << dataType;
qCDebug(dcZigbeeNetwork()) << " Attribut size:" << attributeSize; qCDebug(dcZigbeeNetwork()) << " Attribut size:" << attributeSize;
qCDebug(dcZigbeeNetwork()) << " Data:" << ZigbeeUtils::convertByteArrayToHexString(data); qCDebug(dcZigbeeNetwork()) << " Data:" << ZigbeeUtils::convertByteArrayToHexString(data);
@ -1052,7 +1065,7 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
qCDebug(dcZigbeeNetwork()) << " Data(converted)" << QString::fromUtf8(data); qCDebug(dcZigbeeNetwork()) << " Data(converted)" << QString::fromUtf8(data);
break; break;
case Zigbee::Bool: case Zigbee::Bool:
qCDebug(dcZigbeeNetwork()) << " Data(converted)" << QVariant(data).toBool(); qCDebug(dcZigbeeNetwork()) << " Data(converted)" << static_cast<bool>(data.at(0));
break; break;
default: default:
break; break;
@ -1064,10 +1077,24 @@ void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &
void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &message) void ZigbeeNetworkManager::processLeaveIndication(const ZigbeeInterfaceMessage &message)
{ {
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(0, 2)); QByteArray data = message.data();
quint8 rejoining = static_cast<quint8>(message.data().at(2)); quint64 extendedAddress = 0;
bool rejoining = 0;
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> extendedAddress;
stream >> rejoining;
qCDebug(dcZigbeeNetwork()) << "Node leaving:" << ZigbeeUtils::convertUint16ToHexString(shortAddress) << rejoining; ZigbeeAddress address(extendedAddress);
// ZigbeeAddress extendedAddress = ZigbeeAddress(ZigbeeUtils::convertByteArrayToUint64(message.data().mid(0, 8)));
// quint8 rejoining = static_cast<quint8>(message.data().at(9));
qCDebug(dcZigbeeNetwork()) << "Node leaving indication:" << address.toString() << "rejoining:" << rejoining;
ZigbeeNode *node = getZigbeeNode(address);
if (node) {
removeNode(node);
}
// TODO: remove node // TODO: remove node
} }
@ -1094,20 +1121,26 @@ void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessag
} }
if (m_startingState == StartingStateReset) { if (m_startingState == StartingStateReset) {
qCDebug(dcZigbeeNetwork()) << "Reset finished.";
if (m_networkRunning) { if (m_networkRunning) {
qCDebug(dcZigbeeNetwork()) << "Reset finished. Network already running. No need to set it up";
setStartingState(StartingStateGetPermitJoinStatus); setStartingState(StartingStateGetPermitJoinStatus);
} else {
qCDebug(dcZigbeeNetwork()) << "Reset finished. Set up network";
setStartingState(StartingStateGetVersion);
} }
} }
} }
void ZigbeeNetworkManager::startNetwork() void ZigbeeNetworkManager::startNetwork()
{ {
qCDebug(dcZigbeeNetwork()) << "Start network...";
if (m_controller) { if (m_controller) {
qCDebug(dcZigbeeNetwork()) << "Clean up old controller...";
delete m_controller; delete m_controller;
m_controller = nullptr; m_controller = nullptr;
} }
qCDebug(dcZigbeeNetwork()) << "Create new controller...";
m_controller = new ZigbeeBridgeController(this); m_controller = new ZigbeeBridgeController(this);
connect(m_controller, &ZigbeeBridgeController::messageReceived, this, &ZigbeeNetworkManager::onMessageReceived); connect(m_controller, &ZigbeeBridgeController::messageReceived, this, &ZigbeeNetworkManager::onMessageReceived);
connect(m_controller, &ZigbeeBridgeController::availableChanged, this, &ZigbeeNetworkManager::onControllerAvailableChanged); connect(m_controller, &ZigbeeBridgeController::availableChanged, this, &ZigbeeNetworkManager::onControllerAvailableChanged);
@ -1118,14 +1151,23 @@ void ZigbeeNetworkManager::startNetwork()
setError(ErrorHardwareUnavailable); setError(ErrorHardwareUnavailable);
} else { } else {
// Reset // Reset
setState(StateStarting);
setStartingState(StartingStateReset); setStartingState(StartingStateReset);
setState(StateStarting);
} }
} }
void ZigbeeNetworkManager::stopNetwork() void ZigbeeNetworkManager::stopNetwork()
{ {
qCDebug(dcZigbeeNetwork()) << "Stopping network...";
setState(StateStopping);
if (m_controller) {
delete m_controller;
m_controller = nullptr;
}
setStartingState(StartingStateNone);
setState(StateDisconnected);
setError(ErrorNoError);
} }
void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &message) void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &message)
@ -1162,7 +1204,7 @@ void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &messa
processRestartProvisioned(message); processRestartProvisioned(message);
break; break;
default: default:
qCDebug(dcZigbeeController()) << "Message received:" << message; qCWarning(dcZigbeeController()) << "Unhandled message received:" << message;
break; break;
} }
} }
@ -1171,6 +1213,11 @@ void ZigbeeNetworkManager::onControllerAvailableChanged(bool available)
{ {
qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available"); qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available");
if (m_factoryResetting && !available) {
setStartingState(StartingStateReset);
return;
}
if (!available) { if (!available) {
setError(ErrorHardwareUnavailable); setError(ErrorHardwareUnavailable);
setState(StateDisconnected); setState(StateDisconnected);
@ -1183,3 +1230,12 @@ void ZigbeeNetworkManager::onControllerAvailableChanged(bool available)
} }
void ZigbeeNetworkManager::factoryResetNetwork()
{
qCDebug(dcZigbeeNetwork()) << "Factory reset network and forgett all information. This cannot be undone.";
clearSettings();
setState(StateStarting);
setStartingState(StartingStateErase);
}

View File

@ -14,7 +14,10 @@ class ZigbeeNetworkManager : public ZigbeeNetwork
public: public:
explicit ZigbeeNetworkManager(QObject *parent = nullptr); explicit ZigbeeNetworkManager(QObject *parent = nullptr);
QString controllerVersion() const; QString controllerFirmwareVersion() const;
// Note: temporary public available for debugging
ZigbeeBridgeController *controller() const;
bool networkRunning() const; bool networkRunning() const;
@ -41,13 +44,16 @@ private:
}; };
ZigbeeBridgeController *m_controller = nullptr; ZigbeeBridgeController *m_controller = nullptr;
QString m_controllerVersion; QString m_controllerFirmwareVersion;
StartingState m_startingState = StartingStateNone; StartingState m_startingState = StartingStateNone;
void setStartingState(StartingState state); void setStartingState(StartingState state);
QList<ZigbeeNode *> m_uninitializedNodes;
bool m_permitJoining = false; bool m_permitJoining = false;
bool m_networkRunning = false; bool m_networkRunning = false;
bool m_factoryResetting = false;
signals: signals:
void permitJoiningChanged(bool permitJoining); void permitJoiningChanged(bool permitJoining);
@ -98,6 +104,7 @@ private slots:
public slots: public slots:
void startNetwork() override; void startNetwork() override;
void stopNetwork() override; void stopNetwork() override;
void factoryResetNetwork() override;
}; };

View File

@ -31,6 +31,11 @@ void ZigbeeSecurityConfiguration::setGlobalTrustCenterlinkKey(const QString &glo
m_globalTrustCenterLinkKey = globalTrustCenterLinkKey; m_globalTrustCenterLinkKey = globalTrustCenterLinkKey;
} }
void ZigbeeSecurityConfiguration::clear()
{
m_networkKey.clear();
}
bool ZigbeeSecurityConfiguration::operator==(const ZigbeeSecurityConfiguration &other) const bool ZigbeeSecurityConfiguration::operator==(const ZigbeeSecurityConfiguration &other) const
{ {
return m_networkKey == other.networkKey() && m_globalTrustCenterLinkKey == other.globalTrustCenterLinkKey(); return m_networkKey == other.networkKey() && m_globalTrustCenterLinkKey == other.globalTrustCenterLinkKey();

View File

@ -15,6 +15,8 @@ public:
QString globalTrustCenterLinkKey() const; QString globalTrustCenterLinkKey() const;
void setGlobalTrustCenterlinkKey(const QString & globalTrustCenterLinkKey); void setGlobalTrustCenterlinkKey(const QString & globalTrustCenterLinkKey);
void clear();
bool operator==(const ZigbeeSecurityConfiguration &other) const; bool operator==(const ZigbeeSecurityConfiguration &other) const;
bool operator!=(const ZigbeeSecurityConfiguration &other) const; bool operator!=(const ZigbeeSecurityConfiguration &other) const;