Restore basic node adding and start node initialization

This commit is contained in:
Simon Stürz 2020-02-28 17:28:49 +01:00
parent 7c7ba4f13a
commit 080e89cf94
13 changed files with 359 additions and 241 deletions

View File

@ -222,7 +222,7 @@ void ZigbeeInterface::onReadyRead()
void ZigbeeInterface::onError(const QSerialPort::SerialPortError &error) void ZigbeeInterface::onError(const QSerialPort::SerialPortError &error)
{ {
if (error != QSerialPort::NoError && m_serialPort->isOpen()) { if (error != QSerialPort::NoError && m_serialPort->isOpen()) {
qCCritical(dcZigbeeInterface()) << "Serial port error:" << error << m_serialPort->errorString(); qCWarning(dcZigbeeInterface()) << "Serial port error:" << error << m_serialPort->errorString();
m_reconnectTimer->start(); m_reconnectTimer->start();
m_serialPort->close(); m_serialPort->close();
setAvailable(false); setAvailable(false);

View File

@ -190,7 +190,7 @@ ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandGetPermitJoinStatus()
return sendRequest(request); return sendRequest(request);
} }
ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandRequestActiveEndpoints(quint16 shortAddress) ZigbeeInterfaceReply *ZigbeeBridgeControllerNxp::commandActiveEndpointsRequest(quint16 shortAddress)
{ {
QByteArray data; QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly); QDataStream stream(&data, QIODevice::WriteOnly);

View File

@ -59,7 +59,7 @@ public:
ZigbeeInterfaceReply *commandStartScan(); ZigbeeInterfaceReply *commandStartScan();
ZigbeeInterfaceReply *commandPermitJoin(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 180, bool tcSignificance = false); ZigbeeInterfaceReply *commandPermitJoin(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 180, bool tcSignificance = false);
ZigbeeInterfaceReply *commandGetPermitJoinStatus(); ZigbeeInterfaceReply *commandGetPermitJoinStatus();
ZigbeeInterfaceReply *commandRequestActiveEndpoints(quint16 shortAddress); ZigbeeInterfaceReply *commandActiveEndpointsRequest(quint16 shortAddress);
ZigbeeInterfaceReply *commandRequestLinkQuality(quint16 shortAddress); ZigbeeInterfaceReply *commandRequestLinkQuality(quint16 shortAddress);
ZigbeeInterfaceReply *commandEnableWhiteList(); ZigbeeInterfaceReply *commandEnableWhiteList();
ZigbeeInterfaceReply *commandInitiateTouchLink(); ZigbeeInterfaceReply *commandInitiateTouchLink();

View File

@ -2,6 +2,8 @@
#include "../loggingcategory.h" #include "../loggingcategory.h"
#include "../zigbeeutils.h" #include "../zigbeeutils.h"
#include "zigbeenodenxp.h"
#include <QDataStream> #include <QDataStream>
ZigbeeNetworkNxp::ZigbeeNetworkNxp(QObject *parent) : ZigbeeNetworkNxp::ZigbeeNetworkNxp(QObject *parent) :
@ -155,7 +157,18 @@ void ZigbeeNetworkNxp::setStartingState(ZigbeeNetworkNxp::StartingState state)
case StartingStateStartNetwork: { case StartingStateStartNetwork: {
qCDebug(dcZigbeeNetwork()) << "Starting state changed: Starting network"; qCDebug(dcZigbeeNetwork()) << "Starting state changed: Starting network";
ZigbeeInterfaceReply *reply = m_controller->commandStartNetwork(); ZigbeeInterfaceReply *reply = m_controller->commandStartNetwork();
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandStartNetworkFinished); connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){
reply->deleteLater();
if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeNetwork()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
return;
}
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
qCDebug(dcZigbeeController()) << reply->additionalMessage();
processNetworkFormed(reply->additionalMessage());
});
break; break;
} }
case StartingStateReadeNodeDescriptor: { case StartingStateReadeNodeDescriptor: {
@ -221,6 +234,36 @@ void ZigbeeNetworkNxp::readPermitJoinStatus()
}); });
} }
ZigbeeNode *ZigbeeNetworkNxp::createNode(QObject *parent)
{
return new ZigbeeNodeNxp(m_controller, parent);
}
void ZigbeeNetworkNxp::setPermitJoiningInternal(bool permitJoining)
{
// Note: 0xfffc = all routers
qCDebug(dcZigbeeNetwork()) << "Send request to" << (permitJoining ? "enable" : "disable") << "permit joining network.";
ZigbeeInterfaceReply *reply = m_controller->commandPermitJoin(0xfffc, (permitJoining ? 255 : 0));
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";
qCDebug(dcZigbeeController()) << reply->additionalMessage();
if (m_permitJoining == permitJoining)
return;
qCDebug(dcZigbeeNetwork()) << "Permit joining changed to" << permitJoining;
m_permitJoining = permitJoining;
emit permitJoiningChanged(m_permitJoining);
});
}
void ZigbeeNetworkNxp::onCommandInitiateTouchLinkFinished() void ZigbeeNetworkNxp::onCommandInitiateTouchLinkFinished()
{ {
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender()); ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
@ -398,6 +441,8 @@ void ZigbeeNetworkNxp::processNodeClusterList(const ZigbeeInterfaceMessage &mess
profileId <<= 8; profileId <<= 8;
profileId |= static_cast<quint8>(message.data().at(2)); profileId |= static_cast<quint8>(message.data().at(2));
// FIXME:
return;
qCDebug(dcZigbeeController()) << "Node cluster list received:"; qCDebug(dcZigbeeController()) << "Node cluster list received:";
qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint;
qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId)); qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
@ -418,10 +463,14 @@ void ZigbeeNetworkNxp::processNodeAttributeList(const ZigbeeInterfaceMessage &me
{ {
quint8 sourceEndpoint = static_cast<quint8>(message.data().at(0)); quint8 sourceEndpoint = static_cast<quint8>(message.data().at(0));
quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2)); quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2));
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2)); quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2));
// FIXME:
return;
qCDebug(dcZigbeeController()) << "Node attribute list received:"; qCDebug(dcZigbeeController()) << "Node attribute list received:";
qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint;
qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId)); qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId)); qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
@ -445,6 +494,8 @@ void ZigbeeNetworkNxp::processNodeCommandIdList(const ZigbeeInterfaceMessage &me
quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2)); quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2));
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2)); quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2));
// FIXME:
return;
qCDebug(dcZigbeeController()) << "Node command list received:"; qCDebug(dcZigbeeController()) << "Node command list received:";
qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint; qCDebug(dcZigbeeController()) << " Souce endpoint:" << sourceEndpoint;
qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId)); qCDebug(dcZigbeeController()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
@ -469,39 +520,37 @@ void ZigbeeNetworkNxp::processDeviceAnnounce(const ZigbeeInterfaceMessage &messa
QDataStream stream(&data, QIODevice::ReadOnly); QDataStream stream(&data, QIODevice::ReadOnly);
stream >> shortAddress >> ieeeAddress >> macCapabilitiesFlag; stream >> shortAddress >> ieeeAddress >> macCapabilitiesFlag;
ZigbeeAddress nodeIeeeAddress(ieeeAddress);
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:" << nodeIeeeAddress;
qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag); qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag);
// Check if we already have a node with this // Check if we already have a node with this
if (hasNode(nodeIeeeAddress)) {
qCDebug(dcZigbeeNetwork()) << "Node already registered in the network.";
ZigbeeNode *node = getZigbeeNode(nodeIeeeAddress);
if (node->shortAddress() != shortAddress) {
qCWarning(dcZigbeeNetwork()) << "The node changed the NWK address from" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << "to" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
// FIMXE: check if we should reinitialize the node
}
return;
}
// ZigbeeNode *node = createNode(); ZigbeeNodeNxp *node = new ZigbeeNodeNxp(m_controller, this);
// node->setShortAddress(shortAddress); node->setShortAddress(shortAddress);
// node->setExtendedAddress(ZigbeeAddress(ieeeAddress)); node->setExtendedAddress(ZigbeeAddress(ieeeAddress));
// node->setMacCapabilitiesFlag(macCapabilitiesFlag); node->setMacCapabilitiesFlag(macCapabilitiesFlag);
qCDebug(dcZigbeeNetwork()) << "Node:" << node;
// qCDebug(dcZigbeeNetwork()) << " Node:" << node; node->startInitialization();
addUnitializedNode(node);
// // FIXME: check if node already added, and if we have to update it
// addUnitializedNode(node);
// node->setState(StateInitializing);
// ZigbeeInterfaceReply *reply = nullptr; // ZigbeeInterfaceReply *reply = nullptr;
// reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey()); // reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandAuthenticateDeviceFinished); // connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandAuthenticateDeviceFinished);
// reply = m_controller->commandNodeDescriptorRequest(node->shortAddress());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandNodeDescriptorRequestFinished);
// reply = m_controller->commandSimpleDescriptorRequest(node->shortAddress(), endPoint());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandSimpleDescriptorRequestFinished);
// reply = m_controller->commandPowerDescriptorRequest(node->shortAddress());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkNxp::onCommandPowerDescriptorRequestFinished);
} }
void ZigbeeNetworkNxp::processAttributeReport(const ZigbeeInterfaceMessage &message) void ZigbeeNetworkNxp::processAttributeReport(const ZigbeeInterfaceMessage &message)
@ -691,26 +740,29 @@ void ZigbeeNetworkNxp::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) { if (!available) {
setStartingState(StartingStateReset); foreach (ZigbeeNode *node, nodes()) {
return; qobject_cast<ZigbeeNodeNxp *>(node)->setConnected(false);
} }
if (!available) {
// FIXME
// foreach (ZigbeeNode *node, nodes()) {
// node->setConnected(false);
// }
setError(ErrorHardwareUnavailable); setError(ErrorHardwareUnavailable);
setPermitJoining(false); m_permitJoining = false;
setState(StateOffline); emit permitJoiningChanged(m_permitJoining);
setStartingState(StartingStateNone); setStartingState(StartingStateNone);
setState(StateOffline);
} else { } else {
m_error = ErrorNoError; m_error = ErrorNoError;
setState(StateStarting); m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
// Note: if we are factory resetting, erase also the data on the controller before resetting
if (m_factoryResetting) {
setStartingState(StartingStateErase);
} else {
setStartingState(StartingStateReset); setStartingState(StartingStateReset);
} }
setState(StateStarting);
}
} }
@ -765,23 +817,6 @@ void ZigbeeNetworkNxp::onCommandSoftResetControllerFinished()
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
} }
void ZigbeeNetworkNxp::onCommandStartNetworkFinished()
{
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
reply->deleteLater();
if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeNetwork()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
return;
}
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
qCDebug(dcZigbeeController()) << reply->additionalMessage();
processNetworkFormed(reply->additionalMessage());
// FIXME: start creating coordinator node
//if (m_startingState == StartingStateStartNetwork) setStartingState(StartingStateGetPermitJoinStatus);
}
void ZigbeeNetworkNxp::onCommandStartScanFinished() void ZigbeeNetworkNxp::onCommandStartScanFinished()
{ {
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender()); ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
@ -837,7 +872,8 @@ void ZigbeeNetworkNxp::processNetworkFormed(const ZigbeeInterfaceMessage &messag
if (networkStatus != Zigbee::ZigbeeNwkLayerStatusJointNetwork && networkStatus != Zigbee::ZigbeeNwkLayerStatusFormedNetwork) { if (networkStatus != Zigbee::ZigbeeNwkLayerStatusJointNetwork && networkStatus != Zigbee::ZigbeeNwkLayerStatusFormedNetwork) {
qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatusString; qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatusString;
setPermitJoining(false); m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
setStartingState(StartingStateNone); setStartingState(StartingStateNone);
setState(StateOffline); setState(StateOffline);
setError(ErrorZigbeeError); setError(ErrorZigbeeError);
@ -856,20 +892,28 @@ void ZigbeeNetworkNxp::processNetworkFormed(const ZigbeeInterfaceMessage &messag
qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining(); qCDebug(dcZigbeeNetwork()) << " Permit joining:" << permitJoining();
saveNetwork(); saveNetwork();
m_networkRunning = true; m_networkRunning = true;
if (nodes().isEmpty()) {
// Create coordinator node
ZigbeeNodeNxp *node = new ZigbeeNodeNxp(m_controller, m_controller);
node->setShortAddress(shortAddress);
node->setExtendedAddress(ZigbeeAddress(extendedAddress));
node->startInitialization();
connect(node, &ZigbeeNode::stateChanged, this, [this, node](){
if (node->state() == ZigbeeNode::StateInitialized) {
m_coordinatorNode = qobject_cast<ZigbeeNode *>(node);
addNode(m_coordinatorNode);
qCDebug(dcZigbeeNetwork()) << "Coordinator node initialized. The network is now set up.";
setState(StateRunning); setState(StateRunning);
}
// FIXME: create coordinator node });
} else {
// // Set the node information // Primary initialization was already done.
// setShortAddress(shortAddress); setState(StateRunning);
// setExtendedAddress(ZigbeeAddress(extendedAddress)); }
// setChannel(channel);
// if (!hasNode(this->shortAddress()))
// addUnitializedNode(this);
} }
void ZigbeeNetworkNxp::startNetwork() void ZigbeeNetworkNxp::startNetwork()
@ -890,12 +934,10 @@ void ZigbeeNetworkNxp::startNetwork()
if (state() == StateUninitialized) if (state() == StateUninitialized)
loadNetwork(); loadNetwork();
if (extendedPanId() == 0 && channel() == 0) { // Do a factory reset if there are no network configuration and create a new one from scratch
m_factoryResetting = true; m_factoryResetting = !networkConfigurationAvailable();
}
setState(StateOffline); setState(StateOffline);
// Check if we have to create a pan ID and select the channel // Check if we have to create a pan ID and select the channel
if (extendedPanId() == 0) { if (extendedPanId() == 0) {
setExtendedPanId(ZigbeeUtils::generateRandomPanId()); setExtendedPanId(ZigbeeUtils::generateRandomPanId());
@ -904,25 +946,18 @@ void ZigbeeNetworkNxp::startNetwork()
// TODO: get desired channel, by default use all // TODO: get desired channel, by default use all
if (!m_controller->enable(serialPortName(), serialBaudrate())) { if (!m_controller->enable(serialPortName(), serialBaudrate())) {
setPermitJoining(false); m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
setState(StateOffline); setState(StateOffline);
setStartingState(StartingStateNone); setStartingState(StartingStateNone);
setError(ErrorHardwareUnavailable); setError(ErrorHardwareUnavailable);
return; return;
} }
setPermitJoining(false); m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
// Note: if we are factory resetting, erase also the data on the controller // Note: wait for the controller available signal and start the initialization there
if (m_factoryResetting) {
setStartingState(StartingStateReset);
} else {
setStartingState(StartingStateErase);
}
setState(StateStarting);
} }
void ZigbeeNetworkNxp::stopNetwork() void ZigbeeNetworkNxp::stopNetwork()
@ -935,7 +970,8 @@ void ZigbeeNetworkNxp::stopNetwork()
} }
setStartingState(StartingStateNone); setStartingState(StartingStateNone);
setPermitJoining(false); m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
setState(StateOffline); setState(StateOffline);
setError(ErrorNoError); setError(ErrorNoError);
} }

View File

@ -35,6 +35,10 @@ private:
void readControllerVersion(); void readControllerVersion();
void readPermitJoinStatus(); void readPermitJoinStatus();
protected:
ZigbeeNode *createNode(QObject *parent) override;
void setPermitJoiningInternal(bool permitJoining) override;
private slots: private slots:
void onMessageReceived(const ZigbeeInterfaceMessage &message); void onMessageReceived(const ZigbeeInterfaceMessage &message);
void onControllerAvailableChanged(bool available); void onControllerAvailableChanged(bool available);
@ -42,7 +46,6 @@ private slots:
// Controller command finished slots // Controller command finished slots
void onCommandResetControllerFinished(); void onCommandResetControllerFinished();
void onCommandSoftResetControllerFinished(); void onCommandSoftResetControllerFinished();
void onCommandStartNetworkFinished();
void onCommandStartScanFinished(); void onCommandStartScanFinished();
//void onCommandEnableWhitelistFinished(); //void onCommandEnableWhitelistFinished();

View File

@ -1,6 +1,105 @@
#include "zigbeenodenxp.h" #include "zigbeenodenxp.h"
#include "loggingcategory.h"
#include "zigbeeutils.h"
ZigbeeNodeNxp::ZigbeeNodeNxp(QObject *parent) : QObject(parent) #include <QDataStream>
ZigbeeNodeNxp::ZigbeeNodeNxp(ZigbeeBridgeControllerNxp *controller, QObject *parent):
ZigbeeNode(parent),
m_controller(controller)
{ {
} }
void ZigbeeNodeNxp::setInitState(ZigbeeNodeNxp::InitState initState)
{
m_initState = initState;
switch (m_initState) {
case InitStateNone:
break;
case InitStateNodeDescriptor: {
qCDebug(dcZigbeeNode()) << "Request node descriptor for" << this;
ZigbeeInterfaceReply *reply = m_controller->commandNodeDescriptorRequest(shortAddress());
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();
}
setNodeDescriptorRawData(reply->additionalMessage().data());
setInitState(InitStatePowerDescriptor);
});
break;
}
case InitStatePowerDescriptor: {
qCDebug(dcZigbeeNode()) << "Request power descriptor for" << this;
ZigbeeInterfaceReply *reply = m_controller->commandPowerDescriptorRequest(shortAddress());
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();
}
QByteArray data = reply->additionalMessage().data();
quint8 sequenceNumber = 0;
quint8 status = 0;
quint16 powerDescriptorFlag = 0;
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> sequenceNumber >> status >> powerDescriptorFlag;
setPowerDescriptorFlag(powerDescriptorFlag);
setInitState(InitStateActiveEndpoints);
});
break;
}
case InitStateActiveEndpoints: {
qCDebug(dcZigbeeNode()) << "Request active endpoints for" << this;
ZigbeeInterfaceReply *reply = m_controller->commandActiveEndpointsRequest(shortAddress());
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();
} else {
QByteArray data = reply->additionalMessage().data();
quint8 sequenceNumber = 0;
quint8 status = 0;
quint16 shortAddress = 0;
quint8 endpointCount = 0;
QList<quint8> endpointIds;
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> sequenceNumber >> status >> shortAddress >> endpointCount;
qCDebug(dcZigbeeNode()) << "Active endpoint list received:";
qCDebug(dcZigbeeNode()) << "Sequence number" << sequenceNumber;
qCDebug(dcZigbeeNode()) << "Status:" << status;
qCDebug(dcZigbeeNode()) << "Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNode()) << "Endpoint count:" << endpointCount;
for (int i = 0; i < endpointCount; i++) {
quint8 endpointId = 0;
stream >> endpointId;
endpointIds.append(endpointId);
qCDebug(dcZigbeeNode()) << " - " << ZigbeeUtils::convertByteToHexString(endpointId);
}
}
setState(StateInitialized);
});
break;
}
case InitStateSimpleDescriptors:
break;
}
}
void ZigbeeNodeNxp::startInitialization()
{
qCDebug(dcZigbeeNode()) << "Start initialization" << this;
setState(StateInitializing);
setInitState(InitStateNodeDescriptor);
}

