Add zigbee uart monitor

This commit is contained in:
Simon Stürz 2020-10-28 16:53:07 +01:00
parent 5e2426165c
commit 097254756e
10 changed files with 352 additions and 112 deletions

18
debian/control vendored
View File

@ -7,12 +7,13 @@ Homepage: https://nymea.io
Vcs-Git: https://github.com/nymea/nymea-zigbee.git Vcs-Git: https://github.com/nymea/nymea-zigbee.git
Build-Depends: debhelper (>= 9.0.0), Build-Depends: debhelper (>= 9.0.0),
dpkg-dev (>= 1.16.1~), dpkg-dev (>= 1.16.1~),
pkg-config,
qt5-default, qt5-default,
qt5-qmake, qt5-qmake,
qtbase5-dev, qtbase5-dev,
qtbase5-dev-tools, qtbase5-dev-tools,
libqt5serialport5-dev, libqt5serialport5-dev,
libreadline-dev libudev-dev
Package: libnymea-zigbee1 Package: libnymea-zigbee1
Section: libs Section: libs
@ -22,8 +23,8 @@ Depends: ${shlibs:Depends},
libqt5network5, libqt5network5,
libqt5gui5, libqt5gui5,
libqt5serialport5 libqt5serialport5
Description: Qt 5 based library for Zigbee Description: Qt 5 based library for ZigBee
Qt 5 based library for Zigbee. Qt 5 based library for ZigBee.
Package: libnymea-zigbee-dev Package: libnymea-zigbee-dev
@ -31,9 +32,10 @@ Section: libdevel
Architecture: any Architecture: any
Depends: libnymea-zigbee1 (= ${binary:Version}), Depends: libnymea-zigbee1 (= ${binary:Version}),
${shlibs:Depends}, ${shlibs:Depends},
${misc:Depends} ${misc:Depends},
Description: Qt 5 based library for Zigbee - development files pkg-config
Development files for Qt 5 based Zigbee library. Dscription: Qt 5 based library for ZigBee - development files
Development files for Qt 5 based ZigBee library.
Package: libnymea-zigbee1-dbg Package: libnymea-zigbee1-dbg
@ -43,5 +45,5 @@ Section: debug
Depends: libnymea-zigbee1 (= ${binary:Version}), Depends: libnymea-zigbee1 (= ${binary:Version}),
${shlibs:Depends}, ${shlibs:Depends},
${misc:Depends} ${misc:Depends}
Description: Qt 5 based library for Zigbee - debug symbols Description: Qt 5 based library for ZigBee - debug symbols
Debug Symbols for Qt 5 based Zigbee library. Debug Symbols for Qt 5 based ZigBee library.

View File

