First version of deconz network start procedure and factory reset

This commit is contained in:
Simon Stürz 2020-04-07 15:41:24 +02:00
parent c9cdbb4413
commit 4472700160
27 changed files with 1185 additions and 156 deletions

View File

@ -714,11 +714,7 @@ DeconzDeviceState ZigbeeBridgeControllerDeconz::parseDeviceStateFlag(quint8 devi
void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceState)
{
qCDebug(dcZigbeeController()) << "Device state changed notification:" << deviceState.networkState
<< "ASPDE-DATA.confirm:" << deviceState.aspDataConfirm
<< "ASPDE-DATA.indication:" << deviceState.aspDataIndication
<< "configuration changed:" << deviceState.configurationChanged
<< "ASPDE-DATA.request free slots:" << deviceState.aspDataRequestFreeSlots;
qCDebug(dcZigbeeController()) << deviceState;
if (m_networkState != deviceState.networkState) {
qCDebug(dcZigbeeController()) << "Network state changed" << deviceState.networkState;
@ -729,13 +725,15 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
if (m_aspFreeSlotsAvailable != deviceState.aspDataRequestFreeSlots) {
m_aspFreeSlotsAvailable = deviceState.aspDataRequestFreeSlots;
// FIXME: if true, send next asp request
// FIXME: if changed to true, send next asp data request
}
if (m_networkState != Deconz::NetworkStateConnected)
return;
// Check if we have to fech new data
if (deviceState.aspDataConfirm) {
// Check if we have to read a data indication message
if (deviceState.aspDataIndication) {
ZigbeeInterfaceDeconzReply *reply = requestReadReceivedDataIndication();
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
@ -744,77 +742,133 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
return;
}
// ASP data indication received
QDataStream stream(reply->responseData());
stream.setByteOrder(QDataStream::LittleEndian);
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 destinationAddressModeFlag = 0;
quint16 destinationShortAddress = 0; quint64 destinationIeeeAddress = 0; quint8 destinationEndpoint = 0;
quint8 sourceAddressModeFlag = 0; quint16 sourceShortAddress = 0; quint64 sourceIeeeAddress = 0; quint8 sourceEndpoint = 0;
quint16 profileId = 0; quint16 clusterId = 0; quint16 asduLength = 0; QByteArray asdu; quint8 reserved = 0;
quint8 lqi = 0; qint8 rssi = 0;
stream >> payloadLenght >> deviceStateFlag >> destinationAddressModeFlag;
Zigbee::DestinationAddressMode destinationAddressMode = static_cast<Zigbee::DestinationAddressMode>(destinationAddressModeFlag);
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
stream >> destinationShortAddress;
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
stream >> destinationIeeeAddress;
stream >> destinationEndpoint >> sourceAddressModeFlag;
Zigbee::SourceAddressMode sourceAddressMode = static_cast<Zigbee::SourceAddressMode>(sourceAddressModeFlag);
if (sourceAddressMode == Zigbee::SourceAddressModeShortAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
stream >> sourceShortAddress;
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
stream >> sourceIeeeAddress;
stream >> sourceEndpoint >> profileId >> clusterId >> asduLength;
// Fill asdu data
for (int i = 0; i < asduLength; i++) {
quint8 byte = 0;
stream >> byte;
asdu.append(static_cast<char>(byte));
}
stream >> reserved >> reserved >> lqi >> reserved >> reserved >> reserved >> reserved >> rssi;
qCDebug(dcZigbeeController()) << "Data indication received:";
qCDebug(dcZigbeeController()) << " Destination address mode:" << destinationAddressMode;
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup)
qCDebug(dcZigbeeController()) << " Destination address (group):" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
if (destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
qCDebug(dcZigbeeController()) << " Destination short address:" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
qCDebug(dcZigbeeController()) << " Destination IEEE address:" << ZigbeeAddress(destinationIeeeAddress).toString();
qCDebug(dcZigbeeController()) << " Destination endpoint" << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
qCDebug(dcZigbeeController()) << " Source address mode:" << sourceAddressMode;
if (sourceAddressMode == Zigbee::SourceAddressModeShortAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
qCDebug(dcZigbeeController()) << " Source address:" << ZigbeeUtils::convertUint16ToHexString(sourceShortAddress);
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
qCDebug(dcZigbeeController()) << " Source IEEE address:" << ZigbeeAddress(sourceIeeeAddress).toString();
qCDebug(dcZigbeeController()) << " Source endpoint:" << ZigbeeUtils::convertByteToHexString(sourceEndpoint);
qCDebug(dcZigbeeController()) << " Profile:" << static_cast<Zigbee::ZigbeeProfile>(profileId);
qCDebug(dcZigbeeController()) << " Cluster:" << static_cast<Zigbee::ClusterId>(clusterId);
qCDebug(dcZigbeeController()) << " ASDU:" << ZigbeeUtils::convertByteArrayToHexString(asdu);
qCDebug(dcZigbeeController()) << " LQI:" << lqi;
qCDebug(dcZigbeeController()) << " RSSI:" << rssi << "dBm";
processDeviceState(parseDeviceStateFlag(deviceStateFlag));
// ASP data indication received, process the content
qCDebug(dcZigbeeController()) << "Reading data indication finished successfully";
processDataIndication(reply->responseData());
});
}
// Check if we have a response to read for a request
if (deviceState.aspDataConfirm) {
ZigbeeInterfaceDeconzReply *reply = requestQuerySendDataConfirm();
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not read data indication." << reply->statusCode();
// FIXME: set an appropriate error
return;
}
// ASP data indication received, process the content
qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully";
processDataConfirm(reply->responseData());
});
}
}
void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data)
{
// ASP data indication
QDataStream stream(data);
stream.setByteOrder(QDataStream::LittleEndian);
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 destinationAddressModeFlag = 0;
quint16 destinationShortAddress = 0; quint64 destinationIeeeAddress = 0; quint8 destinationEndpoint = 0;
quint8 sourceAddressModeFlag = 0; quint16 sourceShortAddress = 0; quint64 sourceIeeeAddress = 0; quint8 sourceEndpoint = 0;
quint16 profileId = 0; quint16 clusterId = 0; quint16 asduLength = 0; QByteArray asdu; quint8 reserved = 0;
quint8 lqi = 0; qint8 rssi = 0;
stream >> payloadLenght >> deviceStateFlag >> destinationAddressModeFlag;
Zigbee::DestinationAddressMode destinationAddressMode = static_cast<Zigbee::DestinationAddressMode>(destinationAddressModeFlag);
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
stream >> destinationShortAddress;
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
stream >> destinationIeeeAddress;
stream >> destinationEndpoint >> sourceAddressModeFlag;
Zigbee::SourceAddressMode sourceAddressMode = static_cast<Zigbee::SourceAddressMode>(sourceAddressModeFlag);
if (sourceAddressMode == Zigbee::SourceAddressModeShortAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
stream >> sourceShortAddress;
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
stream >> sourceIeeeAddress;
stream >> sourceEndpoint >> profileId >> clusterId >> asduLength;
// Fill asdu data
for (int i = 0; i < asduLength; i++) {
quint8 byte = 0;
stream >> byte;
asdu.append(static_cast<char>(byte));
}
stream >> reserved >> reserved >> lqi >> reserved >> reserved >> reserved >> reserved >> rssi;
// Print the information for debugging
qCDebug(dcZigbeeController()) << "Data indication received:";
qCDebug(dcZigbeeController()) << " Destination address mode:" << destinationAddressMode;
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup)
qCDebug(dcZigbeeController()) << " Destination address (group):" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
if (destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
qCDebug(dcZigbeeController()) << " Destination short address:" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
qCDebug(dcZigbeeController()) << " Destination IEEE address:" << ZigbeeAddress(destinationIeeeAddress).toString();
qCDebug(dcZigbeeController()) << " Destination endpoint" << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
qCDebug(dcZigbeeController()) << " Source address mode:" << sourceAddressMode;
if (sourceAddressMode == Zigbee::SourceAddressModeShortAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
qCDebug(dcZigbeeController()) << " Source address:" << ZigbeeUtils::convertUint16ToHexString(sourceShortAddress);
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
qCDebug(dcZigbeeController()) << " Source IEEE address:" << ZigbeeAddress(sourceIeeeAddress).toString();
qCDebug(dcZigbeeController()) << " Source endpoint:" << ZigbeeUtils::convertByteToHexString(sourceEndpoint);
qCDebug(dcZigbeeController()) << " Profile:" << static_cast<Zigbee::ZigbeeProfile>(profileId);
qCDebug(dcZigbeeController()) << " Cluster:" << static_cast<Zigbee::ClusterId>(clusterId);
qCDebug(dcZigbeeController()) << " ASDU:" << ZigbeeUtils::convertByteArrayToHexString(asdu);
qCDebug(dcZigbeeController()) << " LQI:" << lqi;
qCDebug(dcZigbeeController()) << " RSSI:" << rssi << "dBm";
processDeviceState(parseDeviceStateFlag(deviceStateFlag));
}
void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data)
{
QDataStream stream(data);
stream.setByteOrder(QDataStream::LittleEndian);
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 requestId = 0; quint8 destinationAddressMode = 0;
quint16 destinationShortAddress = 0; quint64 destinationIeeeAddress = 0; quint8 destinationEndpoint = 0;
quint8 sourceEndpoint = 0; quint8 zigbeeConfirmStatus = 0;
stream >> payloadLenght >> deviceStateFlag >> requestId >> destinationAddressMode;
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
stream >> destinationShortAddress;
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
stream >> destinationIeeeAddress;
stream >> destinationEndpoint >> sourceEndpoint >> zigbeeConfirmStatus;
// Print the information for debugging
qCDebug(dcZigbeeController()) << "Data confirm received: Request" << requestId;
qCDebug(dcZigbeeController()) << " Destination address mode:" << destinationAddressMode;
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup)
qCDebug(dcZigbeeController()) << " Destination address (group):" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
if (destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
qCDebug(dcZigbeeController()) << " Destination short address:" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
qCDebug(dcZigbeeController()) << " Destination IEEE address:" << ZigbeeAddress(destinationIeeeAddress).toString();
qCDebug(dcZigbeeController()) << " Destination endpoint" << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
qCDebug(dcZigbeeController()) << " Source endpoint" << ZigbeeUtils::convertByteToHexString(sourceEndpoint);
qCDebug(dcZigbeeController()) << " Confirm status" << static_cast<Zigbee::ZigbeeStatus>(zigbeeConfirmStatus);
}
void ZigbeeBridgeControllerDeconz::onInterfaceAvailableChanged(bool available)
@ -903,3 +957,28 @@ void ZigbeeBridgeControllerDeconz::disable()
{
m_interface->disable();
}
QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState)
{
debug.nospace() << "DeviceState(";
switch (deviceState.networkState) {
case Deconz::NetworkStateJoining:
debug.nospace() << "Joining, ";
break;
case Deconz::NetworkStateLeaving:
debug.nospace() << "Leaving, ";
break;
case Deconz::NetworkStateOffline:
debug.nospace() << "Offline, ";
break;
case Deconz::NetworkStateConnected:
debug.nospace() << "Connected, ";
break;
}
debug.nospace() << "Confirm=" << static_cast<int>(deviceState.aspDataConfirm) << ", ";
debug.nospace() << "Indication=" << static_cast<int>(deviceState.aspDataIndication) << ", ";
debug.nospace() << "ConfigChanged=" << static_cast<int>(deviceState.configurationChanged) << ", ";
debug.nospace() << "CanSend=" << deviceState.aspDataRequestFreeSlots << ")";
return debug.space();
}