View File

@ -4,11 +4,34 @@
#include <QObject> #include <QObject>
#include "../zigbeenode.h" #include "../zigbeenode.h"
class ZigbeeNodeNxp : public QObject #include "zigbeebridgecontrollernxp.h"
class ZigbeeNodeNxp : public ZigbeeNode
{ {
Q_OBJECT Q_OBJECT
friend class ZigbeeNetworkNxp;
public: public:
explicit ZigbeeNodeNxp(QObject *parent = nullptr); enum InitState {
InitStateNone,
InitStateNodeDescriptor,
InitStatePowerDescriptor,
InitStateActiveEndpoints,
InitStateSimpleDescriptors
};
Q_ENUM(InitState)
explicit ZigbeeNodeNxp(ZigbeeBridgeControllerNxp *controller, QObject *parent = nullptr);
private:
ZigbeeBridgeControllerNxp *m_controller = nullptr;
InitState m_initState = InitStateNone;
void setInitState(InitState initState);
protected:
void startInitialization() override;
signals: signals:

View File

@ -136,12 +136,7 @@ bool ZigbeeNetwork::permitJoining() const
void ZigbeeNetwork::setPermitJoining(bool permitJoining) void ZigbeeNetwork::setPermitJoining(bool permitJoining)
{ {
if (m_permitJoining == permitJoining) setPermitJoiningInternal(permitJoining);
return;
qCDebug(dcZigbeeNetwork()) << "Permit joining changed to" << permitJoining;
m_permitJoining = permitJoining;
emit permitJoiningChanged(m_permitJoining);
} }
QList<ZigbeeNode *> ZigbeeNetwork::nodes() const QList<ZigbeeNode *> ZigbeeNetwork::nodes() const
@ -151,7 +146,7 @@ QList<ZigbeeNode *> ZigbeeNetwork::nodes() const
ZigbeeNode *ZigbeeNetwork::coordinatorNode() const ZigbeeNode *ZigbeeNetwork::coordinatorNode() const
{ {
return getZigbeeNode(0); return m_coordinatorNode;
} }
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress) const
@ -205,7 +200,8 @@ void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
return; return;
} }
node->setConnected(state() == StateRunning); // FIXME: check when and how the note will be reachable
//node->setConnected(state() == StateRunning);
m_nodes.append(node); m_nodes.append(node);
emit nodeAdded(node); emit nodeAdded(node);
@ -253,78 +249,76 @@ void ZigbeeNetwork::loadNetwork()
foreach (const QString ieeeAddressString, settings.childGroups()) { foreach (const QString ieeeAddressString, settings.childGroups()) {
settings.beginGroup(ieeeAddressString); settings.beginGroup(ieeeAddressString);
ZigbeeNode *node = new ZigbeeNode(this); ZigbeeNode *node = createNode(this);
node->setExtendedAddress(ZigbeeAddress(ieeeAddressString)); node->setExtendedAddress(ZigbeeAddress(ieeeAddressString));
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt())); node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
node->setMacCapabilitiesFlag(static_cast<quint8>(settings.value("macCapabilitiesFlag", 0).toUInt())); node->setMacCapabilitiesFlag(static_cast<quint8>(settings.value("macCapabilitiesFlag", 0).toUInt()));
node->setNodeDescriptorRawData(settings.value("nodeDescriptorRawData", QByteArray()).toByteArray()); node->setNodeDescriptorRawData(settings.value("nodeDescriptorRawData", QByteArray()).toByteArray());
node->setPowerDescriptorFlag(static_cast<quint16>(settings.value("powerDescriptorFlag", 0).toUInt())); node->setPowerDescriptorFlag(static_cast<quint16>(settings.value("powerDescriptorFlag", 0).toUInt()));
// TODO: load endpoints // TODO: load endpoints
// settings.beginGroup("inputCluster"); // settings.beginGroup("inputCluster");
// foreach (const QString &clusterIdString, settings.childGroups()) { // foreach (const QString &clusterIdString, settings.childGroups()) {
// settings.beginGroup(clusterIdString); // settings.beginGroup(clusterIdString);
// Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt()); // Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt());
// foreach (const QString &attributeIdString, settings.childGroups()) { // foreach (const QString &attributeIdString, settings.childGroups()) {
// settings.beginGroup(attributeIdString); // settings.beginGroup(attributeIdString);
// quint16 id = static_cast<quint16>(attributeIdString.toInt()); // quint16 id = static_cast<quint16>(attributeIdString.toInt());
// Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt()); // Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
// QByteArray data = settings.value("data").toByteArray(); // QByteArray data = settings.value("data").toByteArray();
// node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data)); // node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
// settings.endGroup(); // attributeId // settings.endGroup(); // attributeId
// } // }
// settings.endGroup(); // clusterId // settings.endGroup(); // clusterId
// } // }
// settings.endGroup(); // inputCluster // settings.endGroup(); // inputCluster
// // Output cluster // // Output cluster
// settings.beginGroup("outputCluster"); // settings.beginGroup("outputCluster");
// foreach (const QString &clusterIdString, settings.childGroups()) { // foreach (const QString &clusterIdString, settings.childGroups()) {
// settings.beginGroup(clusterIdString); // settings.beginGroup(clusterIdString);
// Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt()); // Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt());
// foreach (const QString &attributeIdString, settings.childGroups()) { // foreach (const QString &attributeIdString, settings.childGroups()) {
// settings.beginGroup(attributeIdString); // settings.beginGroup(attributeIdString);
// quint16 id = static_cast<quint16>(attributeIdString.toInt()); // quint16 id = static_cast<quint16>(attributeIdString.toInt());
// Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt()); // Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
// QByteArray data = settings.value("data").toByteArray(); // QByteArray data = settings.value("data").toByteArray();
// node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data)); // node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
// settings.endGroup(); // attributeId // settings.endGroup(); // attributeId
// } // }
// settings.endGroup(); // clusterId // settings.endGroup(); // clusterId
// } // }
// settings.endGroup(); // outputCluster // settings.endGroup(); // outputCluster
//FIXME
//node->setState(StateInitialized); node->setState(ZigbeeNode::StateInitialized);
addNodeInternally(node); addNodeInternally(node);
settings.endGroup(); // ieeeAddress settings.endGroup(); // ieeeAddress
} }
settings.endGroup(); // Nodes settings.endGroup(); // Nodes
qCDebug(dcZigbeeNetwork()) << "Extended 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()) << QStringLiteral("Nodes: (%1)").arg(m_nodes.count());
foreach (ZigbeeNode *node, nodes()) { // foreach (ZigbeeNode *node, nodes()) {
qCDebug(dcZigbeeNetwork()) << " - " << node; // qCDebug(dcZigbeeNetwork()) << " - " << node;
// qCDebug(dcZigbeeNetwork()) << "Output cluster:"; // qCDebug(dcZigbeeNetwork()) << "Output cluster:";
// foreach (ZigbeeCluster *cluster, node->outputClusters()) { // foreach (ZigbeeCluster *cluster, node->outputClusters()) {
// qCDebug(dcZigbeeNetwork()) << " " << cluster; // qCDebug(dcZigbeeNetwork()) << " " << cluster;
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { // foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// qCDebug(dcZigbeeNetwork()) << " " << attribute; // qCDebug(dcZigbeeNetwork()) << " " << attribute;
// } // }
// } // }
// qCDebug(dcZigbeeNetwork()) << "Input cluster:"; // qCDebug(dcZigbeeNetwork()) << "Input cluster:";
// foreach (ZigbeeCluster *cluster, node->inputClusters()) { // foreach (ZigbeeCluster *cluster, node->inputClusters()) {
// qCDebug(dcZigbeeNetwork()) << " " << cluster; // qCDebug(dcZigbeeNetwork()) << " " << cluster;
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { // foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// qCDebug(dcZigbeeNetwork()) << " " << attribute; // qCDebug(dcZigbeeNetwork()) << " " << attribute;
// } // }
// } // }
} // }
} }
void ZigbeeNetwork::clearSettings() void ZigbeeNetwork::clearSettings()
@ -368,34 +362,34 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node)
// TODO: save the rest of the node // TODO: save the rest of the node
// // Input clusters // // Input clusters
// settings.beginGroup("inputCluster"); // settings.beginGroup("inputCluster");
// foreach (ZigbeeCluster *cluster, node->inputClusters()) { // foreach (ZigbeeCluster *cluster, node->inputClusters()) {
// settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId()))); // settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId())));
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { // foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// settings.beginGroup(QString::number(static_cast<int>(attribute.id()))); // settings.beginGroup(QString::number(static_cast<int>(attribute.id())));
// settings.setValue("dataType", static_cast<int>(attribute.dataType())); // settings.setValue("dataType", static_cast<int>(attribute.dataType()));
// settings.setValue("data", attribute.data()); // settings.setValue("data", attribute.data());
// settings.endGroup(); // attributeId // settings.endGroup(); // attributeId
// } // }
// settings.endGroup(); // clusterId // settings.endGroup(); // clusterId
// } // }
// settings.endGroup(); // inputCluster // settings.endGroup(); // inputCluster
// // Output clusters // // Output clusters
// settings.beginGroup("outputCluster"); // settings.beginGroup("outputCluster");
// foreach (ZigbeeCluster *cluster, node->outputClusters()) { // foreach (ZigbeeCluster *cluster, node->outputClusters()) {
// settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId()))); // settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId())));
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) { // foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// settings.beginGroup(QString::number(static_cast<int>(attribute.id()))); // settings.beginGroup(QString::number(static_cast<int>(attribute.id())));
// settings.setValue("dataType", static_cast<int>(attribute.dataType())); // settings.setValue("dataType", static_cast<int>(attribute.dataType()));
// settings.setValue("data", attribute.data()); // settings.setValue("data", attribute.data());
// settings.endGroup(); // attributeId // settings.endGroup(); // attributeId
// } // }
// settings.endGroup(); // clusterId // settings.endGroup(); // clusterId
// } // }
// settings.endGroup(); // inputCluster // settings.endGroup(); // inputCluster
settings.endGroup(); // Node ieee address settings.endGroup(); // Node ieee address
@ -416,11 +410,6 @@ void ZigbeeNetwork::removeNodeFromSettings(ZigbeeNode *node)
settings.endGroup(); // Nodes settings.endGroup(); // Nodes
} }
ZigbeeNode *ZigbeeNetwork::createNode(QObject *parent)
{
return new ZigbeeNode(parent);
}
void ZigbeeNetwork::addNode(ZigbeeNode *node) void ZigbeeNetwork::addNode(ZigbeeNode *node)
{ {
qCDebug(dcZigbeeNetwork()) << "Add node" << node; qCDebug(dcZigbeeNetwork()) << "Add node" << node;
@ -467,6 +456,11 @@ void ZigbeeNetwork::setError(ZigbeeNetwork::Error error)
emit errorOccured(m_error); emit errorOccured(m_error);
} }
bool ZigbeeNetwork::networkConfigurationAvailable() const
{
return m_extendedPanId != 0 && m_channel != 0;
}
void ZigbeeNetwork::onNodeStateChanged(ZigbeeNode::State state) void ZigbeeNetwork::onNodeStateChanged(ZigbeeNode::State state)
{ {
ZigbeeNode *node = qobject_cast<ZigbeeNode *>(sender()); ZigbeeNode *node = qobject_cast<ZigbeeNode *>(sender());

View File

@ -94,7 +94,6 @@ public:
bool hasNode(quint16 shortAddress) const; bool hasNode(quint16 shortAddress) const;
bool hasNode(const ZigbeeAddress &address) const; bool hasNode(const ZigbeeAddress &address) const;
private: private:
State m_state = StateUninitialized; State m_state = StateUninitialized;
@ -107,7 +106,6 @@ private:
quint32 m_channel = 0; quint32 m_channel = 0;
ZigbeeSecurityConfiguration m_securityConfiguration; ZigbeeSecurityConfiguration m_securityConfiguration;
ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator; ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator;
bool m_permitJoining = false;
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf"; QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
QList<ZigbeeNode *> m_nodes; QList<ZigbeeNode *> m_nodes;
@ -118,6 +116,11 @@ private:
protected: protected:
Error m_error = ErrorNoError; Error m_error = ErrorNoError;
ZigbeeNode *m_coordinatorNode = nullptr;
bool m_permitJoining = false;
virtual ZigbeeNode *createNode(QObject *parent) = 0;
virtual void setPermitJoiningInternal(bool permitJoining) = 0;
void saveNetwork(); void saveNetwork();
void loadNetwork(); void loadNetwork();
@ -126,8 +129,6 @@ protected:
void saveNode(ZigbeeNode *node); void saveNode(ZigbeeNode *node);
void removeNodeFromSettings(ZigbeeNode *node); void removeNodeFromSettings(ZigbeeNode *node);
ZigbeeNode *createNode(QObject *parent);
void addNode(ZigbeeNode *node); void addNode(ZigbeeNode *node);
void addUnitializedNode(ZigbeeNode *node); void addUnitializedNode(ZigbeeNode *node);
void removeNode(ZigbeeNode *node); void removeNode(ZigbeeNode *node);
@ -135,6 +136,8 @@ protected:
void setState(State state); void setState(State state);
void setError(Error error); void setError(Error error);
bool networkConfigurationAvailable() const;
signals: signals:
void settingsFileNameChanged(const QString &settingsFileName); void settingsFileNameChanged(const QString &settingsFileName);
void serialPortNameChanged(const QString &serialPortName); void serialPortNameChanged(const QString &serialPortName);

View File

@ -27,47 +27,18 @@
#include "zigbeenetworkmanager.h" #include "zigbeenetworkmanager.h"
#include "loggingcategory.h" #include "loggingcategory.h"
#include "zigbeeutils.h"
#include "nxp/zigbeenetworknxp.h" #include "nxp/zigbeenetworknxp.h"
#include <QDateTime> #include <QDateTime>
#include <QDataStream>
#include <QSettings>
ZigbeeNetworkManager::ZigbeeNetworkManager(const QString &serialPortName, qint32 baudrate, BackendType backendType, QObject *parent) : ZigbeeNetwork *ZigbeeNetworkManager::createZigbeeNetwork(ZigbeeNetworkManager::BackendType backend, QObject *parent)
QObject(parent),
m_serialPortName(serialPortName),
m_baudrate(baudrate),
m_backendType(backendType)
{ {
srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000)); srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
switch (backend) {
switch (backendType) {
case BackendTypeNxp: case BackendTypeNxp:
m_network = new ZigbeeNetworkNxp(this); return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkNxp(parent));
m_network->setSerialPortName(m_serialPortName);
m_network->setSerialBaudrate(baudrate);
break;
} }
}
QString ZigbeeNetworkManager::serialPortName() const return nullptr;
{
return m_serialPortName;
}
qint32 ZigbeeNetworkManager::baudrate() const
{
return m_baudrate;
}
ZigbeeNetworkManager::BackendType ZigbeeNetworkManager::backendType() const
{
return m_backendType;
}
ZigbeeNetwork *ZigbeeNetworkManager::network() const
{
return m_network;
} }