@ -3,6 +3,9 @@ include(../config.pri)
TARGET = nymea-zigbee1 TARGET = nymea-zigbee1
TEMPLATE = lib TEMPLATE = lib
CONFIG += link_pkgconfig
PKGCONFIG += libudev
SOURCES += \ SOURCES += \
backends/deconz/interface/zigbeeinterfacedeconz.cpp \ backends/deconz/interface/zigbeeinterfacedeconz.cpp \
backends/deconz/interface/zigbeeinterfacedeconzreply.cpp \ backends/deconz/interface/zigbeeinterfacedeconzreply.cpp \
@ -31,7 +34,6 @@ SOURCES += \
zdo/zigbeedeviceobject.cpp \ zdo/zigbeedeviceobject.cpp \
zdo/zigbeedeviceobjectreply.cpp \ zdo/zigbeedeviceobjectreply.cpp \
zdo/zigbeedeviceprofile.cpp \ zdo/zigbeedeviceprofile.cpp \
zigbeeadapter.cpp \
zigbeeadpu.cpp \ zigbeeadpu.cpp \
zigbeebridgecontroller.cpp \ zigbeebridgecontroller.cpp \
zigbeechannelmask.cpp \ zigbeechannelmask.cpp \
@ -47,17 +49,11 @@ SOURCES += \
zigbeenetworkrequest.cpp \ zigbeenetworkrequest.cpp \
zigbeenodeendpoint.cpp \ zigbeenodeendpoint.cpp \
zigbeesecurityconfiguration.cpp \ zigbeesecurityconfiguration.cpp \
zigbeeuartadapter.cpp \
zigbeeuartadaptermonitor.cpp \
zigbeeutils.cpp \ zigbeeutils.cpp \
zigbeenode.cpp \ zigbeenode.cpp \
zigbeeaddress.cpp \ zigbeeaddress.cpp
# nxp/interface/zigbeeinterface.cpp \
# nxp/interface/zigbeeinterfacemessage.cpp \
# nxp/interface/zigbeeinterfacerequest.cpp \
# nxp/interface/zigbeeinterfacereply.cpp \
# nxp/zigbeenetworknxp.cpp \
# nxp/zigbeebridgecontrollernxp.cpp \
# nxp/zigbeenodeendpointnxp.cpp \
# nxp/zigbeenodenxp.cpp \
HEADERS += \ HEADERS += \
backends/deconz/interface/deconz.h \ backends/deconz/interface/deconz.h \
@ -89,7 +85,6 @@ HEADERS += \
zdo/zigbeedeviceobject.h \ zdo/zigbeedeviceobject.h \
zdo/zigbeedeviceobjectreply.h \ zdo/zigbeedeviceobjectreply.h \
zdo/zigbeedeviceprofile.h \ zdo/zigbeedeviceprofile.h \
zigbeeadapter.h \
zigbeeadpu.h \ zigbeeadpu.h \
zigbeebridgecontroller.h \ zigbeebridgecontroller.h \
zigbeechannelmask.h \ zigbeechannelmask.h \
@ -105,17 +100,11 @@ HEADERS += \
zigbeenetworkrequest.h \ zigbeenetworkrequest.h \
zigbeenodeendpoint.h \ zigbeenodeendpoint.h \
zigbeesecurityconfiguration.h \ zigbeesecurityconfiguration.h \
zigbeeuartadapter.h \
zigbeeuartadaptermonitor.h \
zigbeeutils.h \ zigbeeutils.h \
zigbeenode.h \ zigbeenode.h \
zigbeeaddress.h \ zigbeeaddress.h
# nxp/interface/zigbeeinterface.h \
# nxp/interface/zigbeeinterfacemessage.h \
# nxp/interface/zigbeeinterfacerequest.h \
# nxp/interface/zigbeeinterfacereply.h \
# nxp/zigbeenetworknxp.h \
# nxp/zigbeebridgecontrollernxp.h \
# nxp/zigbeenodeendpointnxp.h \
# nxp/zigbeenodenxp.h \
# install header file with relative subdirectory # install header file with relative subdirectory
for (header, HEADERS) { for (header, HEADERS) {

View File

@ -35,6 +35,7 @@ Q_LOGGING_CATEGORY(dcZigbeeEndpoint, "ZigbeeEndpoint")
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface") Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController") Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject") Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject")
Q_LOGGING_CATEGORY(dcZigbeeAdapterMonitor, "ZigbeeAdapterMonitor")
Q_LOGGING_CATEGORY(dcZigbeeClusterLibrary, "ZigbeeClusterLibrary") Q_LOGGING_CATEGORY(dcZigbeeClusterLibrary, "ZigbeeClusterLibrary")
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase") Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic") Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")

View File

@ -39,6 +39,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcZigbeeEndpoint)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeAdapterMonitor)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeClusterLibrary) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeClusterLibrary)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)

View File