View File

@ -70,8 +70,6 @@ typedef struct DeconzDeviceState {
bool aspDataRequestFreeSlots = false;
} DeconzDeviceState;
class ZigbeeBridgeControllerDeconz : public ZigbeeBridgeController
{
Q_OBJECT
@ -93,6 +91,7 @@ public:
ZigbeeInterfaceDeconzReply *requestWriteParameter(Deconz::Parameter parameter, const QByteArray &data);
ZigbeeInterfaceDeconzReply *requestChangeNetworkState(Deconz::NetworkState networkState);
// Receive data
ZigbeeInterfaceDeconzReply *requestReadReceivedDataIndication(Deconz::SourceAddressMode sourceAddressMode = Deconz::SourceAddressModeShortSourceAddress);
ZigbeeInterfaceDeconzReply *requestQuerySendDataConfirm();
@ -101,7 +100,6 @@ public:
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
private:
ZigbeeInterfaceDeconz *m_interface = nullptr;
quint8 m_sequenceNumber = 0;
@ -126,6 +124,9 @@ private:
DeconzDeviceState parseDeviceStateFlag(quint8 deviceStateFlag);
void processDeviceState(DeconzDeviceState deviceState);
void processDataIndication(const QByteArray &data);
void processDataConfirm(const QByteArray &data);
signals:
void networkStateChanged(Deconz::NetworkState networkState);
void networkConfigurationParameterChanged(const DeconzNetworkConfiguration &networkConfiguration);
@ -141,4 +142,7 @@ public slots:
void disable();
};
QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState);
#endif // ZIGBEEBRIDGECONTROLLERDECONZ_H

