diff --git a/docs/deconz/deCONZ-Serial-Protocol-en_1.20.pdf b/docs/deconz/deCONZ-Serial-Protocol-en_1.20.pdf new file mode 100644 index 0000000..fffba1b Binary files /dev/null and b/docs/deconz/deCONZ-Serial-Protocol-en_1.20.pdf differ diff --git a/libnymea-zigbee/backends/deconz/interface/deconz.h b/libnymea-zigbee/backends/deconz/interface/deconz.h index 3ea785b..3c7dac7 100644 --- a/libnymea-zigbee/backends/deconz/interface/deconz.h +++ b/libnymea-zigbee/backends/deconz/interface/deconz.h @@ -67,13 +67,14 @@ public: CommandApsDataIndication = 0x17, CommandGreenPower = 0x19, CommandMacPoll = 0x1C, - CommandSimplifiedBeacon = 0x1F + CommandMacBeacon = 0x1F, + CommandUpdateBootloader = 0x21 }; Q_ENUM(Command) enum Parameter { ParameterMacAddress = 0x01, // R - ParameterPanId = 0x05, // R + ParameterPanId = 0x05, // RW ParameterNetworkAddress = 0x07, // R ParameterNetworkExtendedPanId = 0x08, // R ParameterNodeType = 0x09, //RW @@ -81,12 +82,15 @@ public: ParameterApsExtendedPanId = 0x0B, //RW ParameterTrustCenterAddress = 0x0E, // RW ParameterSecurityMode = 0x10, // RW - ParameterNetworkKey = 0x18, //W + ParameterPredefinedNwkPanId = 0x15, // RW + ParameterNetworkKey = 0x18, // RW + ParameterLinkKey = 0x19, // RW ParameterCurrentChannel = 0x1c, // R ParameterPermitJoin = 0x21, // RW ParameterProtocolVersion = 0x22, // R ParameterNetworkUpdateId = 0x24, // RW - ParameterWatchdogTtl = 0x26 // RW since protocol version 0x0108 + ParameterWatchdogTtl = 0x26, // RW since protocol version 0x0108 + ParameterNetworkFrameCounter = 0x27 // RW }; Q_ENUM(Parameter) diff --git a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp index 9023a77..7990782 100644 --- a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp +++ b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.cpp @@ -67,6 +67,29 @@ Deconz::NetworkState ZigbeeBridgeControllerDeconz::networkState() const return m_networkState; } +void ZigbeeBridgeControllerDeconz::rebootController() +{ + // According to the docs, the watchdog can be used to reboot the device by + // setting the watchdog timeout to a small value and let it timeout + + // Reset the timer to prevent interrupting the reboot + m_watchdogTimer->start(); + + // Write the watchdog to 2 seconds + QByteArray parameterData; + QDataStream stream(¶meterData, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(2); + ZigbeeInterfaceDeconzReply *reply = requestWriteParameter(Deconz::ParameterWatchdogTtl, parameterData); + connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [reply](){ + if (reply->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Could initiate reboot controller by writing watchdog parameter." << reply->statusCode(); + return; + } + qCDebug(dcZigbeeController()) << "Reboot device requested successfully. The controler is about to reboot..."; + }); +} + ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestVersion() { @@ -216,9 +239,9 @@ void ZigbeeBridgeControllerDeconz::sendNextRequest() if (m_currentReply) return; -// // FIXME: If the controler request queue is full, wait until it's free again -// if (!m_apsFreeSlotsAvailable) -// return; + // // FIXME: If the controler request queue is full, wait until it's free again + // if (!m_apsFreeSlotsAvailable) + // return; // Get the next reply, set the sequence number, send the request data over the interface and start waiting m_currentReply = m_replyQueue.dequeue(); @@ -284,12 +307,12 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Co ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius) { -// quint8 sequenceNumber = generateSequenceNumber(); -// qCDebug(dcZigbeeController()) << "Request enqueue send data to group" << ZigbeeUtils::convertUint16ToHexString(groupAddress) -// << "SQN:" << sequenceNumber -// << static_cast(profileId) -// << ZigbeeUtils::convertUint16ToHexString(clusterId) -// << ZigbeeUtils::convertByteToHexString(sourceEndpoint); + // quint8 sequenceNumber = generateSequenceNumber(); + // qCDebug(dcZigbeeController()) << "Request enqueue send data to group" << ZigbeeUtils::convertUint16ToHexString(groupAddress) + // << "SQN:" << sequenceNumber + // << static_cast(profileId) + // << ZigbeeUtils::convertUint16ToHexString(clusterId) + // << ZigbeeUtils::convertByteToHexString(sourceEndpoint); Q_ASSERT_X(asdu.length() <= 127, "ASDU", "ASDU package length has to <= 127 bytes"); @@ -323,13 +346,13 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius) { -// quint8 sequenceNumber = generateSequenceNumber(); -// qCDebug(dcZigbeeController()) << "Request enqueue send data to short address" << ZigbeeUtils::convertUint16ToHexString(shortAddress) -// << "SQN:" << sequenceNumber -// << ZigbeeUtils::convertByteToHexString(destinationEndpoint) -// << static_cast(profileId) -// << ZigbeeUtils::convertUint16ToHexString(clusterId) -// << ZigbeeUtils::convertByteToHexString(sourceEndpoint); + // quint8 sequenceNumber = generateSequenceNumber(); + // qCDebug(dcZigbeeController()) << "Request enqueue send data to short address" << ZigbeeUtils::convertUint16ToHexString(shortAddress) + // << "SQN:" << sequenceNumber + // << ZigbeeUtils::convertByteToHexString(destinationEndpoint) + // << static_cast(profileId) + // << ZigbeeUtils::convertUint16ToHexString(clusterId) + // << ZigbeeUtils::convertByteToHexString(sourceEndpoint); Q_ASSERT_X(asdu.length() <= 127, "ASDU", "ASDU package length has to <= 127 bytes"); @@ -363,12 +386,12 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius) { -// quint8 sequenceNumber = generateSequenceNumber(); -// qCDebug(dcZigbeeController()) << "Request enqueue send data to IEEE address" << ieeeAddress.toString() -// << "SQN:" << sequenceNumber -// << ZigbeeUtils::convertByteToHexString(destinationEndpoint) -// << profileId << clusterId -// << ZigbeeUtils::convertByteToHexString(sourceEndpoint); + // quint8 sequenceNumber = generateSequenceNumber(); + // qCDebug(dcZigbeeController()) << "Request enqueue send data to IEEE address" << ieeeAddress.toString() + // << "SQN:" << sequenceNumber + // << ZigbeeUtils::convertByteToHexString(destinationEndpoint) + // << profileId << clusterId + // << ZigbeeUtils::convertByteToHexString(sourceEndpoint); Q_ASSERT_X(asdu.length() <= 127, "ZigbeeController", "ASDU package length has to be <= 127 bytes"); @@ -420,7 +443,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( << Deconz::ParameterMacAddress << "finished with error" << replyMacAddress->statusCode(); readNetworkParametersReply->m_statusCode = replyMacAddress->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } QDataStream stream(replyMacAddress->responseData()); @@ -440,7 +463,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyPanId->sequenceNumber() << replyPanId->command() << Deconz::ParameterPanId << "finished with error" << replyPanId->statusCode(); readNetworkParametersReply->m_statusCode = replyPanId->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } QDataStream stream(replyPanId->responseData()); @@ -460,7 +483,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyShortAddress->sequenceNumber() << replyShortAddress->command() << Deconz::ParameterNetworkAddress << "finished with error" << replyShortAddress->statusCode(); readNetworkParametersReply->m_statusCode = replyShortAddress->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } @@ -480,7 +503,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyExtendedPanId->sequenceNumber() << replyExtendedPanId->command() << Deconz::ParameterNetworkExtendedPanId << "finished with error" << replyExtendedPanId->statusCode(); readNetworkParametersReply->m_statusCode = replyExtendedPanId->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } @@ -500,7 +523,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyNodeType->sequenceNumber() << replyNodeType->command() << Deconz::ParameterNodeType << "finished with error" << replyNodeType->statusCode(); readNetworkParametersReply->m_statusCode = replyNodeType->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } @@ -521,7 +544,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyChannelMask->sequenceNumber() << replyChannelMask->command() << Deconz::ParameterChannelMask << "finished with error" << replyChannelMask->statusCode(); readNetworkParametersReply->m_statusCode = replyChannelMask->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } @@ -542,7 +565,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyApsExtendedPanId->sequenceNumber() << replyApsExtendedPanId->command() << Deconz::ParameterApsExtendedPanId << "finished with error" << replyApsExtendedPanId->statusCode(); readNetworkParametersReply->m_statusCode = replyApsExtendedPanId->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } @@ -563,7 +586,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyTrustCenterAddress->sequenceNumber() << replyTrustCenterAddress->command() << Deconz::ParameterTrustCenterAddress << "finished with error" << replyTrustCenterAddress->statusCode(); readNetworkParametersReply->m_statusCode = replyTrustCenterAddress->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } @@ -584,7 +607,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replySecurityMode->sequenceNumber() << replySecurityMode->command() << Deconz::ParameterSecurityMode << "finished with error" << replySecurityMode->statusCode(); readNetworkParametersReply->m_statusCode = replySecurityMode->statusCode(); - readNetworkParametersReply->finished(); + emit readNetworkParametersReply->finished(); return; } @@ -598,128 +621,158 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters( << static_cast(parameter) << "finished successfully"; qCDebug(dcZigbeeController()) << m_networkConfiguration.securityMode; - // Note: reading the network key returns "InavlidParameter". Might be for security reasons which is good! - // Read channel - ZigbeeInterfaceDeconzReply *replyChannel = requestReadParameter(Deconz::ParameterCurrentChannel); - connect(replyChannel, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyChannel](){ - if (replyChannel->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyChannel->sequenceNumber() << replyChannel->command() << Deconz::ParameterCurrentChannel - << "finished with error" << replyChannel->statusCode(); - readNetworkParametersReply->m_statusCode = replyChannel->statusCode(); - readNetworkParametersReply->finished(); + // Read predefined new pan id + ZigbeeInterfaceDeconzReply *replyPredefinedNwkPanId = requestReadParameter(Deconz::ParameterPredefinedNwkPanId); + connect(replyPredefinedNwkPanId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyPredefinedNwkPanId](){ + if (replyPredefinedNwkPanId->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyPredefinedNwkPanId->sequenceNumber() << replyPredefinedNwkPanId->command() + << Deconz::ParameterSecurityMode << "finished with error" << replyPredefinedNwkPanId->statusCode(); + readNetworkParametersReply->m_statusCode = replyPredefinedNwkPanId->statusCode(); + emit readNetworkParametersReply->finished(); return; } - QDataStream stream(replyChannel->responseData()); + QDataStream stream(replyPredefinedNwkPanId->responseData()); stream.setByteOrder(QDataStream::LittleEndian); - quint16 payloadLenght = 0; quint8 parameter = 0; quint8 channel = 0; - stream >> payloadLenght >> parameter >> channel; - m_networkConfiguration.currentChannel = channel; - qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyChannel->sequenceNumber() << replyChannel->command() << static_cast(parameter) - << "finished successfully"; - qCDebug(dcZigbeeController()) << "Current channel:" << m_networkConfiguration.currentChannel; + quint16 payloadLenght = 0; quint8 parameter = 0; quint8 predefinedNwkPanId = 0; + stream >> payloadLenght >> parameter >> predefinedNwkPanId; + + m_networkConfiguration.predefinedNetworkPanId = static_cast(predefinedNwkPanId); + qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyPredefinedNwkPanId->sequenceNumber() << replyPredefinedNwkPanId->command() + << static_cast(parameter) << "finished successfully"; + qCDebug(dcZigbeeController()) << m_networkConfiguration.predefinedNetworkPanId; - // Read permit join status - ZigbeeInterfaceDeconzReply *replyPermitJoin = requestReadParameter(Deconz::ParameterPermitJoin); - connect(replyPermitJoin, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyPermitJoin](){ - if (replyPermitJoin->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyPermitJoin->sequenceNumber() << replyPermitJoin->command() - << Deconz::ParameterPermitJoin << "finished with error" << replyPermitJoin->statusCode(); - readNetworkParametersReply->m_statusCode = replyPermitJoin->statusCode(); - readNetworkParametersReply->finished(); + // We don't make use of link key for now + + // Note: reading the network key returns "InavlidParameter". Might be for security reasons which is good! + + // Read channel + ZigbeeInterfaceDeconzReply *replyChannel = requestReadParameter(Deconz::ParameterCurrentChannel); + connect(replyChannel, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyChannel](){ + if (replyChannel->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyChannel->sequenceNumber() << replyChannel->command() << Deconz::ParameterCurrentChannel + << "finished with error" << replyChannel->statusCode(); + readNetworkParametersReply->m_statusCode = replyChannel->statusCode(); + emit readNetworkParametersReply->finished(); return; } - QDataStream stream(replyPermitJoin->responseData()); + QDataStream stream(replyChannel->responseData()); stream.setByteOrder(QDataStream::LittleEndian); - quint16 payloadLenght = 0; quint8 parameter = 0; - stream >> payloadLenght >> parameter; - //m_networkConfiguration.currentChannel = channel; - qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyPermitJoin->sequenceNumber() << replyPermitJoin->command() << static_cast(parameter) - << "finished successfully" << ZigbeeUtils::convertByteArrayToHexString(replyPermitJoin->responseData()); + quint16 payloadLenght = 0; quint8 parameter = 0; quint8 channel = 0; + stream >> payloadLenght >> parameter >> channel; + m_networkConfiguration.currentChannel = channel; + qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyChannel->sequenceNumber() << replyChannel->command() << static_cast(parameter) + << "finished successfully"; + qCDebug(dcZigbeeController()) << "Current channel:" << m_networkConfiguration.currentChannel; - // Read protocol version - ZigbeeInterfaceDeconzReply *replyProtocolVersion = requestReadParameter(Deconz::ParameterProtocolVersion); - connect(replyProtocolVersion, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyProtocolVersion](){ - if (replyProtocolVersion->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyProtocolVersion->sequenceNumber() << replyProtocolVersion->command() - << Deconz::ParameterProtocolVersion << "finished with error" << replyProtocolVersion->statusCode(); - readNetworkParametersReply->m_statusCode = replyProtocolVersion->statusCode(); - readNetworkParametersReply->finished(); + // Read permit join status + ZigbeeInterfaceDeconzReply *replyPermitJoin = requestReadParameter(Deconz::ParameterPermitJoin); + connect(replyPermitJoin, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyPermitJoin](){ + if (replyPermitJoin->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyPermitJoin->sequenceNumber() << replyPermitJoin->command() + << Deconz::ParameterPermitJoin << "finished with error" << replyPermitJoin->statusCode(); + readNetworkParametersReply->m_statusCode = replyPermitJoin->statusCode(); + emit readNetworkParametersReply->finished(); return; } - QDataStream stream(replyProtocolVersion->responseData()); + QDataStream stream(replyPermitJoin->responseData()); stream.setByteOrder(QDataStream::LittleEndian); - quint16 payloadLenght = 0; quint8 parameter = 0; quint16 protocolVersion = 0; - stream >> payloadLenght >> parameter >> protocolVersion; - m_networkConfiguration.protocolVersion = protocolVersion; - qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyProtocolVersion->sequenceNumber() << replyProtocolVersion->command() - << static_cast(parameter) << "finished successfully"; - qCDebug(dcZigbeeController()) << "Protocol version:" << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.protocolVersion); + quint16 payloadLenght = 0; quint8 parameter = 0; + stream >> payloadLenght >> parameter; + //m_networkConfiguration.currentChannel = channel; + qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyPermitJoin->sequenceNumber() << replyPermitJoin->command() << static_cast(parameter) + << "finished successfully" << ZigbeeUtils::convertByteArrayToHexString(replyPermitJoin->responseData()); - // Read network updat id - ZigbeeInterfaceDeconzReply *replyNetworkUpdateId = requestReadParameter(Deconz::ParameterNetworkUpdateId); - connect(replyNetworkUpdateId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyNetworkUpdateId](){ - if (replyNetworkUpdateId->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyNetworkUpdateId->sequenceNumber() << replyNetworkUpdateId->command() - << Deconz::ParameterNetworkUpdateId << "finished with error" << replyNetworkUpdateId->statusCode(); - readNetworkParametersReply->m_statusCode = replyNetworkUpdateId->statusCode(); - readNetworkParametersReply->finished(); + + // Read protocol version + ZigbeeInterfaceDeconzReply *replyProtocolVersion = requestReadParameter(Deconz::ParameterProtocolVersion); + connect(replyProtocolVersion, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyProtocolVersion](){ + if (replyProtocolVersion->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyProtocolVersion->sequenceNumber() << replyProtocolVersion->command() + << Deconz::ParameterProtocolVersion << "finished with error" << replyProtocolVersion->statusCode(); + readNetworkParametersReply->m_statusCode = replyProtocolVersion->statusCode(); + emit readNetworkParametersReply->finished(); return; } - QDataStream stream(replyNetworkUpdateId->responseData()); + QDataStream stream(replyProtocolVersion->responseData()); stream.setByteOrder(QDataStream::LittleEndian); - quint16 payloadLenght = 0; quint8 parameter = 0; quint8 networkUpdateId = 0; - stream >> payloadLenght >> parameter >> networkUpdateId; - m_networkConfiguration.networkUpdateId = networkUpdateId; - qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyNetworkUpdateId->sequenceNumber() << replyNetworkUpdateId->command() + quint16 payloadLenght = 0; quint8 parameter = 0; quint16 protocolVersion = 0; + stream >> payloadLenght >> parameter >> protocolVersion; + m_networkConfiguration.protocolVersion = protocolVersion; + qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyProtocolVersion->sequenceNumber() << replyProtocolVersion->command() << static_cast(parameter) << "finished successfully"; - qCDebug(dcZigbeeController()) << "Network update ID:" << m_networkConfiguration.networkUpdateId; + qCDebug(dcZigbeeController()) << "Protocol version:" << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.protocolVersion); - // Make sure the watchdog is available for this version - if (m_networkConfiguration.protocolVersion < 0x0108) { - qCDebug(dcZigbeeController()) << "The watchdog api is available since protocol version 0x0108. The watchdog is not required for this version"; - m_watchdogTimer->stop(); - - // Finished reading all parameters. Finish the independent reply in order to indicate the process has finished - emit networkConfigurationParameterChanged(m_networkConfiguration); - readNetworkParametersReply->m_statusCode = Deconz::StatusCodeSuccess; - readNetworkParametersReply->finished(); - return; - } - - // Reset the watchdog in any case - resetControllerWatchdog(); - - // Read watchdog timeout - ZigbeeInterfaceDeconzReply *replyWatchdogTimeout = requestReadParameter(Deconz::ParameterWatchdogTtl); - connect(replyWatchdogTimeout, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyWatchdogTimeout](){ - if (replyWatchdogTimeout->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyWatchdogTimeout->sequenceNumber() << replyWatchdogTimeout->command() - << Deconz::ParameterWatchdogTtl << "finished with error" << replyWatchdogTimeout->statusCode(); - readNetworkParametersReply->m_statusCode = replyWatchdogTimeout->statusCode(); - readNetworkParametersReply->finished(); + // Read network updat id + ZigbeeInterfaceDeconzReply *replyNetworkUpdateId = requestReadParameter(Deconz::ParameterNetworkUpdateId); + connect(replyNetworkUpdateId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyNetworkUpdateId](){ + if (replyNetworkUpdateId->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyNetworkUpdateId->sequenceNumber() << replyNetworkUpdateId->command() + << Deconz::ParameterNetworkUpdateId << "finished with error" << replyNetworkUpdateId->statusCode(); + readNetworkParametersReply->m_statusCode = replyNetworkUpdateId->statusCode(); + emit readNetworkParametersReply->finished(); return; } - QDataStream stream(replyWatchdogTimeout->responseData()); + QDataStream stream(replyNetworkUpdateId->responseData()); stream.setByteOrder(QDataStream::LittleEndian); - quint16 payloadLenght = 0; quint8 parameter = 0; quint32 watchdogTimeout = 0; - stream >> payloadLenght >> parameter >> watchdogTimeout; - m_networkConfiguration.watchdogTimeout = watchdogTimeout; - qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyWatchdogTimeout->sequenceNumber() << replyWatchdogTimeout->command() + quint16 payloadLenght = 0; quint8 parameter = 0; quint8 networkUpdateId = 0; + stream >> payloadLenght >> parameter >> networkUpdateId; + m_networkConfiguration.networkUpdateId = networkUpdateId; + qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyNetworkUpdateId->sequenceNumber() << replyNetworkUpdateId->command() << static_cast(parameter) << "finished successfully"; - qCDebug(dcZigbeeController()) << "Watchdog timeout:" << m_networkConfiguration.watchdogTimeout; + qCDebug(dcZigbeeController()) << "Network update ID:" << m_networkConfiguration.networkUpdateId; - // Finished reading all parameters. Finish the independent reply in order to indicate the process has finished - emit networkConfigurationParameterChanged(m_networkConfiguration); - readNetworkParametersReply->m_statusCode = Deconz::StatusCodeSuccess; - readNetworkParametersReply->finished(); + // Make sure the watchdog is available for this version + if (m_networkConfiguration.protocolVersion < 0x0108) { + qCDebug(dcZigbeeController()) << "The watchdog api is available since protocol version 0x0108. The watchdog is not required for this version"; + m_watchdogTimer->stop(); + + // Finished reading all parameters. Finish the independent reply in order to indicate the process has finished + emit networkConfigurationParameterChanged(m_networkConfiguration); + readNetworkParametersReply->m_statusCode = Deconz::StatusCodeSuccess; + emit readNetworkParametersReply->finished(); + return; + } + + // Reset the watchdog in any case + resetControllerWatchdog(); + + // Read watchdog timeout + ZigbeeInterfaceDeconzReply *replyWatchdogTimeout = requestReadParameter(Deconz::ParameterWatchdogTtl); + connect(replyWatchdogTimeout, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyWatchdogTimeout](){ + if (replyWatchdogTimeout->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyWatchdogTimeout->sequenceNumber() << replyWatchdogTimeout->command() + << Deconz::ParameterWatchdogTtl << "finished with error" << replyWatchdogTimeout->statusCode(); + readNetworkParametersReply->m_statusCode = replyWatchdogTimeout->statusCode(); + emit readNetworkParametersReply->finished(); + return; + } + + QDataStream stream(replyWatchdogTimeout->responseData()); + stream.setByteOrder(QDataStream::LittleEndian); + quint16 payloadLenght = 0; quint8 parameter = 0; quint32 watchdogTimeout = 0; + stream >> payloadLenght >> parameter >> watchdogTimeout; + m_networkConfiguration.watchdogTimeout = watchdogTimeout; + qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyWatchdogTimeout->sequenceNumber() << replyWatchdogTimeout->command() + << static_cast(parameter) << "finished successfully"; + qCDebug(dcZigbeeController()) << "Watchdog timeout:" << m_networkConfiguration.watchdogTimeout; + + // Finished reading all parameters. Finish the independent reply in order to indicate the process has finished + emit networkConfigurationParameterChanged(m_networkConfiguration); + readNetworkParametersReply->m_statusCode = Deconz::StatusCodeSuccess; + emit readNetworkParametersReply->finished(); + + + // We ignore the frame counter for now, since we let the firmware take control + + }); }); }); }); @@ -819,7 +872,10 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt if (m_apsFreeSlotsAvailable != deviceState.apsDataRequestFreeSlots) { m_apsFreeSlotsAvailable = deviceState.apsDataRequestFreeSlots; if (!m_apsFreeSlotsAvailable) { - qCWarning(dcZigbeeController()) << "The APS request table is full on the device. Cannot send requests until the queue gets processed on the controller."; + // Warn only if the network is up + if (m_networkState == Deconz::NetworkStateConnected) { + qCWarning(dcZigbeeController()) << "The APS request table is full on the device. Cannot send requests until the queue gets processed on the controller."; + } return; } else { qCDebug(dcZigbeeController()) << "The APS request table is free again. Sending the next request"; @@ -925,6 +981,18 @@ void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data) } } +void ZigbeeBridgeControllerDeconz::processMacPoll(const QByteArray &data) +{ + qCDebug(dcZigbeeController()) << "MAC Poll command received" << ZigbeeUtils::convertByteArrayToHexString(data); + +} + +void ZigbeeBridgeControllerDeconz::processMacBeacon(const QByteArray &data) +{ + qCDebug(dcZigbeeController()) << "Simplified beacon command received" << ZigbeeUtils::convertByteArrayToHexString(data); + +} + void ZigbeeBridgeControllerDeconz::onInterfaceAvailableChanged(bool available) { qCDebug(dcZigbeeController()) << "Interface available changed" << available; @@ -961,7 +1029,7 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray & if (m_currentReply && m_currentReply->sequenceNumber() == sequenceNumber && m_currentReply->command() == command) { m_currentReply->m_responseData = data; m_currentReply->m_statusCode = status; - m_currentReply->finished(); + emit m_currentReply->finished(); // Note: the current reply will be cleaned up in the finished slot return; } @@ -979,13 +1047,11 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray & break; } case Deconz::CommandMacPoll: { - // FIXME: parse the data and print info - qCDebug(dcZigbeeController()) << "MAC Poll command received" << ZigbeeUtils::convertByteArrayToHexString(data); + processMacPoll(data); break; } - case Deconz::CommandSimplifiedBeacon: { - // FIXME: parse the data and print info - qCDebug(dcZigbeeController()) << "Simplified beacon command received" << ZigbeeUtils::convertByteArrayToHexString(data); + case Deconz::CommandMacBeacon: { + processMacBeacon(data); break; } default: @@ -1053,7 +1119,8 @@ QDebug operator<<(QDebug debug, const DeconzNetworkConfiguration &configuration) debug.nospace() << " - Node type:" << configuration.nodeType << "\n"; debug.nospace() << " - IEEE address: " << configuration.ieeeAddress.toString() << "\n"; debug.nospace() << " - NWK address: " << ZigbeeUtils::convertUint16ToHexString(configuration.shortAddress) << "\n"; - debug.nospace() << " - PAN ID: " << ZigbeeUtils::convertUint16ToHexString(configuration.panId) << "\n"; + debug.nospace() << " - PAN ID: " << ZigbeeUtils::convertUint16ToHexString(configuration.panId) << " (" << configuration.panId << ")\n"; + debug.nospace() << " - Use predefined network PAN ID: " << configuration.predefinedNetworkPanId << "\n"; debug.nospace() << " - Extended PAN ID: " << ZigbeeUtils::convertUint64ToHexString(configuration.extendedPanId) << "\n"; debug.nospace() << " - APS Extended PAN ID: " << ZigbeeUtils::convertUint64ToHexString(configuration.apsExtendedPanId) << "\n"; debug.nospace() << " - Trust center IEEE address: " << configuration.trustCenterAddress.toString() << "\n"; diff --git a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.h b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.h index 3fc7f32..088148d 100644 --- a/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.h +++ b/libnymea-zigbee/backends/deconz/zigbeebridgecontrollerdeconz.h @@ -54,6 +54,7 @@ typedef struct DeconzNetworkConfiguration { quint64 apsExtendedPanId = 0; // RW ZigbeeAddress trustCenterAddress; // RW Deconz::SecurityMode securityMode = Deconz::SecurityModeNoMasterButTrustCenterKey; // RW + bool predefinedNetworkPanId; // RW ZigbeeNetworkKey networkKey; // RW quint8 currentChannel = 0; // R quint16 protocolVersion = 0; // R @@ -85,6 +86,8 @@ public: void setFirmwareVersionString(const QString &firmwareVersion); Deconz::NetworkState networkState() const; + void rebootController(); + // Controllere requests ZigbeeInterfaceDeconzReply *requestVersion(); @@ -142,6 +145,8 @@ private: void processDeviceState(DeconzDeviceState deviceState); void processDataIndication(const QByteArray &data); void processDataConfirm(const QByteArray &data); + void processMacPoll(const QByteArray &data); + void processMacBeacon(const QByteArray &data); signals: void networkStateChanged(Deconz::NetworkState networkState); diff --git a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp index b7654ac..3748055 100644 --- a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp +++ b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp @@ -201,7 +201,8 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo case CreateNetworkStateWriteConfiguration: { // - Set coordinator // - Set channel mask - // - Set APS extended PANID (zero to reset) + // - Set predefined network PANID (0: let the firmware pick, 1: use the defined pan id) + // - Set NWK PANID // - Set trust center address (coordinator address) // - Set security mode // - Set network key @@ -236,76 +237,95 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo qCDebug(dcZigbeeNetwork()) << "Configured channel mask successfully. SQN:" << reply->sequenceNumber(); + + qCDebug(dcZigbeeNetwork()) << "Configure firmware to use predefined network PANID"; QByteArray paramData; QDataStream stream(¶mData, QIODevice::WriteOnly); - stream << static_cast(extendedPanId()); stream.setByteOrder(QDataStream::LittleEndian); - qCDebug(dcZigbeeNetwork()) << "Configure APS extended PANID" << extendedPanId(); - ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterApsExtendedPanId, paramData); + stream << static_cast(0x01); + ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterPredefinedNwkPanId, paramData); connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ if (reply->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterApsExtendedPanId << reply->statusCode(); + qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterPredefinedNwkPanId << reply->statusCode(); // FIXME: set an appropriate error return; } - qCDebug(dcZigbeeController()) << "Configured APS extended PANID successfully. SQN:" << reply->sequenceNumber(); + qCDebug(dcZigbeeController()) << "Configured firmware to use predefined network PNAID successfully. SQN:" << reply->sequenceNumber(); + + + qCDebug(dcZigbeeNetwork()) << "Configure network PANID" << panId() << ZigbeeUtils::convertUint16ToHexString(panId()); QByteArray paramData; QDataStream stream(¶mData, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); - stream << m_controller->networkConfiguration().ieeeAddress.toUInt64(); - qCDebug(dcZigbeeNetwork()) << "Configure trust center address" << m_controller->networkConfiguration().ieeeAddress.toString(); - ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterTrustCenterAddress, paramData); + stream << panId(); + ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterPanId, paramData); connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ if (reply->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterTrustCenterAddress << reply->statusCode(); + qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterPanId << reply->statusCode(); // FIXME: set an appropriate error return; } - qCDebug(dcZigbeeController()) << "Configured trust center address successfully. SQN:" << reply->sequenceNumber(); + qCDebug(dcZigbeeController()) << "Configured network PANID successfully. SQN:" << reply->sequenceNumber(); QByteArray paramData; QDataStream stream(¶mData, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); - stream << static_cast(Deconz::SecurityModeNoMasterButTrustCenterKey); - qCDebug(dcZigbeeNetwork()) << "Configure security mode" << Deconz::SecurityModeNoMasterButTrustCenterKey; - ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterSecurityMode, paramData); + stream << m_controller->networkConfiguration().ieeeAddress.toUInt64(); + qCDebug(dcZigbeeNetwork()) << "Configure trust center address" << m_controller->networkConfiguration().ieeeAddress.toString(); + ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterTrustCenterAddress, paramData); connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ if (reply->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterSecurityMode << reply->statusCode(); + qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterTrustCenterAddress << reply->statusCode(); // FIXME: set an appropriate error return; } - qCDebug(dcZigbeeController()) << "Configured security mode successfully. SQN:" << reply->sequenceNumber(); + qCDebug(dcZigbeeController()) << "Configured trust center address successfully. SQN:" << reply->sequenceNumber(); - - qCDebug(dcZigbeeNetwork()) << "Configure network key" << securityConfiguration().networkKey().toString(); - ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNetworkKey, securityConfiguration().networkKey().toByteArray()); + QByteArray paramData; + QDataStream stream(¶mData, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(Deconz::SecurityModeNoMasterButTrustCenterKey); + qCDebug(dcZigbeeNetwork()) << "Configure security mode" << Deconz::SecurityModeNoMasterButTrustCenterKey; + ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterSecurityMode, paramData); connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ if (reply->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterNetworkKey << reply->statusCode(); + qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterSecurityMode << reply->statusCode(); // FIXME: set an appropriate error - // Note: writing the network key fails all the time... - //return; - } else { - qCDebug(dcZigbeeController()) << "Configured network key successfully. SQN:" << reply->sequenceNumber(); + return; } - // Re-read the configurations - // Read all network parameters - ZigbeeInterfaceDeconzReply *reply = m_controller->readNetworkParameters(); + qCDebug(dcZigbeeController()) << "Configured security mode successfully. SQN:" << reply->sequenceNumber(); + + + qCDebug(dcZigbeeNetwork()) << "Configure network key" << securityConfiguration().networkKey().toString(); + ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNetworkKey, securityConfiguration().networkKey().toByteArray()); connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ if (reply->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up. SQN:" << reply->sequenceNumber() << reply->statusCode(); + qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterNetworkKey << reply->statusCode(); + // FIXME: set an appropriate error + // Note: writing the network key fails all the time... + //return; + } else { + qCDebug(dcZigbeeController()) << "Configured network key successfully. SQN:" << reply->sequenceNumber(); } - qCDebug(dcZigbeeController()) << m_controller->networkConfiguration(); + // Re-read the configurations + // Read all network parameters + ZigbeeInterfaceDeconzReply *reply = m_controller->readNetworkParameters(); + connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){ + if (reply->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up. SQN:" << reply->sequenceNumber() << reply->statusCode(); + } - // Configuration finished, lets start the network - setCreateNetworkState(CreateNetworkStateStartNetwork); + qCDebug(dcZigbeeController()) << m_controller->networkConfiguration(); + + // Configuration finished, lets start the network + setCreateNetworkState(CreateNetworkStateStartNetwork); + }); }); }); }); @@ -342,10 +362,15 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully. SQN:" << reply->sequenceNumber(); + qCDebug(dcZigbeeNetwork()) << "Network running with following configuration:"; + qCDebug(dcZigbeeNetwork()) << m_controller->networkConfiguration(); + setPanId(m_controller->networkConfiguration().panId); setExtendedPanId(m_controller->networkConfiguration().extendedPanId); setChannel(m_controller->networkConfiguration().currentChannel); + + setCreateNetworkState(CreateNetworkStateInitializeCoordinatorNode); }); break; @@ -545,8 +570,8 @@ void ZigbeeNetworkDeconz::startNetworkInternally() m_createNewNetwork = false; // Check if we have to create a pan ID and select the channel if (panId() == 0 || !m_coordinatorNode) { - qCDebug(dcZigbeeNetwork()) << "Generate new extended PAN ID..."; - setExtendedPanId(ZigbeeUtils::generateRandomPanId()); + setPanId(ZigbeeUtils::generateRandomPanId()); + qCDebug(dcZigbeeNetwork()) << "Generated new extended PAN ID" << panId() << ZigbeeUtils::convertUint16ToHexString(panId()); m_createNewNetwork = true; } @@ -595,8 +620,10 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout() m_controller->processDeviceState(m_controller->parseDeviceStateFlag(deviceStateFlag)); if (m_controller->networkState() == Deconz::NetworkStateOffline) { qCDebug(dcZigbeeNetwork()) << "Network stopped successfully for creation"; - // The network is now offline, continue with the state machine - setCreateNetworkState(CreateNetworkStateWriteConfiguration); + // The network is now offline, continue with the state machine in one second (some grace period after network shutdown) + QTimer::singleShot(1000, this, [=](){ + setCreateNetworkState(CreateNetworkStateWriteConfiguration); + }); } else { // Not offline yet, continue poll m_pollNetworkStateTimer->start(); @@ -701,7 +728,8 @@ void ZigbeeNetworkDeconz::stopNetwork() void ZigbeeNetworkDeconz::reset() { - // TODO + qCDebug(dcZigbeeNetwork()) << "Reboot the controller. The stack will perform a restart."; + m_controller->rebootController(); } void ZigbeeNetworkDeconz::factoryResetNetwork() diff --git a/libnymea-zigbee/zigbeeutils.cpp b/libnymea-zigbee/zigbeeutils.cpp index 0ec7267..040347e 100644 --- a/libnymea-zigbee/zigbeeutils.cpp +++ b/libnymea-zigbee/zigbeeutils.cpp @@ -290,10 +290,10 @@ QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId) return profileName; } -quint64 ZigbeeUtils::generateRandomPanId() +quint16 ZigbeeUtils::generateRandomPanId() { // Note: the PAN ID has to be between 0x0000 and 0x3fff - return static_cast(rand() % (0x3fff - 1) + 1); + return static_cast(rand() % (0x3fff - 1) + 1); } QPointF ZigbeeUtils::convertColorToXY(const QColor &color) diff --git a/libnymea-zigbee/zigbeeutils.h b/libnymea-zigbee/zigbeeutils.h index 800744d..c6af13d 100644 --- a/libnymea-zigbee/zigbeeutils.h +++ b/libnymea-zigbee/zigbeeutils.h @@ -69,7 +69,7 @@ public: static QString profileIdToString(const Zigbee::ZigbeeProfile &profileId); // Generate random data - static quint64 generateRandomPanId(); + static quint16 generateRandomPanId(); // Color converter