@ -32,58 +32,6 @@
#include "backends/deconz/zigbeenetworkdeconz.h" #include "backends/deconz/zigbeenetworkdeconz.h"
#include <QDateTime> #include <QDateTime>
#include <QSerialPortInfo>
QList<ZigbeeAdapter> ZigbeeNetworkManager::availableAdapters()
{
QList<ZigbeeAdapter> adapters;
qCDebug(dcZigbeeNetwork()) << "Loading available adapters" ;
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
qCDebug(dcZigbeeNetwork()) << "Adapter candidate" << serialPortInfo.portName();
qCDebug(dcZigbeeNetwork()) << " Description:" << serialPortInfo.description();
qCDebug(dcZigbeeNetwork()) << " System location:" << serialPortInfo.systemLocation();
qCDebug(dcZigbeeNetwork()) << " Manufacturer:" << serialPortInfo.manufacturer();
qCDebug(dcZigbeeNetwork()) << " Serialnumber:" << serialPortInfo.serialNumber();
if (serialPortInfo.hasProductIdentifier()) {
qCDebug(dcZigbeeNetwork()) << " Product identifier:" << serialPortInfo.productIdentifier();
}
if (serialPortInfo.hasVendorIdentifier()) {
qCDebug(dcZigbeeNetwork()) << " Vendor identifier:" << serialPortInfo.vendorIdentifier();
}
// Check if we recognize this controller
ZigbeeAdapter adapter;
if (serialPortInfo.portName().isEmpty()) {
adapter.setName("Zigbee adapter");
} else {
adapter.setName(serialPortInfo.portName());
}
if (serialPortInfo.description().isEmpty()) {
adapter.setDescription("Unknown");
} else {
adapter.setDescription(serialPortInfo.description());
}
adapter.setSystemLocation(serialPortInfo.systemLocation());
// Check if we recognize this adapter from USB information
if (serialPortInfo.manufacturer().toLower().contains("dresden elektronik")) {
adapter.setBackendSuggestionAvailable(true);
adapter.setSuggestedZigbeeBackendType(Zigbee::ZigbeeBackendTypeDeconz);
adapter.setSuggestedBaudRate(38400);
} else if (serialPortInfo.manufacturer().toLower().contains("nxp")) {
adapter.setBackendSuggestionAvailable(true);
adapter.setSuggestedZigbeeBackendType(Zigbee::ZigbeeBackendTypeNxp);
adapter.setSuggestedBaudRate(115200);
}
adapters.append(adapter);
}
return adapters;
}
QStringList ZigbeeNetworkManager::availableZigbeeBackendTypes() QStringList ZigbeeNetworkManager::availableZigbeeBackendTypes()
{ {

View File

@ -30,14 +30,14 @@
#include <QObject> #include <QObject>
#include "zigbeeadapter.h" #include "zigbeeuartadapter.h"
#include "zigbeenetwork.h" #include "zigbeenetwork.h"
class ZigbeeNetworkManager class ZigbeeNetworkManager
{ {
Q_GADGET Q_GADGET
public: public:
static QList<ZigbeeAdapter> availableAdapters();
static QStringList availableZigbeeBackendTypes(); static QStringList availableZigbeeBackendTypes();
static ZigbeeNetwork *createZigbeeNetwork(Zigbee::ZigbeeBackendType backend, QObject *parent = nullptr); static ZigbeeNetwork *createZigbeeNetwork(Zigbee::ZigbeeBackendType backend, QObject *parent = nullptr);
}; };

View File

@ -25,76 +25,76 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zigbeeadapter.h" #include "zigbeeuartadapter.h"
ZigbeeAdapter::ZigbeeAdapter() ZigbeeUartAdapter::ZigbeeUartAdapter()
{ {
} }
QString ZigbeeAdapter::name() const QString ZigbeeUartAdapter::name() const
{ {
return m_name; return m_name;
} }
void ZigbeeAdapter::setName(const QString &name) void ZigbeeUartAdapter::setName(const QString &name)
{ {
m_name = name; m_name = name;
} }
QString ZigbeeAdapter::description() const QString ZigbeeUartAdapter::description() const
{ {
return m_description; return m_description;
} }
void ZigbeeAdapter::setDescription(const QString &description) void ZigbeeUartAdapter::setDescription(const QString &description)
{ {
m_description = description; m_description = description;
} }
QString ZigbeeAdapter::systemLocation() const QString ZigbeeUartAdapter::systemLocation() const
{ {
return m_systemLocation; return m_systemLocation;
} }
void ZigbeeAdapter::setSystemLocation(const QString &systemLocation) void ZigbeeUartAdapter::setSystemLocation(const QString &systemLocation)
{ {
m_systemLocation = systemLocation; m_systemLocation = systemLocation;
} }
bool ZigbeeAdapter::backendSuggestionAvailable() const bool ZigbeeUartAdapter::backendSuggestionAvailable() const
{ {
return m_backendSuggestionAvailable; return m_backendSuggestionAvailable;
} }
void ZigbeeAdapter::setBackendSuggestionAvailable(bool backendSuggestionAvailable) void ZigbeeUartAdapter::setBackendSuggestionAvailable(bool backendSuggestionAvailable)
{ {
m_backendSuggestionAvailable = backendSuggestionAvailable; m_backendSuggestionAvailable = backendSuggestionAvailable;
} }
Zigbee::ZigbeeBackendType ZigbeeAdapter::suggestedZigbeeBackendType() const Zigbee::ZigbeeBackendType ZigbeeUartAdapter::suggestedZigbeeBackendType() const
{ {
return m_suggestedZigbeeBackendType; return m_suggestedZigbeeBackendType;
} }
void ZigbeeAdapter::setSuggestedZigbeeBackendType(Zigbee::ZigbeeBackendType backendType) void ZigbeeUartAdapter::setSuggestedZigbeeBackendType(Zigbee::ZigbeeBackendType backendType)
{ {
m_suggestedZigbeeBackendType = backendType; m_suggestedZigbeeBackendType = backendType;
} }
qint32 ZigbeeAdapter::suggestedBaudRate() const qint32 ZigbeeUartAdapter::suggestedBaudRate() const
{ {
return m_suggestedBaudRate; return m_suggestedBaudRate;
} }
void ZigbeeAdapter::setSuggestedBaudRate(qint32 baudRate) void ZigbeeUartAdapter::setSuggestedBaudRate(qint32 baudRate)
{ {
m_suggestedBaudRate = baudRate; m_suggestedBaudRate = baudRate;
} }
QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter) QDebug operator<<(QDebug debug, const ZigbeeUartAdapter &adapter)
{ {
debug.nospace() << "ZigbeeAdapter(" << adapter.name() << " - " << adapter.description(); debug.nospace() << "ZigbeeUartAdapter(" << adapter.name() << " - " << adapter.description();
debug.nospace() << ", " << adapter.systemLocation(); debug.nospace() << ", " << adapter.systemLocation();
if (adapter.backendSuggestionAvailable()) { if (adapter.backendSuggestionAvailable()) {
debug.nospace() << "Suggested backend: " << adapter.suggestedZigbeeBackendType(); debug.nospace() << "Suggested backend: " << adapter.suggestedZigbeeBackendType();

View File

@ -25,26 +25,18 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEEADAPTER_H #ifndef ZIGBEEUARTADAPTER_H
#define ZIGBEEADAPTER_H #define ZIGBEEUARTADAPTER_H
#include <QObject> #include <QString>
#include <QDebug> #include <QDebug>
#include "zigbee.h" #include "zigbee.h"
class ZigbeeAdapter class ZigbeeUartAdapter
{ {
Q_GADGET
Q_PROPERTY(QString name READ name)
Q_PROPERTY(QString description READ description)
Q_PROPERTY(QString systemLocation READ systemLocation)
Q_PROPERTY(bool backendSuggestionAvailable READ backendSuggestionAvailable)
Q_PROPERTY(Zigbee::ZigbeeBackendType suggestedZigbeeBackendType READ suggestedZigbeeBackendType)
Q_PROPERTY(qint32 suggestedBaudRate READ suggestedBaudRate)
public: public:
explicit ZigbeeAdapter(); explicit ZigbeeUartAdapter();
QString name() const; QString name() const;
void setName(const QString &name); void setName(const QString &name);
@ -74,7 +66,9 @@ private:
qint32 m_suggestedBaudRate = 38400; qint32 m_suggestedBaudRate = 38400;
}; };
QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter); Q_DECLARE_METATYPE(ZigbeeUartAdapter)
QDebug operator<<(QDebug debug, const ZigbeeUartAdapter &adapter);
#endif // ZIGBEEADAPTER_H #endif // ZIGBEEADAPTER_H

View File

@ -0,0 +1,241 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 "zigbeeuartadaptermonitor.h"
#include "loggingcategory.h"
#include <QSerialPortInfo>
ZigbeeUartAdapterMonitor::ZigbeeUartAdapterMonitor(QObject *parent) : QObject(parent)
{
qRegisterMetaType<ZigbeeUartAdapter>();
m_udev = udev_new();
if (!m_udev) {
qCWarning(dcZigbeeAdapterMonitor()) << "Could not initialize udev for the adapter monitor";
return;
}
// Read initially all tty devices
struct udev_enumerate *enumerate = udev_enumerate_new(m_udev);
if (!enumerate) {
qCWarning(dcZigbeeAdapterMonitor()) << "Could not create udev enumerate for initial device reading for the adapter monitor.";
udev_unref(m_udev);
m_udev = nullptr;
return;
}
udev_enumerate_add_match_subsystem(enumerate, "tty");
if (udev_enumerate_scan_devices(enumerate) < 0) {
qCWarning(dcZigbeeAdapterMonitor()) << "Failed to scan devices from udev enumerate.";
udev_enumerate_unref(enumerate);
enumerate = nullptr;
udev_unref(m_udev);
m_udev = nullptr;
return;
}
qCDebug(dcZigbeeAdapterMonitor()) << "Load initial list of available serial ports...";
struct udev_list_entry *devices = nullptr;
devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *dev_list_entry = nullptr;
udev_list_entry_foreach(dev_list_entry, devices) {
struct udev_device *device = nullptr;
const char *path;
path = udev_list_entry_get_name(dev_list_entry);
device = udev_device_new_from_syspath(m_udev, path);
// Print properties
struct udev_list_entry *properties = udev_device_get_properties_list_entry(device);
struct udev_list_entry *property_list_entry = nullptr;
udev_list_entry_foreach(property_list_entry, properties) {
qCDebug(dcZigbeeAdapterMonitor()) << " - Property" << udev_list_entry_get_name(property_list_entry) << udev_list_entry_get_value(property_list_entry);
}
QString devicePath = QString::fromLatin1(udev_device_get_property_value(device,"DEVNAME"));
QString manufacturerString = QString::fromLatin1(udev_device_get_property_value(device,"ID_VENDOR_ENC"));
QString descriptionString = QString::fromLatin1(udev_device_get_property_value(device,"ID_MODEL_ENC"));
QString serialNumberString = QString::fromLatin1(udev_device_get_property_value(device, "ID_SERIAL_SHORT"));
// Clean up this device since we have all information
udev_device_unref(device);
qCDebug(dcZigbeeAdapterMonitor()) << "[+]" << devicePath << manufacturerString << descriptionString << serialNumberString;
addAdapterInternally(devicePath);
}
udev_enumerate_unref(enumerate);
enumerate = nullptr;
// Create udev monitor
m_monitor = udev_monitor_new_from_netlink(m_udev, "udev");
if (!m_monitor) {
qCWarning(dcZigbeeAdapterMonitor()) << "Could not initialize udev monitor.";
udev_unref(m_udev);
m_udev = nullptr;
return;
}
// Set monitor filter to tty subsystem
if (udev_monitor_filter_add_match_subsystem_devtype(m_monitor, "tty", nullptr) < 0) {
qCWarning(dcZigbeeAdapterMonitor()) << "Could not set subsystem device type filter to tty.";
udev_monitor_unref(m_monitor);
m_monitor = nullptr;
udev_unref(m_udev);
m_udev = nullptr;
return;
}
// Enable the monitor
if (udev_monitor_enable_receiving(m_monitor) < 0) {
qCWarning(dcZigbeeAdapterMonitor()) << "Could not enable udev monitor.";
udev_monitor_unref(m_monitor);
m_monitor = nullptr;
udev_unref(m_udev);
m_udev = nullptr;
return;
}
// Create socket notifier for read
int socketDescriptor = udev_monitor_get_fd(m_monitor);
m_notifier = new QSocketNotifier(socketDescriptor, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated, this, [this, socketDescriptor](int socket){
// Make sure the socket matches
if (socketDescriptor != socket) {
qCWarning(dcZigbeeAdapterMonitor()) << "socket != socketdescriptor";
return;
}
// Create udev device
udev_device *device = udev_monitor_receive_device(m_monitor);
if (!device) {
qCWarning(dcZigbeeAdapterMonitor()) << "Got socket sotification but could not read device information.";
return;
}
QString actionString = QString::fromLatin1(udev_device_get_action(device));
QString devicePath = QString::fromLatin1(udev_device_get_property_value(device,"DEVNAME"));
QString manufacturerString = QString::fromLatin1(udev_device_get_property_value(device,"ID_VENDOR_ENC"));
QString descriptionString = QString::fromLatin1(udev_device_get_property_value(device,"ID_MODEL_ENC"));
QString serialNumberString = QString::fromLatin1(udev_device_get_property_value(device, "ID_SERIAL_SHORT"));
// Clean udev device
udev_device_unref(device);
// Make sure we know the action
if (actionString.isEmpty())
return;
if (actionString == "add") {
qCDebug(dcZigbeeAdapterMonitor()) << "[+]" << devicePath << serialNumberString;
if (!m_availableAdapters.contains(devicePath)) {
addAdapterInternally(devicePath);
}
}
if (actionString == "remove") {
qCDebug(dcZigbeeAdapterMonitor()) << "[-]" << devicePath << serialNumberString;
if (m_availableAdapters.contains(devicePath)) {
ZigbeeUartAdapter adapter = m_availableAdapters.take(devicePath);
qCDebug(dcZigbeeAdapterMonitor()) << "Removed" << adapter;
emit adapterRemoved(adapter);
}
}
});
m_notifier->setEnabled(true);
m_isValid = true;
}
QList<ZigbeeUartAdapter> ZigbeeUartAdapterMonitor::availableAdapters() const
{
return m_availableAdapters.values();
}
bool ZigbeeUartAdapterMonitor::isValid() const
{
return m_isValid;
}
void ZigbeeUartAdapterMonitor::addAdapterInternally(const QString &systemLocation)
{
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
if (serialPortInfo.systemLocation() != systemLocation)
continue;
if (m_availableAdapters.keys().contains(systemLocation)) {
qCWarning(dcZigbeeAdapterMonitor()) << "The adapter" << systemLocation << "has already been added to the monitor.";
continue;
}
qCDebug(dcZigbeeAdapterMonitor()) << "Adapter candidate" << serialPortInfo.portName();
qCDebug(dcZigbeeAdapterMonitor()) << " Description:" << serialPortInfo.description();
qCDebug(dcZigbeeAdapterMonitor()) << " System location:" << serialPortInfo.systemLocation();
qCDebug(dcZigbeeAdapterMonitor()) << " Manufacturer:" << serialPortInfo.manufacturer();
qCDebug(dcZigbeeAdapterMonitor()) << " Serialnumber:" << serialPortInfo.serialNumber();
if (serialPortInfo.hasProductIdentifier()) {
qCDebug(dcZigbeeAdapterMonitor()) << " Product identifier:" << serialPortInfo.productIdentifier();
}
if (serialPortInfo.hasVendorIdentifier()) {
qCDebug(dcZigbeeAdapterMonitor()) << " Vendor identifier:" << serialPortInfo.vendorIdentifier();
}
// Check if we recognize this controller
ZigbeeUartAdapter adapter;
if (serialPortInfo.portName().isEmpty()) {
adapter.setName("Zigbee adapter");
} else {
adapter.setName(serialPortInfo.portName());
}
if (serialPortInfo.description().isEmpty()) {
adapter.setDescription("Unknown");
} else {
adapter.setDescription(serialPortInfo.description());
}
adapter.setSystemLocation(serialPortInfo.systemLocation());
// Check if we recognize this adapter from USB information
if (serialPortInfo.manufacturer().toLower().contains("dresden elektronik")) {
adapter.setBackendSuggestionAvailable(true);
adapter.setSuggestedZigbeeBackendType(Zigbee::ZigbeeBackendTypeDeconz);
adapter.setSuggestedBaudRate(38400);
} else if (serialPortInfo.manufacturer().toLower().contains("nxp")) {
adapter.setBackendSuggestionAvailable(true);
adapter.setSuggestedZigbeeBackendType(Zigbee::ZigbeeBackendTypeNxp);
adapter.setSuggestedBaudRate(115200);
}
qCDebug(dcZigbeeAdapterMonitor()) << "Added" << adapter;
m_availableAdapters.insert(adapter.systemLocation(), adapter);
emit adapterAdded(adapter);
}
}

View File

@ -0,0 +1,64 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 ZIGBEEUARTADAPTERMONITOR_H
#define ZIGBEEUARTADAPTERMONITOR_H
#include <QObject>
#include <QSocketNotifier>
#include <libudev.h>
#include "zigbeeuartadapter.h"
class ZigbeeUartAdapterMonitor : public QObject
{
Q_OBJECT
public:
explicit ZigbeeUartAdapterMonitor(QObject *parent = nullptr);
QList<ZigbeeUartAdapter> availableAdapters() const;
bool isValid() const;
private:
bool m_isValid = false;
struct udev *m_udev = nullptr;
struct udev_monitor *m_monitor = nullptr;
QSocketNotifier *m_notifier = nullptr;
QHash<QString, ZigbeeUartAdapter> m_availableAdapters;
void addAdapterInternally(const QString &systemLocation);
signals:
void adapterAdded(const ZigbeeUartAdapter &adapter);
void adapterRemoved(const ZigbeeUartAdapter &adapter);
};
#endif // ZIGBEEUARTADAPTERMONITOR_H