View File

@ -37,6 +37,11 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(QObject *parent) :
m_controller = new ZigbeeBridgeControllerDeconz(this);
//connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived);
connect(m_controller, &ZigbeeBridgeControllerDeconz::availableChanged, this, &ZigbeeNetworkDeconz::onControllerAvailableChanged);
m_pollNetworkStateTimer = new QTimer(this);
m_pollNetworkStateTimer->setInterval(1000);
m_pollNetworkStateTimer->setSingleShot(false);
connect(m_pollNetworkStateTimer, &QTimer::timeout, this, &ZigbeeNetworkDeconz::onPollNetworkStateTimeout);
}
ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const
@ -47,11 +52,194 @@ ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const
return nullptr;
}
void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state)
{
if (m_createState == state)
return;
m_createState = state;
qCDebug(dcZigbeeNetwork()) << "Create network state changed" << m_createState;
switch (m_createState) {
case CreateNetworkStateIdle:
break;
case CreateNetworkStateStopNetwork: {
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateOffline);
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not stop network for creating a new one." << reply->statusCode();
// FIXME: set an appropriate error
return;
}
// Start polling the device state, should be Online -> Leaving -> Offline
m_pollNetworkStateTimer->start();
});
break;
}
case CreateNetworkStateWriteConfiguration: {
// - Set coordinator
// - Set channel mask
// - Set APS extended PANID (zero to reset)
// - Set trust center address (coordinator address)
// - Set security mode
// - Set network key
QByteArray paramData;
QDataStream stream(&paramData, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(Deconz::NodeTypeCoordinator);
qCDebug(dcZigbeeNetwork()) << "Configure bridge to" << Deconz::NodeTypeCoordinator;
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNodeType, paramData);
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterNodeType << Deconz::NodeTypeCoordinator << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Configured successfully bridge to" << Deconz::NodeTypeCoordinator;
QByteArray paramData;
QDataStream stream(&paramData, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint32>(channelMask().toUInt32());
qCDebug(dcZigbeeNetwork()) << "Configure channel mask" << channelMask();
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterChannelMask, paramData);
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterChannelMask << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Configured channel mask successfully";
QByteArray paramData;
QDataStream stream(&paramData, QIODevice::WriteOnly);
stream << static_cast<quint64>(0);
stream.setByteOrder(QDataStream::LittleEndian);
qCDebug(dcZigbeeNetwork()) << "Configure APS extended PANID" << 0;
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterApsExtendedPanId, paramData);
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterApsExtendedPanId << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Configured APS extended PANID successfully";
QByteArray paramData;
QDataStream stream(&paramData, 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);
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterTrustCenterAddress << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Configured trust center address successfully";
QByteArray paramData;
QDataStream stream(&paramData, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(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" << Deconz::ParameterSecurityMode << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Configured security mode successfully";
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 write parameter" << Deconz::ParameterNetworkKey << reply->statusCode();
// FIXME: set an appropriate error
// Note: writing the network key fails all the time...
//return;
} else {
qCDebug(dcZigbeeNetwork()) << "Configured network key successfully";
}
// Configuration finished, lets start the network
setCreateNetworkState(CreateNetworkStateStartNetwork);
});
});
});
});
});
});
break;
}
case CreateNetworkStateStartNetwork: {
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateConnected);
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not start network for creating a new one." << reply->statusCode();
// FIXME: set an appropriate error
return;
}
// Start polling the device state, should be Online -> Leaving -> Offline
m_pollNetworkStateTimer->start();
});
break;
}
case CreateNetworkStateReadConfiguration: {
// 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." << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully.";
setPanId(m_controller->networkConfiguration().panId);
setExtendedPanId(m_controller->networkConfiguration().extendedPanId);
setChannel(m_controller->networkConfiguration().currentChannel);
setCreateNetworkState(CreateNetworkStateInitializeCoordinatorNode);
});
break;
}
case CreateNetworkStateInitializeCoordinatorNode: {
ZigbeeNodeDeconz *coordinatorNode = qobject_cast<ZigbeeNodeDeconz *>(createNode(this));
coordinatorNode->setShortAddress(m_controller->networkConfiguration().shortAddress);
coordinatorNode->setExtendedAddress(m_controller->networkConfiguration().ieeeAddress);
// TODO: done when when node initialized
m_coordinatorNode = coordinatorNode;
addNode(coordinatorNode);
setCreateNetworkState(CreateNetworkStateIdle);
setState(StateRunning);
//addUnitializedNode(coordinatorNode);
//coordinatorNode->startInitialization();
}
}
}
ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent)
{
//FIXME
Q_UNUSED(parent)
return nullptr;
return new ZigbeeNodeDeconz(m_controller, parent);
}
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
@ -64,11 +252,13 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
{
qCDebug(dcZigbeeNetwork()) << "Start network internally";
m_createNewNetwork = false;
// Check if we have to create a pan ID and select the channel
if (extendedPanId() == 0) {
if (panId() == 0) {
m_createNewNetwork = true;
setExtendedPanId(ZigbeeUtils::generateRandomPanId());
qCDebug(dcZigbeeNetwork()) << "Created new PAN ID:" << extendedPanId();
//setExtendedPanId(ZigbeeUtils::generateRandomPanId());
//qCDebug(dcZigbeeNetwork()) << "Created new PAN ID:" << extendedPanId();
}
if (securityConfiguration().networkKey().isNull()) {
@ -79,7 +269,7 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
}
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().networkKey() << "network link key";
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().globalTrustCenterLinkKey() << "global trust center link key";
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().globalTrustCenterLinkKey() << "global trust center link key";
// - Read the firmware version
@ -115,8 +305,8 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
}
qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully.";
QString protocolVersion = QString("%1.%2").arg(m_controller->networkConfiguration().protocolVersion & 0xFF00)
.arg(m_controller->networkConfiguration().protocolVersion & 0x00FF);
QString protocolVersion = QString("%1.%2").arg(m_controller->networkConfiguration().protocolVersion >> 8 & 0xFF)
.arg(m_controller->networkConfiguration().protocolVersion & 0xFF);
m_controller->setFirmwareVersionString(QString("%1 - %2").arg(firmwareVersion).arg(protocolVersion));
@ -137,39 +327,31 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
m_controller->processDeviceState(m_controller->parseDeviceStateFlag(deviceStateFlag));
if (m_createNewNetwork) {
// Write the configurations which need to be changed
createNetwork();
// Initialize coordinator node
setCreateNetworkState(CreateNetworkStateStopNetwork);
} else {
// Get the network state and start the network if required
if (m_controller->networkState() == Deconz::NetworkStateConnected) {
qCDebug(dcZigbeeNetwork()) << "The network is already running.";
setState(StateRunning);
}
}
});
});
});
}
void ZigbeeNetworkDeconz::createNetwork()
{
// Set offline
setCreateNetworkState(CreateNetworkStateStopNetwork);
// Write configurations
// Set online
// Read configurations
// Create and initialize coordinator node
}
void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available)
@ -190,6 +372,76 @@ void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available)
}
}
void ZigbeeNetworkDeconz::onPollNetworkStateTimeout()
{
// Stop the timer and make the request
m_pollNetworkStateTimer->stop();
switch (m_createState) {
case CreateNetworkStateStopNetwork: {
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not read device state during network start up." << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
QDataStream stream(reply->responseData());
stream.setByteOrder(QDataStream::LittleEndian);
quint8 deviceStateFlag = 0;
stream >> deviceStateFlag;
// Update the device state in the controller
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);
} else {
// Not offline yet, continue poll
m_pollNetworkStateTimer->start();
}
});
break;
}
case CreateNetworkStateStartNetwork: {
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
qCWarning(dcZigbeeController()) << "Could not read device state during network start up." << reply->statusCode();
// FIXME: set an appropriate error
return;
}
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
QDataStream stream(reply->responseData());
stream.setByteOrder(QDataStream::LittleEndian);
quint8 deviceStateFlag = 0;
stream >> deviceStateFlag;
// Update the device state in the controller
m_controller->processDeviceState(m_controller->parseDeviceStateFlag(deviceStateFlag));
if (m_controller->networkState() == Deconz::NetworkStateConnected) {
// The network is now online, continue with the state machine
setCreateNetworkState(CreateNetworkStateReadConfiguration);
} else if (m_controller->networkState() == Deconz::NetworkStateOffline) {
qCWarning(dcZigbeeNetwork()) << "Failed to start the network.";
setCreateNetworkState(CreateNetworkStateIdle);
setState(StateOffline);
setError(ErrorZigbeeError);
return;
} else {
// Not offline yet, continue poll
m_pollNetworkStateTimer->start();
}
});
break;
}
default:
break;
}
}
void ZigbeeNetworkDeconz::startNetwork()
{
loadNetwork();
@ -231,5 +483,9 @@ void ZigbeeNetworkDeconz::reset()
void ZigbeeNetworkDeconz::factoryResetNetwork()
{
// Wipe settings, and reconfigure network
qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone.";
clearSettings();
setState(StateUninitialized);
qCDebug(dcZigbeeNetwork()) << "The factory reset is finished. Start restart with a fresh network.";
startNetwork();
}

View File

@ -29,7 +29,9 @@
#define ZIGBEENETWORKDECONZ_H
#include <QObject>
#include "zigbeenetwork.h"
#include "zigbeenodedeconz.h"
#include "zigbeechannelmask.h"
#include "zigbeebridgecontrollerdeconz.h"
@ -37,17 +39,34 @@ class ZigbeeNetworkDeconz : public ZigbeeNetwork
{
Q_OBJECT
public:
enum CreateNetworkState {
CreateNetworkStateIdle,
CreateNetworkStateStopNetwork,
CreateNetworkStateWriteConfiguration,
CreateNetworkStateStartNetwork,
CreateNetworkStateReadConfiguration,
CreateNetworkStateInitializeCoordinatorNode
};
Q_ENUM(CreateNetworkState)
explicit ZigbeeNetworkDeconz(QObject *parent = nullptr);
ZigbeeBridgeController *bridgeController() const override;
private:
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
bool m_networkRunning = false;
CreateNetworkState m_createState = CreateNetworkStateIdle;
bool m_createNewNetwork = false;
QTimer *m_pollNetworkStateTimer = nullptr;
void setCreateNetworkState(CreateNetworkState state);
protected:
ZigbeeNode *createNode(QObject *parent) override;
void setPermitJoiningInternal(bool permitJoining) override;
void startNetworkInternally();
@ -56,6 +75,7 @@ protected:
private slots:
void onControllerAvailableChanged(bool available);
void onPollNetworkStateTimeout();
public slots:
void startNetwork() override;

View File

@ -27,8 +27,42 @@
#include "zigbeenodedeconz.h"
ZigbeeNodeDeconz::ZigbeeNodeDeconz(QObject *parent) :
ZigbeeNode(parent)
ZigbeeNodeDeconz::ZigbeeNodeDeconz(ZigbeeBridgeControllerDeconz *controller, QObject *parent) :
ZigbeeNode(parent),
m_controller(controller)
{
}
void ZigbeeNodeDeconz::leaveNetworkRequest(bool rejoin, bool removeChildren)
{
Q_UNUSED(rejoin)
Q_UNUSED(removeChildren)
}
void ZigbeeNodeDeconz::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report)
{
Q_UNUSED(report)
}
void ZigbeeNodeDeconz::startInitialization()
{
/* Node initialisation steps (sequentially)
* - Node descriptor
* - Power descriptor
* - Active endpoints
* - for each endpoint do:
* - Simple descriptor request
* - for each endpoint
* - read basic cluster
*/
}
ZigbeeNodeEndpoint *ZigbeeNodeDeconz::createNodeEndpoint(quint8 endpointId, QObject *parent)
{
Q_UNUSED(endpointId)
Q_UNUSED(parent)
return nullptr;
}

View File

@ -32,6 +32,7 @@
#include "zigbee.h"
#include "zigbeenode.h"
#include "zigbeebridgecontrollerdeconz.h"
class ZigbeeNodeDeconz : public ZigbeeNode
{
@ -40,9 +41,21 @@ class ZigbeeNodeDeconz : public ZigbeeNode
friend class ZigbeeNetworkDeconz;
public:
explicit ZigbeeNodeDeconz(QObject *parent = nullptr);
explicit ZigbeeNodeDeconz(ZigbeeBridgeControllerDeconz *controller, QObject *parent = nullptr);
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
private:
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
protected:
void startInitialization() override;
ZigbeeNodeEndpoint *createNodeEndpoint(quint8 endpointId, QObject *parent) override;
private slots:
signals:
};

View File

@ -23,6 +23,8 @@ SOURCES += \
zigbeechannelmask.cpp \
zigbeecluster.cpp \
zigbeeclusterattribute.cpp \
zigbeedeviceobject.cpp \
zigbeedeviceprofile.cpp \
zigbeemanufacturer.cpp \
zigbeenetwork.cpp \
zigbeenetworkkey.cpp \
@ -30,6 +32,7 @@ SOURCES += \
zigbee.cpp \
loggingcategory.cpp \
zigbeenetworkreply.cpp \
zigbeenetworkrequest.cpp \
zigbeenodeendpoint.cpp \
zigbeesecurityconfiguration.cpp \
zigbeeutils.cpp \
@ -57,6 +60,8 @@ HEADERS += \
zigbeechannelmask.h \
zigbeecluster.h \
zigbeeclusterattribute.h \
zigbeedeviceobject.h \
zigbeedeviceprofile.h \
zigbeemanufacturer.h \
zigbeenetwork.h \
zigbeenetworkkey.h \
@ -64,6 +69,7 @@ HEADERS += \
zigbee.h \
loggingcategory.h \
zigbeenetworkreply.h \
zigbeenetworkrequest.h \
zigbeenodeendpoint.h \
zigbeesecurityconfiguration.h \
zigbeeutils.h \

View File

@ -41,6 +41,7 @@ class Zigbee
public:
enum ZigbeeProfile {
ZigbeeProfileDevice = 0x0000,
ZigbeeProfileIndustrialPlantMonitoring = 0x0101,
ZigbeeProfileHomeAutomation = 0x0104,
ZigbeeProfileCommercialBuildingAutomation = 0x0105,

View File

@ -111,6 +111,6 @@ bool ZigbeeAddress::operator!=(const ZigbeeAddress &other) const
QDebug operator<<(QDebug debug, const ZigbeeAddress &address)
{
debug << address.toString();
return debug;
debug.nospace() << address.toString();
return debug.space();
}

View File

@ -32,25 +32,44 @@ ZigbeeAdpu::ZigbeeAdpu(QObject *parent) : QObject(parent)
}
quint8 ZigbeeAdpu::buildFrameControl(ZigbeeAdpu::FrameType frameType, ZigbeeAdpu::DeliveryMode deliveryMode, bool apsAckFormat, bool securitySubField, bool acknowledgementRequest, bool extendedHeaderPresent)
ZigbeeAdpu::FrameControl ZigbeeAdpu::frameControl() const
{
quint8 frameControl = 0;
frameControl &= static_cast<quint8>(frameType); // Bit 0 - 1
frameControl &= static_cast<quint8>(deliveryMode); // Bit 2 - 3
if (apsAckFormat)
frameControl &= static_cast<quint8>(0x08); // Bit 4
return m_frameControl;
}
if (securitySubField)
frameControl &= static_cast<quint8>(0x04); // Bit 5
void ZigbeeAdpu::setFrameControl(ZigbeeAdpu::FrameControl frameControl)
{
m_frameControl = frameControl;
}
if (securitySubField)
frameControl &= static_cast<quint8>(0x04); // Bit 6
quint8 ZigbeeAdpu::buildFrameControlByte(FrameControl frameControl)
{
quint8 frameControlByte = 0;
frameControlByte |= static_cast<quint8>(frameControl.frameType); // Bit 0 - 1
frameControlByte |= static_cast<quint8>(frameControl.deliveryMode); // Bit 2 - 3
if (frameControl.apsAckFormat)
frameControlByte |= static_cast<quint8>(0x10); // Bit 4
if (acknowledgementRequest)
frameControl &= static_cast<quint8>(0x02); // Bit 7
if (frameControl.security)
frameControlByte |= static_cast<quint8>(0x20); // Bit 5
if (extendedHeaderPresent)
frameControl &= static_cast<quint8>(0x01); // Bit 8
if (frameControl.acknowledgementRequest)
frameControlByte |= static_cast<quint8>(0x40); // Bit 6
if (frameControl.extendedHeader)
frameControlByte |= static_cast<quint8>(0x80); // Bit 7
return frameControlByte;
}
ZigbeeAdpu::FrameControl ZigbeeAdpu::readFrameControlByte(quint8 frameControlByte)
{
FrameControl frameControl;
frameControl.frameType = static_cast<FrameType>(frameControlByte | 0x03);
frameControl.deliveryMode = static_cast<DeliveryMode>(frameControlByte | 0x0C);
frameControl.apsAckFormat = frameControlByte | 0x10;
frameControl.security = frameControlByte | 0x20;
frameControl.acknowledgementRequest = frameControlByte | 0x40;
frameControl.extendedHeader = frameControlByte | 0x80;
return frameControl;
}

View File

@ -30,39 +30,60 @@
#include <QObject>
typedef struct FrameControl {
} FrameControl;
class ZigbeeAdpu : public QObject
{
Q_OBJECT
public:
// Note: zigbee Pro Specification 2.2.5.1 General APDU Frame Format
/* Frame control */
enum FrameType {
FrameTypeData = 0x00,
FrameTypeCommand = 0x40,
FrameTypeAck = 0x80,
FrameTypeInterPanAps = 0xC0
FrameTypeCommand = 0x01,
FrameTypeAck = 0x02,
FrameTypeInterPanAps = 0x03
};
Q_ENUM(FrameType)
enum DeliveryMode {
DeliveryModeNormalUnicast = 0x00,
DeliveryModeBroadcast = 0x20,
DeliveryModeGroupAddressing = 0x30,
DeliveryModeBroadcast = 0x08,
DeliveryModeGroupAddressing = 0x0C,
};
Q_ENUM(DeliveryMode)
typedef struct FrameControl {
FrameType frameType = FrameTypeData;
DeliveryMode deliveryMode = DeliveryModeNormalUnicast;
bool security = false;
bool apsAckFormat = false;
bool acknowledgementRequest = true;
bool extendedHeader = false;
} FrameControl;
explicit ZigbeeAdpu(QObject *parent = nullptr);
quint8 buildFrameControl(FrameType frameType, DeliveryMode deliveryMode, bool apsAckFormat, bool securitySubField, bool acknowledgementRequest, bool extendedHeaderPresent);
FrameControl frameControl() const;
void setFrameControl(FrameControl frameControl);
quint8 destinationEndpoint() const;
void setDestinationEndpoint(quint8 destinationEndpoint);
quint16 groupAddress() const;
void setGroupAddress(quint16 groupAddress);
quint16 clusterId() const;
void setClusterId(quint16 clusterId);
private:
FrameControl m_frameControl;
quint8 m_destinationEndpoint;
quint8 buildFrameControlByte(FrameControl frameControl);
FrameControl readFrameControlByte(quint8 frameControlByte);
signals:
};

View File

@ -54,6 +54,60 @@ Zigbee::ZigbeeChannels ZigbeeChannelMask::channels() const
return static_cast<Zigbee::ZigbeeChannels>(m_channelMask);
}
QList<int> ZigbeeChannelMask::channelArray() const
{
QList<int> array;
if (channels().testFlag(Zigbee::ZigbeeChannel11))
array.append(11);
if (channels().testFlag(Zigbee::ZigbeeChannel12))
array.append(12);
if (channels().testFlag(Zigbee::ZigbeeChannel13))
array.append(13);
if (channels().testFlag(Zigbee::ZigbeeChannel14))
array.append(14);
if (channels().testFlag(Zigbee::ZigbeeChannel15))
array.append(15);
if (channels().testFlag(Zigbee::ZigbeeChannel16))
array.append(16);
if (channels().testFlag(Zigbee::ZigbeeChannel17))
array.append(17);
if (channels().testFlag(Zigbee::ZigbeeChannel18))
array.append(18);
if (channels().testFlag(Zigbee::ZigbeeChannel19))
array.append(19);
if (channels().testFlag(Zigbee::ZigbeeChannel20))
array.append(20);
if (channels().testFlag(Zigbee::ZigbeeChannel21))
array.append(21);
if (channels().testFlag(Zigbee::ZigbeeChannel22))
array.append(22);
if (channels().testFlag(Zigbee::ZigbeeChannel23))
array.append(23);
if (channels().testFlag(Zigbee::ZigbeeChannel24))
array.append(24);
if (channels().testFlag(Zigbee::ZigbeeChannel25))
array.append(25);
if (channels().testFlag(Zigbee::ZigbeeChannel26))
array.append(26);
return array;
}
bool ZigbeeChannelMask::isSet(Zigbee::ZigbeeChannel channel) const
{
return channels().testFlag(channel);
@ -90,17 +144,7 @@ bool ZigbeeChannelMask::operator!=(const ZigbeeChannelMask &other) const
QDebug operator<<(QDebug debug, const ZigbeeChannelMask &channelMaks)
{
debug.nospace() << "ChannelMask(" << ZigbeeUtils::convertUint32ToHexString(channelMaks.toUInt32());
debug.nospace() << ", [";
for (int i = 11; i <= 25; i++) {
if (channelMaks.isSet(static_cast<Zigbee::ZigbeeChannel>(i))) {
if (i < 25) {
debug.nospace() << i << ", ";
} else {
debug.nospace() << i;
}
}
}
debug.nospace() << "])";
debug.nospace() << ", " << channelMaks.channelArray();
debug.nospace() << ")";
return debug.space();
}

View File

@ -53,6 +53,8 @@ public:
Zigbee::ZigbeeChannels channels() const;
QList<int> channelArray() const;
bool isSet(Zigbee::ZigbeeChannel channel) const;
void setChannel(Zigbee::ZigbeeChannel channel);
void unsetChannel(Zigbee::ZigbeeChannel channel);

View File

@ -0,0 +1,33 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zigbeedeviceobject.h"
ZigbeeDeviceObject::ZigbeeDeviceObject(QObject *parent) : QObject(parent)
{
}

View File

@ -0,0 +1,43 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEEDEVICEOBJECT_H
#define ZIGBEEDEVICEOBJECT_H
#include <QObject>
class ZigbeeDeviceObject : public QObject
{
Q_OBJECT
public:
explicit ZigbeeDeviceObject(QObject *parent = nullptr);
signals:
};
#endif // ZIGBEEDEVICEOBJECT_H

View File

@ -0,0 +1,28 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zigbeedeviceprofile.h"

View File

@ -0,0 +1,144 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEEDEVICEPROFILE_H
#define ZIGBEEDEVICEPROFILE_H
#include <QObject>
class ZigbeeDeviceProfile
{
Q_GADGET
public:
enum ZdoCommand {
/* Requests */
/*Device and service discovery */
NetworkAddressRequest = 0x0000,
IeeeAddressRequest = 0x0001,
NodeDescriptorRequest = 0x0002,
PowerDescriptorRequest = 0x0003,
SimpleDescriptorRequest = 0x0004,
ActiveEndpointsRequest = 0x0005,
MatchDescriptorsRequest = 0x0006,
ComplexDescriptorRequest = 0x0010,
UserDescriptorRequest = 0x0011,
DiscoveryCacheRequest = 0x0012,
DeviceAnnounce = 0x0013,
UserDescriptorSet = 0x0014,
SystemServerDiscoveryRequest = 0x0015,
DiscoveryStoreRequest = 0x0016,
NodeDescriptorStoreRequest = 0x0017,
PowerDescriptorStoreRequest = 0x0018,
ActiveEndpointStoreRequest = 0x0019,
SimpleDescriptorStoreRequest = 0x001A,
RemoveNodeCacheRequest = 0x001B,
FindNodeCacheRequest = 0x001C,
ExtendedSimpleDescriptorRequest = 0x001D,
ExtendedActiveEndpointRequest = 0x001E,
ParentAnnounceRequest = 0x001F,
/* Binding */
EndDeviceBindRequest = 0x0020,
BindRequest = 0x0021,
UnbindRequest = 0x0022,
BindRegisterRequest = 0x0023,
ReplaceDeviceRequest = 0x0024,
StoreBackupBindEntryRequest = 0x0025,
RemoveBackupBindEntryRequest = 0x0026,
BackupBindTableRequest = 0x0027,
RecoverBindTableRequest = 0x0028,
BackupSourceBindRequest = 0x0029,
RecoverSourceBindRequest = 0x002A,
/* Network management */
MgmtNetworkDiscoveryRequest = 0x0030,
MgmtLqiRequest = 0x0031,
MgmtRoutingTableRequest = 0x0032,
MgmtBindRequest = 0x0033,
MgmtLeaveRequest = 0x0034,
MgmtDirectJoinRequest = 0x0035,
MgmtPermitJoinRequest = 0x0036,
MgmtCacheRequest = 0x0037,
MgmtNetworkUpdateRequest = 0x0038,
/* Responses */
/*Device and service discovery */
NetworkAddressResponse = 0x8000,
IeeeAddressResponse = 0x8001,
NodeDescriptorResponse = 0x8002,
PowerDescriptorResponse = 0x8003,
SimpleDescriptorResponse = 0x8004,
ActiveEndpointsResponse = 0x8005,
MatchDescriptorsResponse = 0x8006,
ComplexDescriptorResponse = 0x8010,
UserDescriptorResponse = 0x8011,
DiscoveryCacheResponse = 0x8012,
UserDescriptorSetResponse = 0x8014,
SystemServerDiscoveryResponse = 0x8015,
DiscoveryStoreResponse = 0x8016,
NodeDescriptorStoreResponse = 0x8017,
PowerDescriptorStoreResponse = 0x8018,
ActiveEndpointStoreResponse = 0x8019,
SimpleDescriptorStoreResponse = 0x801A,
RemoveNodeCacheResponse = 0x801B,
FindNodeCacheResponse = 0x801C,
ExtendedSimpleDescriptorResponse = 0x801D,
ExtendedActiveEndpointResponse = 0x801E,
ParentAnnounceRespone = 0x801F,
/* Binding */
EndDeviceBindResponse = 0x8020,
BindResponse = 0x8021,
UnbindResponse = 0x8022,
BindRegisterResponse = 0x8023,
ReplaceDeviceResponse = 0x8024,
StoreBackupBindEntryResponse = 0x8025,
RemoveBackupBindEntryResponse = 0x8026,
BackupBindTableResponse = 0x8027,
RecoverBindTableResponse = 0x8028,
BackupSourceBindResponse = 0x8029,
RecoverSourceBindResponse = 0x802A,
/* Network management */
MgmtNetworkDiscoveryResponse = 0x8030,
MgmtLqiResponse = 0x8031,
MgmtRoutingTableResponse = 0x8032,
MgmtBindResponse = 0x8033,
MgmtLeaveResponse = 0x8034,
MgmtDirectJoinResponse = 0x8035,
MgmtPermitJoinResponse = 0x8036,
MgmtCacheResponse = 0x8037,
MgmtNetworkUpdateResponse = 0x8038
};
};
#endif // ZIGBEEDEVICEPROFILE_H

View File

@ -87,6 +87,20 @@ void ZigbeeNetwork::setSerialBaudrate(qint32 baudrate)
emit serialBaudrateChanged(m_serialBaudrate);
}
quint16 ZigbeeNetwork::panId()
{
return m_panId;
}
void ZigbeeNetwork::setPanId(quint16 panId)
{
if (m_panId == panId)
return;
m_panId = panId;
emit panIdChanged(m_panId);
}
quint64 ZigbeeNetwork::extendedPanId() const
{
return m_extendedPanId;
@ -243,7 +257,7 @@ void ZigbeeNetwork::saveNetwork()
qCDebug(dcZigbeeNetwork()) << "Save current network configuration to" << m_settingsFileName;
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
settings.beginGroup("Network");
settings.setValue("panId", extendedPanId());
settings.setValue("panId", panId());
settings.setValue("channel", channel());
settings.setValue("networkKey", securityConfiguration().networkKey().toString());
settings.setValue("trustCenterLinkKey", securityConfiguration().globalTrustCenterLinkKey().toString());
@ -260,8 +274,8 @@ void ZigbeeNetwork::loadNetwork()
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
settings.beginGroup("Network");
quint64 extendedPanId = static_cast<quint64>(settings.value("panId", 0).toULongLong());
setExtendedPanId(extendedPanId);
quint16 panId = static_cast<quint16>(settings.value("panId", 0).toUInt());
setPanId(panId);
setChannel(settings.value("channel", 0).toUInt());
ZigbeeNetworkKey netKey(settings.value("networkKey", QString()).toString());
if (netKey.isValid())
@ -420,6 +434,11 @@ void ZigbeeNetwork::removeNodeFromSettings(ZigbeeNode *node)
void ZigbeeNetwork::addNode(ZigbeeNode *node)
{
qCDebug(dcZigbeeNetwork()) << "Add node" << node;
if (hasNode(node->extendedAddress())) {
qCWarning(dcZigbeeNetwork()) << "Not adding node to the system since already added" << node;
return;
}
addNodeInternally(node);
saveNode(node);
}

View File

@ -76,6 +76,9 @@ public:
void setSerialBaudrate(qint32 baudrate);
// Network configurations
quint16 panId();
void setPanId(quint16 panId);
quint64 extendedPanId() const;
void setExtendedPanId(quint64 extendedPanId);
@ -109,6 +112,7 @@ private:
qint32 m_serialBaudrate = 115200;
// Network configurations
quint16 m_panId = 0;
quint64 m_extendedPanId = 0;
quint32 m_channel = 0;
ZigbeeChannelMask m_channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels);
@ -151,6 +155,7 @@ signals:
void serialPortNameChanged(const QString &serialPortName);
void serialBaudrateChanged(qint32 serialBaudrate);
void panIdChanged(quint16 panId);
void extendedPanIdChanged(quint64 extendedPanId);
void channelChanged(uint channel);
void channelMaskChanged(const ZigbeeChannelMask &channelMask);