View File

@ -35,32 +35,14 @@
#include "zigbeenetwork.h" #include "zigbeenetwork.h"
class ZigbeeNetworkManager : public QObject class ZigbeeNetworkManager
{ {
Q_OBJECT
public: public:
enum BackendType { enum BackendType {
BackendTypeNxp BackendTypeNxp
}; };
Q_ENUM(BackendType)
explicit ZigbeeNetworkManager(const QString &serialPortName, qint32 baudrate, BackendType backendType, QObject *parent = nullptr);
QString serialPortName() const;
qint32 baudrate() const;
BackendType backendType() const;
ZigbeeNetwork *network() const;
private:
QString m_serialPortName;
qint32 m_baudrate;
BackendType m_backendType = BackendTypeNxp;
ZigbeeNetwork *m_network = nullptr;
private slots:
static ZigbeeNetwork *createZigbeeNetwork(BackendType backend, QObject *parent = nullptr);
}; };
#endif // ZIGBEEMANAGER_H #endif // ZIGBEEMANAGER_H

View File

@ -493,6 +493,11 @@ void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
} }
void ZigbeeNode::startInitialization()
{
qCWarning(dcZigbeeNode()) << "Start initialization is not implemented for this backend.";
}
void ZigbeeNode::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute) void ZigbeeNode::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute)
{ {
qCDebug(dcZigbeeNode()) << this << "cluster attribute changed" << clusterId << attribute; qCDebug(dcZigbeeNode()) << this << "cluster attribute changed" << clusterId << attribute;

View File

@ -39,7 +39,6 @@ class ZigbeeNode : public QObject
Q_OBJECT Q_OBJECT
friend class ZigbeeNetwork; friend class ZigbeeNetwork;
friend class ZigbeeNetworkManager;
public: public:
enum State { enum State {
@ -146,7 +145,6 @@ public:
PowerLevel powerLevel() const; PowerLevel powerLevel() const;
private: private:
ZigbeeNode(QObject *parent = nullptr);
bool m_connected = false; bool m_connected = false;
State m_state = StateUninitialized; State m_state = StateUninitialized;
@ -199,7 +197,8 @@ private:
bool m_extendedActiveEndpointListAvailable = false; bool m_extendedActiveEndpointListAvailable = false;
bool m_extendedSimpleDescriptorListAvailable = false; bool m_extendedSimpleDescriptorListAvailable = false;
private: protected:
ZigbeeNode(QObject *parent = nullptr);
void setState(State state); void setState(State state);
void setConnected(bool connected); void setConnected(bool connected);
@ -225,6 +224,9 @@ private:
quint16 powerDescriptorFlag() const; quint16 powerDescriptorFlag() const;
void setPowerDescriptorFlag(quint16 powerDescriptorFlag); void setPowerDescriptorFlag(quint16 powerDescriptorFlag);
//
virtual void startInitialization();
// Cluster commands // Cluster commands
void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()); void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute());