Continue NXP uart integrations and finish basic network handling

pull/8/head
Simon Stürz 2020-10-14 18:04:11 +02:00
parent b8b2b00e4f
commit a3256af29d
5 changed files with 171 additions and 19 deletions

View File

@ -12,15 +12,20 @@ public:
CommandGetControllerState = 0x01,
CommandSoftReset = 0x02,
CommandFactoryReset = 0x03,
CommandSetPanId = 0x04,
CommandSetChannelMask = 0x05,
CommandSetSecurityKey = 0x06,
CommandStartNetwork = 0x07
CommandStartNetwork = 0x07,
CommandGetNetworkState = 0x08,
CommandSetPermitJoinCoordinator = 0x09
};
Q_ENUM(Command)
enum Notification {
NotificationDeviceStatusChanged = 0x7D,
NotificationNetworkStarted = 0x7E,
NotificationDebugMessage = 0xFE
};
Q_ENUM(Notification)

View File

@ -133,6 +133,33 @@ ZigbeeInterfaceNxpReply *ZigbeeBridgeControllerNxp::requestStartNetwork()
return createReply(Nxp::CommandStartNetwork, m_sequenceNumber, "Request start network", message, this);
}
ZigbeeInterfaceNxpReply *ZigbeeBridgeControllerNxp::requestNetworkState()
{
QByteArray message;
bumpSequenceNumber();
QDataStream stream(&message, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(Nxp::CommandGetNetworkState);
stream << static_cast<quint8>(m_sequenceNumber);
stream << static_cast<quint16>(0); // Frame length
return createReply(Nxp::CommandGetNetworkState, m_sequenceNumber, "Request network state", message, this);
}
ZigbeeInterfaceNxpReply *ZigbeeBridgeControllerNxp::requestSetPermitJoinCoordinator(quint8 duration)
{
QByteArray message;
bumpSequenceNumber();
QDataStream stream(&message, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(Nxp::CommandSetPermitJoinCoordinator);
stream << static_cast<quint8>(m_sequenceNumber);
stream << static_cast<quint16>(1); // Frame length
stream << duration;
return createReply(Nxp::CommandSetPermitJoinCoordinator, m_sequenceNumber, "Request set permit join in coordinator", message, this);
}
ZigbeeInterfaceNxpReply *ZigbeeBridgeControllerNxp::createReply(Nxp::Command command, quint8 sequenceNumber, const QString &requestName, const QByteArray &requestData, QObject *parent)
{
// Create the reply

View File

@ -46,7 +46,12 @@ public:
ZigbeeInterfaceNxpReply *requestSetChannelMask(quint32 channelMask);
ZigbeeInterfaceNxpReply *requestSetSecurityKey(Nxp::KeyType keyType, const ZigbeeNetworkKey &key);
// Network commands
ZigbeeInterfaceNxpReply *requestStartNetwork();
ZigbeeInterfaceNxpReply *requestNetworkState();
ZigbeeInterfaceNxpReply *requestSetPermitJoinCoordinator(quint8 duration);
// APS
signals:

View File

@ -9,10 +9,10 @@ ZigbeeNetworkNxp::ZigbeeNetworkNxp(QObject *parent) :
{
m_controller = new ZigbeeBridgeControllerNxp(this);
connect(m_controller, &ZigbeeBridgeControllerNxp::availableChanged, this, &ZigbeeNetworkNxp::onControllerAvailableChanged);
connect(m_controller, &ZigbeeBridgeControllerNxp::interfaceNotificationReceived, this, &ZigbeeNetworkNxp::onInterfaceNotificationReceived);
connect(m_controller, &ZigbeeBridgeControllerNxp::controllerStateChanged, this, &ZigbeeNetworkNxp::onControllerStateChanged);
//connect(m_controller, &ZigbeeBridgeControllerNxp::apsDataConfirmReceived, this, &ZigbeeNetworkNxp::onApsDataConfirmReceived);
//connect(m_controller, &ZigbeeBridgeControllerNxp::apsDataIndicationReceived, this, &ZigbeeNetworkNxp::onApsDataIndicationReceived);
}
ZigbeeBridgeController *ZigbeeNetworkNxp::bridgeController() const
@ -39,17 +39,24 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::setPermitJoin(quint16 shortAddress, quint8
void ZigbeeNetworkNxp::onControllerAvailableChanged(bool available)
{
qCDebug(dcZigbeeNetwork()) << "Controller is" << (available ? "now available" : "not available any more");
if (available) {
// Get controller state
// Get network state, depending on the controller state
//reset();
factoryResetNetwork();
} else {
setState(StateOffline);
}
}
void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::ControllerState controllerState)
{
qCDebug(dcZigbeeNetwork()) << "Controller state changed" << controllerState;
switch (controllerState) {
case ZigbeeBridgeControllerNxp::ControllerStateRunning: {
setState(StateStarting);
qCDebug(dcZigbeeNetwork()) << "Request controller version";
ZigbeeInterfaceNxpReply *reply = m_controller->requestVersion();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
@ -64,16 +71,74 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr
qCDebug(dcZigbeeNetwork()) << "Controller version" << versionString;
m_controller->setFirmwareVersion(versionString);
// We are done here...
qCDebug(dcZigbeeNetwork()) << "Get the current network state";
ZigbeeInterfaceNxpReply *reply = m_controller->requestNetworkState();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
qCDebug(dcZigbeeNetwork()) << "Get network state response" << reply->status();
//FIXME: error handling
QByteArray data = reply->responseData();
QDataStream payloadStream(&data, QIODevice::ReadOnly);
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint16 networkAddress; quint64 ieeeAddress; quint8 channel;
quint16 panId; quint64 extendedPanId;
payloadStream >> networkAddress >> ieeeAddress >> channel >> panId >> extendedPanId;
qCDebug(dcZigbeeNetwork()) << "Network running" << ZigbeeUtils::convertUint16ToHexString(networkAddress)
<< ZigbeeAddress(ieeeAddress).toString()
<< "Channel:" << channel
<< "PAN ID:" << panId << "Extended PAN ID:" << ZigbeeUtils::convertUint64ToHexString(extendedPanId);
setPanId(panId);
setChannel(channel);
// Initialize the coordinator node if not already done.
if (m_coordinatorNode) {
qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done.";
m_database->saveNode(m_coordinatorNode);
setState(StateRunning);
setPermitJoiningInternal(false);
return;
}
ZigbeeNode *coordinatorNode = createNode(networkAddress, ZigbeeAddress(ieeeAddress), this);
m_coordinatorNode = coordinatorNode;
// TODO: initialize
m_database->saveNode(m_coordinatorNode);
saveNetwork();
setState(StateRunning);
// // Network creation done when coordinator node is initialized
// connect(coordinatorNode, &ZigbeeNode::stateChanged, this, [this, coordinatorNode](ZigbeeNode::State state){
// if (state == ZigbeeNode::StateInitialized) {
// qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
// m_initializing = false;
// setState(StateRunning);
// setPermitJoiningInternal(false);
// return;
// }
// });
// coordinatorNode->startInitialization();
// addUnitializedNode(coordinatorNode);
});
});
break;
}
case ZigbeeBridgeControllerNxp::ControllerStateStarting:
setState(StateStarting);
break;
case ZigbeeBridgeControllerNxp::ControllerStateBooting:
setState(StateStarting);
break;
case ZigbeeBridgeControllerNxp::ControllerStateRunningUninitialized: {
setState(StateStarting);
qCDebug(dcZigbeeNetwork()) << "Request controller version";
ZigbeeInterfaceNxpReply *reply = m_controller->requestVersion();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
@ -90,38 +155,48 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr
qCDebug(dcZigbeeNetwork()) << "Controller version" << versionString;
m_controller->setFirmwareVersion(versionString);
qCDebug(dcZigbeeNetwork()) << "Set pan id" << ZigbeeUtils::convertUint64ToHexString(extendedPanId()) << extendedPanId();
if (extendedPanId() == 0) {
quint64 panId = ZigbeeUtils::generateRandomPanId();
setExtendedPanId(panId);
qCDebug(dcZigbeeNetwork()) << "There is no pan id set yet. Generated new PAN ID" << panId << ZigbeeUtils::convertUint64ToHexString(panId);
ZigbeeSecurityConfiguration securityConfiguration;
securityConfiguration.setNetworkKey(ZigbeeNetworkKey::generateKey());
setSecurityConfiguration(securityConfiguration);
qCDebug(dcZigbeeNetwork()) << "Generated new network key" << securityConfiguration.networkKey().toString();
}
qCDebug(dcZigbeeNetwork()) << "Set PAN ID" << ZigbeeUtils::convertUint64ToHexString(extendedPanId()) << extendedPanId();
ZigbeeInterfaceNxpReply *reply = m_controller->requestSetPanId(extendedPanId());
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
qCDebug(dcZigbeeNetwork()) << "Set PAN ID reply finished" << reply->status();
qCDebug(dcZigbeeNetwork()) << "Set PAN ID reply response" << reply->status();
//FIXME: error handling
qCDebug(dcZigbeeNetwork()) << "Set channel mask" << channelMask() << ZigbeeUtils::convertUint32ToHexString(channelMask().toUInt32()) << channelMask().toUInt32();
qCDebug(dcZigbeeNetwork()) << "Set channel mask" << channelMask();
ZigbeeInterfaceNxpReply *reply = m_controller->requestSetChannelMask(channelMask().toUInt32());
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
qCDebug(dcZigbeeNetwork()) << "Set channel mask reply finished" << reply->status();
qCDebug(dcZigbeeNetwork()) << "Set channel mask reply response" << reply->status();
//FIXME: error handling
qCDebug(dcZigbeeNetwork()) << "Set global link key" << securityConfiguration().globalTrustCenterLinkKey().toString();
ZigbeeInterfaceNxpReply *reply = m_controller->requestSetSecurityKey(Nxp::KeyTypeGlobalLinkKey, securityConfiguration().globalTrustCenterLinkKey());
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
qCDebug(dcZigbeeNetwork()) << "Set global link key" << reply->status();
qCDebug(dcZigbeeNetwork()) << "Set global link key response" << reply->status();
//FIXME: error handling
qCDebug(dcZigbeeNetwork()) << "Set network link key" << securityConfiguration().networkKey().toString();
ZigbeeInterfaceNxpReply *reply = m_controller->requestSetSecurityKey(Nxp::KeyTypeUniqueLinkKey, securityConfiguration().networkKey());
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
qCDebug(dcZigbeeNetwork()) << "Set network link key" << reply->status();
qCDebug(dcZigbeeNetwork()) << "Set network link key response" << reply->status();
//FIXME: error handling
qCDebug(dcZigbeeNetwork()) << "Start the network";
ZigbeeInterfaceNxpReply *reply = m_controller->requestStartNetwork();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply](){
qCDebug(dcZigbeeNetwork()) << "Start network" << reply->status();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [reply](){
qCDebug(dcZigbeeNetwork()) << "Start network response" << reply->status();
//FIXME: error handling
qCDebug(dcZigbeeNetwork()) << "Waiting for the network to start...";
});
});
});
@ -131,13 +206,50 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr
break;
}
case ZigbeeBridgeControllerNxp::ControllerStateNotRunning:
setState(StateOffline);
break;
}
}
void ZigbeeNetworkNxp::onInterfaceNotificationReceived(Nxp::Notification notification, const QByteArray &payload)
{
switch (notification) {
case Nxp::NotificationNetworkStarted: {
QByteArray data = payload;
QDataStream payloadStream(&data, QIODevice::ReadOnly);
payloadStream.setByteOrder(QDataStream::LittleEndian);
quint16 networkAddress; quint64 ieeeAddress; quint8 channel;
payloadStream >> networkAddress >> ieeeAddress >> channel;
qCDebug(dcZigbeeNetwork()) << "Network started" << ZigbeeUtils::convertUint16ToHexString(networkAddress) << ZigbeeAddress(ieeeAddress).toString() << "Channel:" << channel;
break;
}
default:
qCWarning(dcZigbeeNetwork()) << "Unhandeld interface notification received" << notification << ZigbeeUtils::convertByteArrayToHexString(payload);
}
}
void ZigbeeNetworkNxp::setPermitJoiningInternal(bool permitJoining)
{
qCDebug(dcZigbeeNetwork()) << "Set permit join internal" << permitJoining;
quint8 duration = 0;
if (permitJoining) {
duration = 255;
}
// TODO: send broadcast message using ZDO and refrash
qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator node to" << duration << "[s]";
ZigbeeInterfaceNxpReply *reply = m_controller->requestSetPermitJoinCoordinator(duration);
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply, permitJoining](){
qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator finished" << reply->status();
m_permitJoining = permitJoining;
emit permitJoiningChanged(m_permitJoining);
});
}
void ZigbeeNetworkNxp::startNetwork()
@ -165,16 +277,18 @@ void ZigbeeNetworkNxp::stopNetwork()
void ZigbeeNetworkNxp::reset()
{
qCDebug(dcZigbeeNetwork()) << "Soft reset the controller. The stack will perform a restart.";
ZigbeeInterfaceNxpReply *reply = m_controller->requestSoftResetController();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [](){
qCDebug(dcZigbeeNetwork()) << "Soft reset reply finished";
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [reply](){
qCDebug(dcZigbeeNetwork()) << "Soft reset reply finished" << reply->status();
});
}
void ZigbeeNetworkNxp::factoryResetNetwork()
{
qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone.";
ZigbeeInterfaceNxpReply *reply = m_controller->requestFactoryResetController();
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [](){
qCDebug(dcZigbeeNetwork()) << "Factory reset reply finished";
connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [reply](){
qCDebug(dcZigbeeNetwork()) << "Factory reset reply finished" << reply->status();
});
}

View File

@ -27,6 +27,7 @@ private:
private slots:
void onControllerAvailableChanged(bool available);
void onControllerStateChanged(ZigbeeBridgeControllerNxp::ControllerState controllerState);
void onInterfaceNotificationReceived(Nxp::Notification notification, const QByteArray &payload);
protected:
void setPermitJoiningInternal(bool permitJoining) override;