View File

@ -32,12 +32,19 @@ ZigbeeNetworkReply::Error ZigbeeNetworkReply::error() const
return m_error;
}
ZigbeeNetworkRequest ZigbeeNetworkReply::request() const
{
return m_request;
}
Zigbee::ZigbeeStatus ZigbeeNetworkReply::zigbeeStatus() const
{
return m_zigbeeStatus;
}
ZigbeeNetworkReply::ZigbeeNetworkReply(QObject *parent) : QObject(parent)
ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) :
QObject(parent),
m_request(request)
{
}

View File

@ -31,6 +31,7 @@
#include <QObject>
#include "zigbee.h"
#include "zigbeenetworkrequest.h"
class ZigbeeNetworkReply : public QObject
{
@ -48,10 +49,13 @@ public:
Q_ENUM(Error)
Error error() const;
ZigbeeNetworkRequest request() const;
Zigbee::ZigbeeStatus zigbeeStatus() const;
private:
explicit ZigbeeNetworkReply(QObject *parent = nullptr);
explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr);
ZigbeeNetworkRequest m_request;
bool m_finished = false;
Error m_error = ErrorNoError;
Zigbee::ZigbeeStatus m_zigbeeStatus = Zigbee::ZigbeeStatusSuccess;

View File

@ -0,0 +1,143 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zigbeenetworkrequest.h"
ZigbeeNetworkRequest::ZigbeeNetworkRequest()
{
}
quint8 ZigbeeNetworkRequest::requestId() const
{
return m_requestId;
}
void ZigbeeNetworkRequest::setRequestId(quint8 requestId)
{
m_requestId = requestId;
}
Zigbee::DestinationAddressMode ZigbeeNetworkRequest::destinationAddressMode() const
{
return m_destinationAddressMode;
}
void ZigbeeNetworkRequest::setDestinationAddressMode(Zigbee::DestinationAddressMode destinationAddressMode)
{
m_destinationAddressMode = destinationAddressMode;
}
quint16 ZigbeeNetworkRequest::destinationShortAddress() const
{
return m_destinationShortAddress;
}
void ZigbeeNetworkRequest::setDestinationShortAddress(quint16 destinationShortAddress)
{
m_destinationShortAddress = destinationShortAddress;
}
ZigbeeAddress ZigbeeNetworkRequest::destinationIeeeAddress() const
{
return m_destinationIeeeAddress;
}
void ZigbeeNetworkRequest::setDestinationIeeeAddress(const ZigbeeAddress &destinationIeeeAddress)
{
m_destinationIeeeAddress = destinationIeeeAddress;
}
quint8 ZigbeeNetworkRequest::destinationEndpoint() const
{
return m_destinationEndpoint;
}
void ZigbeeNetworkRequest::setDestinationEndpoint(quint8 destinationEndpoint)
{
m_destinationEndpoint = destinationEndpoint;
}
quint16 ZigbeeNetworkRequest::profileId() const
{
return m_profileId;
}
void ZigbeeNetworkRequest::setProfileId(quint16 profileId)
{
m_profileId = profileId;
}
quint16 ZigbeeNetworkRequest::clusterId() const
{
return m_clusterId;
}
void ZigbeeNetworkRequest::setClusterId(quint16 clusterId)
{
m_clusterId = clusterId;
}
quint8 ZigbeeNetworkRequest::sourceEndpoint() const
{
return m_sourceEndpoint;
}
void ZigbeeNetworkRequest::setSourceEndpoint(quint8 sourceEndpoint)
{
m_sourceEndpoint = sourceEndpoint;
}
QByteArray ZigbeeNetworkRequest::asdu() const
{
return m_asdu;
}
void ZigbeeNetworkRequest::setAsdu(const QByteArray &asdu)
{
m_asdu = asdu;
}
Zigbee::ZigbeeTxOptions ZigbeeNetworkRequest::txOptions() const
{
return m_txOptions;
}
void ZigbeeNetworkRequest::setTxOptions(Zigbee::ZigbeeTxOptions txOptions)
{
m_txOptions = txOptions;
}
quint8 ZigbeeNetworkRequest::radius() const
{
return m_radius;
}
void ZigbeeNetworkRequest::setRadius(quint8 radius)
{
m_radius = radius;
}

View File

@ -0,0 +1,88 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea-zigbee.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation; version 3.
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEENETWORKREQUEST_H
#define ZIGBEENETWORKREQUEST_H
#include <QObject>
#include "zigbee.h"
#include "zigbeeaddress.h"
class ZigbeeNetworkRequest
{
public:
ZigbeeNetworkRequest();
quint8 requestId() const;
void setRequestId(quint8 requestId);
Zigbee::DestinationAddressMode destinationAddressMode() const;
void setDestinationAddressMode(Zigbee::DestinationAddressMode destinationAddressMode);
quint16 destinationShortAddress() const;
void setDestinationShortAddress(quint16 destinationShortAddress);
ZigbeeAddress destinationIeeeAddress() const;
void setDestinationIeeeAddress(const ZigbeeAddress &destinationIeeeAddress);
quint8 destinationEndpoint() const;
void setDestinationEndpoint(quint8 destinationEndpoint);
quint16 profileId() const;
void setProfileId(quint16 profileId);
quint16 clusterId() const;
void setClusterId(quint16 clusterId);
quint8 sourceEndpoint() const;
void setSourceEndpoint(quint8 sourceEndpoint);
QByteArray asdu() const;
void setAsdu(const QByteArray &asdu);
Zigbee::ZigbeeTxOptions txOptions() const;
void setTxOptions(Zigbee::ZigbeeTxOptions txOptions);
quint8 radius() const;
void setRadius(quint8 radius);
private:
quint8 m_requestId = 0;
Zigbee::DestinationAddressMode m_destinationAddressMode = Zigbee::DestinationAddressModeShortAddress;
quint16 m_destinationShortAddress = 0;
ZigbeeAddress m_destinationIeeeAddress;
quint8 m_destinationEndpoint = 0;
quint16 m_profileId = 0;
quint16 m_clusterId = 0;
quint8 m_sourceEndpoint = 0;
QByteArray m_asdu;
Zigbee::ZigbeeTxOptions m_txOptions = Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission);
quint8 m_radius = 0;
};
#endif // ZIGBEENETWORKREQUEST_H

View File

@ -155,9 +155,9 @@ void ZigbeeNodeEndpoint::addOutputCluster(ZigbeeCluster *cluster)
m_outputClusters.insert(cluster->clusterId(), cluster);
}
ZigbeeNetworkReply *ZigbeeNodeEndpoint::createNetworkReply()
ZigbeeNetworkReply *ZigbeeNodeEndpoint::createNetworkReply(const ZigbeeNetworkRequest &request)
{
ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(this);
ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(request, this);
// Make sure the reply will be deleted
connect(reply, &ZigbeeNetworkReply::finished, reply, &ZigbeeNetworkReply::deleteLater);
return reply;

View File

@ -131,7 +131,7 @@ protected:
void addOutputCluster(ZigbeeCluster *cluster);
// Network reply methods
ZigbeeNetworkReply *createNetworkReply();
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError, Zigbee::ZigbeeStatus zigbeeStatus = Zigbee::ZigbeeStatusSuccess);
signals:

View File

@ -173,6 +173,11 @@ QByteArray ZigbeeUtils::convertBitArrayToByteArray(const QBitArray &bitArray)
return byteArray;
}
bool ZigbeeUtils::checkBitUint8(const quint8 &value, const int &bitNumber)
{
return value & (1 << bitNumber);
}
bool ZigbeeUtils::checkBitUint16(const quint16 &value, const int &bitNumber)
{
return value & (1 << bitNumber);

View File

@ -38,6 +38,16 @@
#include "zigbee.h"
#include "zigbeecluster.h"
template<class TYPE> inline TYPE ZigbeeBit(const TYPE & x)
{
return TYPE(1) << x;
}
template<class TYPE> inline bool ZigbeeIsBitSet(const TYPE & x, const TYPE & y)
{
return (x & y) != 0;
}
class ZigbeeUtils
{
Q_GADGET
@ -46,6 +56,7 @@ public:
// Data utils
QBitArray convertByteArrayToBitArray(const QByteArray &byteArray);
QByteArray convertBitArrayToByteArray(const QBitArray &bitArray);
static bool checkBitUint8(const quint8 &value, const int &bitNumber);
static bool checkBitUint16(const quint16 &value, const int &bitNumber);
static quint16 convertByteArrayToUint16(const QByteArray &data);