add final qtavahi lib

This commit is contained in:
Simon Stürz 2016-05-04 18:05:43 +02:00 committed by Michael Zanetti
parent 0b03786d13
commit fb91f05b15
42 changed files with 1133 additions and 805 deletions

1
debian/changelog vendored
View File

@ -1,6 +1,7 @@
guh (0.7.2) xenial; urgency=medium
* Add Avahi support
* Add guh-plugins-maker package
-- Simon Stürz <simon.stuerz@guh.guru> Thu, 28 Apr 2016 14:56:17 +0200

14
debian/control vendored
View File

@ -142,3 +142,17 @@ Description: Plugins for guh IoT server - 6LoWPAN Merkur boards
for your environment. This package contains plugins for the 6LoWPAN Merkur
board.
Package: guh-plugins-maker
Section: libs
Architecture: any
Depends: libguh1 (= ${binary:Version}),
guhd (= ${binary:Version}),
${shlibs:Depends},
${misc:Depends}
Description: Plugins for guh IoT server - for maker, tinker and hackers
guh is an open source IoT (Internet of Things) server,
which allows to control a lot of different devices from many different
manufacturers. With the powerful rule engine you are able to connect any
device available in the system and create individual scenes and behaviors
for your environment. This package contains plugins for the 6LoWPAN Merkur
board.

6
debian/copyright vendored
View File

@ -17,12 +17,6 @@ Copyright: (C) 2014 Michael Zanetti <michael_zanetti@gmx.net>
2014 Simon Stürz <stuerz.simon@gmail.com>
License: GPL-2+
Files: libguh/avahi/zconf*
Copyright: (c) 2012 Johannes Hilden
2016 Simon Stürz <stuerz.simon@gmail.com>
License: LGPL-2.1
Files: libguh/avahi/qt-watch*
Copyright: (c) avahi
2016 Simon Stürz <stuerz.simon@gmail.com>

1
debian/guh-plugins-maker.dirs vendored Normal file
View File

@ -0,0 +1 @@
usr/lib/guh/plugins

5
debian/guh-plugins-maker.install vendored Normal file
View File

@ -0,0 +1,5 @@
usr/lib/guh/plugins/libguh_devicepluginavahimonitor.so
usr/lib/guh/plugins/libguh_devicepluginlircd.so
usr/lib/guh/plugins/libguh_devicepluginwifidetector.so
usr/lib/guh/plugins/libguh_deviceplugincommandlauncher.so
usr/lib/guh/plugins/libguh_devicepluginudpcommander.so

View File

@ -3,21 +3,16 @@ usr/lib/guh/plugins/libguh_devicepluginelro.so
usr/lib/guh/plugins/libguh_deviceplugineq3.so
usr/lib/guh/plugins/libguh_devicepluginintertechno.so
usr/lib/guh/plugins/libguh_devicepluginlgsmarttv.so
usr/lib/guh/plugins/libguh_devicepluginlircd.so
usr/lib/guh/plugins/libguh_devicepluginmailnotification.so
usr/lib/guh/plugins/libguh_devicepluginopenweathermap.so
usr/lib/guh/plugins/libguh_devicepluginphilipshue.so
usr/lib/guh/plugins/libguh_devicepluginwakeonlan.so
usr/lib/guh/plugins/libguh_devicepluginwemo.so
usr/lib/guh/plugins/libguh_devicepluginwifidetector.so
usr/lib/guh/plugins/libguh_deviceplugindatetime.so
usr/lib/guh/plugins/libguh_deviceplugincommandlauncher.so
usr/lib/guh/plugins/libguh_devicepluginunitec.so
usr/lib/guh/plugins/libguh_devicepluginleynew.so
usr/lib/guh/plugins/libguh_devicepluginudpcommander.so
usr/lib/guh/plugins/libguh_devicepluginkodi.so
usr/lib/guh/plugins/libguh_devicepluginelgato.so
usr/lib/guh/plugins/libguh_devicepluginawattar.so
usr/lib/guh/plugins/libguh_devicepluginnetatmo.so
usr/lib/guh/plugins/libguh_deviceplugindenon.so

12
debian/guhd.1 vendored
View File

@ -1,6 +1,6 @@
.\" Manpage for guhd.
.\" Contact simon.stuerz@guh.guru to correct errors or typos.
.TH man 1 "January 2016" "1.4" "guhd man page"
.TH man 1 "May 2016" "1.5" "guhd man page"
.SH NAME
guhd \- An open source IoT (Internet of Things) server
.SH SYNOPSIS
@ -36,19 +36,21 @@ categories will be printed unless they are explicitly muted with "NoWarnings".
\fBMain\ debug\ categories:\fR
.IP \fIApplication\fR\ (default\ enabled)
Print the debug messages from the core application.
.IP \fIAvahi\fR\ (default\ disabled)
Print the debug messages from the avahi resource.
.IP \fIConnection\fR\ (default\ enabled)
Print the debug messages from the TCP connections in guh.
.IP \fIDeviceManager\fR\ (default\ enabled)
Print the debug messages from the device manager.
.IP \fIHardware\fR\ (default\ disabled)
Print the debug messages from hardware resources in guh.
.IP \fIJsonRpc\fR\ (default\ enabled)
.IP \fIJsonRpc\fR\ (default\ disabled)
Print the debug messages from JSON-RPC API.
.IP \fILogEngine\fR\ (default\ disabled)
Print the debug messages from logging engine.
.IP \fIOAuth2\fR\ (default\ disabled)
Print the debug messages of the OAuth2 resource.
.IP \fIRest\fR\ (default\ enabled)
.IP \fIRest\fR\ (default\ disabled)
Print the debug messages from REST API.
.IP \fIRuleEngine\fR\ (default\ enabled)
Print the debug messages from the rule engine.
@ -56,9 +58,9 @@ Print the debug messages from the rule engine.
Print the debug messages from the TCP server.
.IP \fIWarning\fR\ (default\ enabled)
Print warnings.
.IP \fIWebServer\fR\ (default\ enabled)
.IP \fIWebServer\fR\ (default\ disabled)
Print the debug messages from the web server.
.IP \fIWebSocketServer\fR\ (default\ enabled)
.IP \fIWebSocketServer\fR\ (default\ disabled)
Print the debug messages from the websocket server.
.TP
\fBDebug\ categories\ for\ plugins:\fR

View File

@ -206,7 +206,6 @@ DeviceManager::DeviceManager(QObject *parent) :
m_radio433 = new Radio433(this);
m_radio433->enable();
// TODO: error handling if no Radio433 detected (GPIO or network), disable radio433 plugins or something...
m_networkManager = new NetworkManager(this);
connect(m_networkManager, &NetworkManager::replyReady, this, &DeviceManager::replyReady);
@ -216,6 +215,10 @@ DeviceManager::DeviceManager(QObject *parent) :
connect(m_upnpDiscovery, &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished);
connect(m_upnpDiscovery, &UpnpDiscovery::upnpNotify, this, &DeviceManager::upnpNotifyReceived);
// Avahi Browser
m_avahiBrowser = new QtAvahiServiceBrowser(this);
m_avahiBrowser->enable();
// Bluetooth LE
#ifdef BLUETOOTH_LE
m_bluetoothScanner = new BluetoothScanner(this);
@ -587,7 +590,7 @@ DeviceManager::DeviceError DeviceManager::pairDevice(const PairingTransactionId
DevicePlugin *plugin = m_devicePlugins.value(m_supportedDevices.value(deviceClassId).pluginId());
if (!plugin) {
qWarning() << "Can't find a plugin for this device class";
qCWarning(dcDeviceManager()) << "Can't find a plugin for this device class";
return DeviceErrorPluginNotFound;
}
@ -1007,7 +1010,7 @@ void DeviceManager::loadPlugins()
m_devicePlugins.insert(pluginIface->pluginId(), pluginIface);
connect(pluginIface, &DevicePlugin::emitEvent, this, &DeviceManager::eventTriggered);
connect(pluginIface, &DevicePlugin::devicesDiscovered, this, &DeviceManager::slotDevicesDiscovered);
connect(pluginIface, &DevicePlugin::devicesDiscovered, this, &DeviceManager::slotDevicesDiscovered, Qt::QueuedConnection);
connect(pluginIface, &DevicePlugin::deviceSetupFinished, this, &DeviceManager::slotDeviceSetupFinished);
connect(pluginIface, &DevicePlugin::actionExecutionFinished, this, &DeviceManager::actionExecutionFinished);
connect(pluginIface, &DevicePlugin::pairingFinished, this, &DeviceManager::slotPairingFinished);
@ -1332,6 +1335,7 @@ void DeviceManager::replyReady(const PluginId &pluginId, QNetworkReply *reply)
}
}
}
void DeviceManager::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId)
{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {

View File

@ -35,6 +35,7 @@
#include "network/networkmanager.h"
#include "network/upnp/upnpdiscovery.h"
#include "network/upnp/upnpdevicedescriptor.h"
#include "network/avahi/qtavahiservicebrowser.h"
#ifdef BLUETOOTH_LE
#include "bluetooth/bluetoothscanner.h"
@ -201,6 +202,8 @@ private:
QTimer m_pluginTimer;
QList<DevicePlugin *> m_pluginTimerUsers;
NetworkManager *m_networkManager;
UpnpDiscovery* m_upnpDiscovery;
QtAvahiServiceBrowser *m_avahiBrowser;
#ifdef BLUETOOTH_LE
BluetoothScanner *m_bluetoothScanner;

View File

@ -48,9 +48,11 @@ HEADERS += devicemanager.h \
network/oauth2.h \
network/avahi/qt-watch.h \
network/avahi/avahiserviceentry.h \
network/avahi/zconfservicebrowser.h \
network/avahi/zconfserviceclient.h \
network/avahi/zconfservice.h \
network/avahi/qtavahiclient.h \
network/avahi/qtavahiservice.h \
network/avahi/qtavahiservice_p.h \
network/avahi/qtavahiservicebrowser.h \
network/avahi/qtavahiservicebrowser_p.h \
coap/coap.h \
coap/coappdu.h \
coap/coapoption.h \
@ -74,8 +76,6 @@ HEADERS += devicemanager.h \
types/ruleaction.h \
types/ruleactionparam.h \
types/statedescriptor.h \
network/avahi/guhavahibrowser.h
SOURCES += devicemanager.cpp \
loggingcategories.cpp \
@ -99,9 +99,11 @@ SOURCES += devicemanager.cpp \
network/oauth2.cpp \
network/avahi/qt-watch.cpp \
network/avahi/avahiserviceentry.cpp \
network/avahi/zconfservicebrowser.cpp \
network/avahi/zconfserviceclient.cpp \
network/avahi/zconfservice.cpp \
network/avahi/qtavahiclient.cpp \
network/avahi/qtavahiservice.cpp \
network/avahi/qtavahiservice_p.cpp \
network/avahi/qtavahiservicebrowser.cpp \
network/avahi/qtavahiservicebrowser_p.cpp \
coap/coap.cpp \
coap/coappdu.cpp \
coap/coapoption.cpp \
@ -125,8 +127,6 @@ SOURCES += devicemanager.cpp \
types/ruleaction.cpp \
types/ruleactionparam.cpp \
types/statedescriptor.cpp \
network/avahi/guhavahibrowser.cpp
# install plugininfo python script for libguh-dev
generateplugininfo.files = $$top_srcdir/plugins/guh-generateplugininfo

View File

@ -33,3 +33,4 @@ Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
Q_LOGGING_CATEGORY(dcJsonRpc, "JsonRpc")
Q_LOGGING_CATEGORY(dcRest, "Rest")
Q_LOGGING_CATEGORY(dcOAuth2, "OAuth2")
Q_LOGGING_CATEGORY(dcAvahi, "Avahi")

View File

@ -40,5 +40,6 @@ Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServer)
Q_DECLARE_LOGGING_CATEGORY(dcJsonRpc)
Q_DECLARE_LOGGING_CATEGORY(dcRest)
Q_DECLARE_LOGGING_CATEGORY(dcOAuth2)
Q_DECLARE_LOGGING_CATEGORY(dcAvahi)
#endif // LOGGINGCATEGORYS_H

View File

@ -18,19 +18,8 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class AvahiServiceEntry
\brief Holds information about an avahi service entry.
\ingroup types
\inmodule libguh
*/
#include "avahiserviceentry.h"
/*! Constructs an empty invalid \l{AvahiServiceEntry}*/
AvahiServiceEntry::AvahiServiceEntry() :
m_port(0),
m_protocol(QAbstractSocket::UnknownNetworkLayerProtocol)
@ -38,9 +27,9 @@ AvahiServiceEntry::AvahiServiceEntry() :
}
/*! Constructs a new \l{AvahiServiceEntry} with the given \a name, \a hostAddress, \a domain, \a hostName, \a port, \a protocol, \a txt and \a flags.*/
AvahiServiceEntry::AvahiServiceEntry(QString name, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, AvahiLookupResultFlags flags) :
AvahiServiceEntry::AvahiServiceEntry(QString name, QString serviceType, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, AvahiLookupResultFlags flags) :
m_name(name),
m_serviceType(serviceType),
m_hostAddress(hostAddress),
m_domain(domain),
m_hostName(hostName),
@ -52,82 +41,109 @@ AvahiServiceEntry::AvahiServiceEntry(QString name, QHostAddress hostAddress, QSt
}
/*! Returns the name of this \l{AvahiServiceEntry}.*/
QString AvahiServiceEntry::name() const
{
return m_name;
}
QString AvahiServiceEntry::serviceType() const
{
return m_serviceType;
}
/*! Returns the host address of this \l{AvahiServiceEntry}.*/
QHostAddress AvahiServiceEntry::hostAddress() const
{
return m_hostAddress;
}
/*! Returns the domain of this \l{AvahiServiceEntry}.*/
QString AvahiServiceEntry::domain() const
{
return m_domain;
}
/*! Returns the host name of this \l{AvahiServiceEntry}.*/
QString AvahiServiceEntry::hostName() const
{
return m_hostName;
}
/*! Returns the port of this \l{AvahiServiceEntry}.*/
quint16 AvahiServiceEntry::port() const
{
return m_port;
}
/*! Returns the protocol of this \l{AvahiServiceEntry}.*/
QAbstractSocket::NetworkLayerProtocol AvahiServiceEntry::protocol() const
{
return m_protocol;
}
/*! Returns the txt string list of this \l{AvahiServiceEntry}.*/
AvahiLookupResultFlags AvahiServiceEntry::flags() const
{
return m_flags;
}
QStringList AvahiServiceEntry::txt() const
{
return m_txt;
}
/*! Returns true if this \l{AvahiServiceEntry} is valid.*/
bool AvahiServiceEntry::isValid() const
{
return !m_hostAddress.isNull() && !m_hostName.isEmpty() && m_port != 0 && m_protocol != QAbstractSocket::UnknownNetworkLayerProtocol;
}
/*! Returns true if this \l{AvahiServiceEntry} was loaded from the cache.*/
bool AvahiServiceEntry::isChached() const
{
return m_flags & AVAHI_LOOKUP_RESULT_CACHED;
}
/*! Returns true if this \l{AvahiServiceEntry} was found in the wide area.*/
bool AvahiServiceEntry::isWideArea() const
{
return m_flags & AVAHI_LOOKUP_RESULT_WIDE_AREA;
}
/*! Returns true if this \l{AvahiServiceEntry} is a multicast service.*/
bool AvahiServiceEntry::isMulticast() const
{
return m_flags & AVAHI_LOOKUP_RESULT_MULTICAST;
}
/*! Returns true if this \l{AvahiServiceEntry} was found local.*/
bool AvahiServiceEntry::isLocal() const
{
return m_flags & AVAHI_LOOKUP_RESULT_LOCAL;
}
/*! Returns true if this \l{AvahiServiceEntry} is our own service.*/
bool AvahiServiceEntry::isOurOwn() const
{
return m_flags & AVAHI_LOOKUP_RESULT_OUR_OWN;
}
bool AvahiServiceEntry::operator ==(const AvahiServiceEntry &other) const
{
return other.name() == m_name &&
other.serviceType() == m_serviceType &&
other.hostAddress() == m_hostAddress &&
other.domain() == m_domain &&
other.hostName() == m_hostName &&
other.port() == m_port &&
other.protocol() == m_protocol &&
other.flags() == m_flags &&
other.txt() == m_txt;
}
bool AvahiServiceEntry::operator !=(const AvahiServiceEntry &other) const
{
return !operator==(other);
}
QDebug operator <<(QDebug dbg, const AvahiServiceEntry &entry)
{
dbg.nospace() << "AvahiServiceEntry(";
dbg << entry.name() << ")" << endl;
dbg << " location: " << entry.hostAddress().toString() << ":" << entry.port() << endl;
dbg << " hostname: " << entry.hostName() << endl;
dbg << " domain: " << entry.domain() << endl;
dbg << "service type: " << entry.serviceType() << endl;
dbg << " protocol: " << entry.protocol() << endl;
dbg << " txt: " << entry.txt() << endl;
return dbg;
}

View File

@ -24,20 +24,25 @@
#include <QObject>
#include <QString>
#include <QHostAddress>
#include <QAbstractSocket>
#include <avahi-client/publish.h>
class AvahiServiceEntry
#include "libguh.h"
class LIBGUH_EXPORT AvahiServiceEntry
{
public:
AvahiServiceEntry();
AvahiServiceEntry(QString name, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, AvahiLookupResultFlags flags);
AvahiServiceEntry(QString name, QString serviceType, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, AvahiLookupResultFlags flags);
QString name() const;
QString serviceType() const;
QHostAddress hostAddress() const;
QString domain() const;
QString hostName() const;
quint16 port() const;
QAbstractSocket::NetworkLayerProtocol protocol() const;
AvahiLookupResultFlags flags() const;
QStringList txt() const;
bool isValid() const;
@ -48,8 +53,12 @@ public:
bool isLocal() const;
bool isOurOwn() const;
bool operator ==(const AvahiServiceEntry &other) const;
bool operator !=(const AvahiServiceEntry &other) const;
private:
QString m_name;
QString m_serviceType;
QHostAddress m_hostAddress;
QString m_domain;
QString m_hostName;
@ -60,4 +69,7 @@ private:
};
QDebug operator <<(QDebug dbg, const AvahiServiceEntry &entry);
Q_DECLARE_METATYPE(AvahiServiceEntry)
#endif // AVAHISERVICEENTRY_H

View File

@ -1,8 +1,6 @@
/***
This file is part of avahi.
Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
@ -18,6 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
***/
#include <QObject>

View File

@ -4,8 +4,6 @@
/***
This file is part of avahi.
Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
@ -19,6 +17,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
***/
/** \file qt-watch.h Qt main loop adapter */

View File

@ -0,0 +1,80 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "qtavahiclient.h"
#include "qt-watch.h"
#include <avahi-common/error.h>
QtAvahiClient::QtAvahiClient(QObject *parent) :
QObject(parent),
poll(avahi_qt_poll_get()),
client(0),
error(0)
{
}
QtAvahiClient::~QtAvahiClient()
{
if (client)
avahi_client_free(client);
}
void QtAvahiClient::start()
{
if (client)
return;
avahi_client_new(poll, (AvahiClientFlags) 0, QtAvahiClient::callback, this, &error);
}
QString QtAvahiClient::errorString() const
{
return QString(avahi_strerror(error));
}
void QtAvahiClient::callback(AvahiClient *client, AvahiClientState state, void *userdata)
{
QtAvahiClient *serviceClient = static_cast<QtAvahiClient *>(userdata);
if (!serviceClient)
return;
serviceClient->client = client;
switch (state) {
case AVAHI_CLIENT_S_RUNNING:
emit serviceClient->clientStateChanged(QtAvahiClientStateRunning);
break;
case AVAHI_CLIENT_FAILURE:
emit serviceClient->clientStateChanged(QtAvahiClientStateFailure);
break;
case AVAHI_CLIENT_S_COLLISION:
emit serviceClient->clientStateChanged(QtAvahiClientStateCollision);
break;
case AVAHI_CLIENT_S_REGISTERING:
emit serviceClient->clientStateChanged(QtAvahiClientStateRegistering);
break;
case AVAHI_CLIENT_CONNECTING:
emit serviceClient->clientStateChanged(QtAvahiClientStateConnecting);
break;
}
}

View File

@ -0,0 +1,65 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef QTAVAHICLIENT_H
#define QTAVAHICLIENT_H
#include <QObject>
#include <avahi-client/client.h>
#include "libguh.h"
class LIBGUH_EXPORT QtAvahiClient : public QObject
{
Q_OBJECT
Q_ENUMS(QtAvahiClientState)
public:
enum QtAvahiClientState {
QtAvahiClientStateRunning,
QtAvahiClientStateFailure,
QtAvahiClientStateCollision,
QtAvahiClientStateRegistering,
QtAvahiClientStateConnecting
};
explicit QtAvahiClient(QObject *parent = 0);
~QtAvahiClient();
private:
friend class QtAvahiService;
friend class QtAvahiServiceBrowser;
friend class QtAvahiServiceBrowserPrivate;
const AvahiPoll *poll;
AvahiClient *client;
int error;
void start();
QString errorString() const;
static void callback(AvahiClient *client, AvahiClientState state, void *userdata);
signals:
void clientStateChanged(const QtAvahiClientState &state);
};
#endif // QTAVAHICLIENT_H

View File

@ -0,0 +1,113 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "qtavahiservice.h"
#include "qtavahiservice_p.h"
QtAvahiService::QtAvahiService(QObject *parent) :
QObject(parent),
d_ptr(new QtAvahiServicePrivate)
{
d_ptr->client = new QtAvahiClient(this);
d_ptr->client->start();
}
QtAvahiService::~QtAvahiService()
{
if (d_ptr->group)
avahi_entry_group_free(d_ptr->group);
delete d_ptr;
}
quint16 QtAvahiService::port() const
{
return d_ptr->port;
}
QString QtAvahiService::name() const
{
return d_ptr->name;
}
QString QtAvahiService::serviceType() const
{
return d_ptr->type;
}
bool QtAvahiService::registerService(QString name, quint16 port, QString type)
{
// check if the client is running
if (!d_ptr->client->client || AVAHI_CLIENT_S_RUNNING != avahi_client_get_state(d_ptr->client->client))
return false;
d_ptr->name = name;
d_ptr->port = port;
d_ptr->type = type;
// if the group is not set yet, create it
if (!d_ptr->group)
d_ptr->group = avahi_entry_group_new(d_ptr->client->client, QtAvahiServicePrivate::callback, this);
// if the group is empty
if (avahi_entry_group_is_empty(d_ptr->group)) {
// add the service
d_ptr->error = avahi_entry_group_add_service(d_ptr->group,
AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC,
(AvahiPublishFlags) 0,
d_ptr->name.toLatin1().data(),
d_ptr->type.toLatin1().data(),
0,
0,
(uint16_t)d_ptr->port,
NULL);
// verify if the group has to be comitted
if (!d_ptr->error)
d_ptr->error = avahi_entry_group_commit(d_ptr->group);
// if the group could not be commited, return false
if (d_ptr->error)
return false;
}
return true;
}
void QtAvahiService::resetService()
{
avahi_entry_group_reset(d_ptr->group);
}
bool QtAvahiService::isValid() const
{
return (d_ptr->group && !d_ptr->error);
}
QString QtAvahiService::errorString() const
{
if (!d_ptr->client->client)
return "Invalid client.";
return avahi_strerror(avahi_client_errno(d_ptr->client->client));
}

View File

@ -0,0 +1,68 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef QTAVAHISERVICE_H
#define QTAVAHISERVICE_H
#include <QObject>
#include "libguh.h"
class QtAvahiServicePrivate;
class LIBGUH_EXPORT QtAvahiService : public QObject
{
Q_OBJECT
Q_ENUMS(QtAvahiServiceState)
public:
enum QtAvahiServiceState {
QtAvahiServiceStateUncomitted,
QtAvahiServiceStateRegistering,
QtAvahiServiceStateEstablished,
QtAvahiServiceStateCollision,
QtAvahiServiceStateFailure
};
explicit QtAvahiService(QObject *parent = 0);
~QtAvahiService();
quint16 port() const;
QString name() const;
QString serviceType() const;
bool registerService(QString name, quint16 port, QString type = "_http._tcp");
void resetService();
bool isValid() const;
QString errorString() const;
signals:
void serviceStateChanged(const QtAvahiServiceState &state);
protected:
QtAvahiServicePrivate *d_ptr;
private:
Q_DECLARE_PRIVATE(QtAvahiService)
};
#endif // QTAVAHISERVICE_H

View File

@ -18,38 +18,39 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "guhavahibrowser.h"
#include "loggingcategories.h"
#include "qtavahiservice_p.h"
GuhAvahiBrowser::GuhAvahiBrowser(QObject *parent) : QObject(parent)
QtAvahiServicePrivate::QtAvahiServicePrivate() :
client(0),
group(0),
error(0)
{
m_browser = new ZConfServiceBrowser(this);
connect(m_browser, &ZConfServiceBrowser::serviceEntryAdded, this, &GuhAvahiBrowser::onSeviceAdded);
connect(m_browser, &ZConfServiceBrowser::serviceEntryRemoved, this, &GuhAvahiBrowser::onSeviceRemoved);
connect(m_browser, &ZConfServiceBrowser::serviceBrowsingFinished, this, &GuhAvahiBrowser::onSeviceBrowsingFinished);
}
void GuhAvahiBrowser::browseService(const QString &serviceType)
void QtAvahiServicePrivate::callback(AvahiEntryGroup *group, AvahiEntryGroupState state, void *userdata)
{
m_serviceEntries.clear();
m_browser->browse(serviceType);
}
void GuhAvahiBrowser::onSeviceAdded(const QString &name)
{
qCDebug(dcHardware()) << QString("Avahi: +%1").arg(name);
m_serviceEntries.append(m_browser->serviceEntry(name));
}
void GuhAvahiBrowser::onSeviceRemoved(const QString &name)
{
qCDebug(dcHardware()) << QString("Avahi: -%1").arg(name);
}
void GuhAvahiBrowser::onSeviceBrowsingFinished()
{
qCDebug(dcHardware()) << "Avahi: discovery finished.";
emit avahiBrowseFinished(m_serviceEntries);
Q_UNUSED(group);
QtAvahiService *service = static_cast<QtAvahiService *>(userdata);
if (!service)
return;
switch (state) {
case AVAHI_ENTRY_GROUP_UNCOMMITED:
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateUncomitted);
break;
case AVAHI_ENTRY_GROUP_REGISTERING:
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateRegistering);
break;
case AVAHI_ENTRY_GROUP_ESTABLISHED:
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateEstablished);
break;
case AVAHI_ENTRY_GROUP_COLLISION:
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateCollision);
break;
case AVAHI_ENTRY_GROUP_FAILURE:
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateFailure);
break;
}
}

View File

@ -18,33 +18,35 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef GUHAVAHIBROWSER_H
#define GUHAVAHIBROWSER_H
#ifndef QTAVAHISERVICEPRIVATE_P
#define QTAVAHISERVICEPRIVATE_P
#include <QObject>
#include <QString>
#include "zconfservicebrowser.h"
#include "qtavahiservice.h"
#include "qtavahiclient.h"
class GuhAvahiBrowser : public QObject
#include "libguh.h"
#include <avahi-client/publish.h>
#include <avahi-common/error.h>
#include <avahi-common/alternative.h>
class LIBGUH_EXPORT QtAvahiServicePrivate
{
Q_OBJECT
public:
explicit GuhAvahiBrowser(QObject *parent = 0);
QtAvahiServicePrivate();
void browseService(const QString &serviceType);
private:
ZConfServiceBrowser *m_browser;
QList<AvahiServiceEntry> m_serviceEntries;
signals:
void avahiBrowseFinished(const QList<AvahiServiceEntry> &serviceEntries);
private slots:
void onSeviceAdded(const QString &name);
void onSeviceRemoved(const QString &name);
void onSeviceBrowsingFinished();
static void callback(AvahiEntryGroup *group, AvahiEntryGroupState state, void *userdata);
QtAvahiClient *client;
AvahiEntryGroup *group;
QString name;
quint16 port;
QString type;
int error;
};
#endif // GUHAVAHIBROWSER_H
#endif // QTAVAHISERVICEPRIVATE_P

View File

@ -0,0 +1,81 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "qtavahiservicebrowser.h"
#include "qtavahiservicebrowser_p.h"
#include "loggingcategories.h"
#include <avahi-common/error.h>
QtAvahiServiceBrowser::QtAvahiServiceBrowser(QObject *parent) :
QObject(parent),
d_ptr(new QtAvahiServiceBrowserPrivate(new QtAvahiClient))
{
connect(d_ptr->client, &QtAvahiClient::clientStateChanged, this, &QtAvahiServiceBrowser::onClientStateChanged);
}
QtAvahiServiceBrowser::~QtAvahiServiceBrowser()
{
// Delete each service browser
foreach (const QString &serviceType, d_ptr->serviceBrowserTable.keys()) {
AvahiServiceBrowser *browser = d_ptr->serviceBrowserTable.take(serviceType);
if (browser) {
avahi_service_browser_free(browser);
}
}
// Delete the service type browser
if (d_ptr->serviceTypeBrowser)
avahi_service_type_browser_free(d_ptr->serviceTypeBrowser);
delete d_ptr;
}
void QtAvahiServiceBrowser::enable()
{
d_ptr->client->start();
}
QList<AvahiServiceEntry> QtAvahiServiceBrowser::serviceEntries() const
{
return m_serviceEntries;
}
void QtAvahiServiceBrowser::onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state)
{
if (state == QtAvahiClient::QtAvahiClientStateRunning) {
qCDebug(dcAvahi()) << "Service browser client connected.";
// Return if we already have a service type browser
if (d_ptr->serviceTypeBrowser)
return;
d_ptr->serviceTypeBrowser = avahi_service_type_browser_new(d_ptr->client->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, (AvahiLookupFlags) 0, QtAvahiServiceBrowserPrivate::callbackServiceTypeBrowser, this);
} else if (state == QtAvahiClient::QtAvahiClientStateFailure) {
qCWarning(dcAvahi()) << "Service browser client failure:" << d_ptr->client->errorString();
}
}
void QtAvahiServiceBrowser::createServiceBrowser(const char *serviceType)
{
// create a new service browser for the given serviceType
AvahiServiceBrowser *browser = avahi_service_browser_new(d_ptr->client->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, serviceType, NULL, (AvahiLookupFlags) 0, QtAvahiServiceBrowserPrivate::callbackServiceBrowser, this);
d_ptr->serviceBrowserTable.insert(serviceType, browser);
}

View File

@ -0,0 +1,62 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef QTAVAHISERVICEBROWSER_H
#define QTAVAHISERVICEBROWSER_H
#include <QObject>
#include <avahi-client/lookup.h>
#include "libguh.h"
#include "qtavahiclient.h"
#include "avahiserviceentry.h"
class QtAvahiServiceBrowserPrivate;
class LIBGUH_EXPORT QtAvahiServiceBrowser : public QObject
{
Q_OBJECT
public:
explicit QtAvahiServiceBrowser(QObject *parent = 0);
~QtAvahiServiceBrowser();
void enable();
QList<AvahiServiceEntry> serviceEntries() const;
signals:
void serviceEntryAdded(const AvahiServiceEntry &entry);
void serviceEntryRemoved(const AvahiServiceEntry &entry);
private slots:
void onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state);
private:
QtAvahiServiceBrowserPrivate *d_ptr;
QList<AvahiServiceEntry> m_serviceEntries;
QStringList m_serviceTypes;
void createServiceBrowser(const char* serviceType);
Q_DECLARE_PRIVATE(QtAvahiServiceBrowser)
};
#endif // QTAVAHISERVICEBROWSER_H

View File

@ -0,0 +1,205 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "qtavahiservicebrowser_p.h"
#include "qtavahiservicebrowser.h"
#include "avahiserviceentry.h"
#include "loggingcategories.h"
#include <avahi-common/strlst.h>
#include <avahi-common/error.h>
QtAvahiServiceBrowserPrivate::QtAvahiServiceBrowserPrivate(QtAvahiClient *client) :
client(client),
serviceTypeBrowser(NULL)
{
}
void QtAvahiServiceBrowserPrivate::callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata)
{
Q_UNUSED(browser)
Q_UNUSED(interface)
Q_UNUSED(protocol)
Q_UNUSED(domain)
Q_UNUSED(flags)
QtAvahiServiceBrowser *serviceBrowser = static_cast<QtAvahiServiceBrowser *>(userdata);
if (!serviceBrowser)
return;
switch (event) {
case AVAHI_BROWSER_NEW:
if (!serviceBrowser->m_serviceTypes.contains(type)) {
serviceBrowser->m_serviceTypes.append(type);
qCDebug(dcAvahi()) << "Create service type browser for" << type;
serviceBrowser->createServiceBrowser(type);
}
break;
case AVAHI_BROWSER_REMOVE:
// Note: the browser for this serviceType will be deleted once all
// services from this type are removed
break;
case AVAHI_BROWSER_CACHE_EXHAUSTED:
break;
case AVAHI_BROWSER_ALL_FOR_NOW:
break;
case AVAHI_BROWSER_FAILURE:
qCWarning(dcAvahi()) << "Service type browser error:" << QString(avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->client)));
break;
}
}
void QtAvahiServiceBrowserPrivate::callbackServiceBrowser(AvahiServiceBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata)
{
Q_UNUSED(browser);
Q_UNUSED(flags);
QtAvahiServiceBrowser *serviceBrowser = static_cast<QtAvahiServiceBrowser *>(userdata);
if (!serviceBrowser)
return;
switch (event) {
case AVAHI_BROWSER_NEW:
// Start resolving new service
if (!(avahi_service_resolver_new(serviceBrowser->d_ptr->client->client,
interface,
protocol,
name,
type,
domain,
AVAHI_PROTO_UNSPEC,
(AvahiLookupFlags) 0,
QtAvahiServiceBrowserPrivate::callbackServiceResolver,
serviceBrowser))) {
qCWarning(dcAvahi()) << "Failed to resolve service" << QString(name) << ":" << avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->client));
}
break;
case AVAHI_BROWSER_REMOVE: {
// Remove the service
foreach (const AvahiServiceEntry &entry, serviceBrowser->m_serviceEntries) {
// Check not only the name, but also the protocol
if (entry.name() == name && entry.protocol() == QtAvahiServiceBrowserPrivate::converProtocol(protocol)) {
serviceBrowser->m_serviceEntries.removeAll(entry);
emit serviceBrowser->serviceEntryRemoved(entry);
}
}
// Check if this was the last service for this serviceType
foreach (const AvahiServiceEntry &entry, serviceBrowser->m_serviceEntries) {
if (entry.serviceType() == type)
return;
}
// This was the last service for this serviceType, lets delete the corresponding browser
AvahiServiceBrowser *browser = serviceBrowser->d_ptr->serviceBrowserTable.take(type);
if (browser)
avahi_service_browser_free(browser);
serviceBrowser->m_serviceTypes.removeAll(type);
break;
}
case AVAHI_BROWSER_ALL_FOR_NOW:
break;
case AVAHI_BROWSER_CACHE_EXHAUSTED:
break;
case AVAHI_BROWSER_FAILURE:
qCWarning(dcAvahi()) << "Service browser error:" << QString(avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->client)));
break;
}
}
void QtAvahiServiceBrowserPrivate::callbackServiceResolver(AvahiServiceResolver *resolver, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata)
{
Q_UNUSED(interface);
Q_UNUSED(type);
Q_UNUSED(txt);
QtAvahiServiceBrowser *serviceBrowser = static_cast<QtAvahiServiceBrowser *>(userdata);
if (!serviceBrowser)
return;
switch (event) {
case AVAHI_RESOLVER_FAILURE:
break;
case AVAHI_RESOLVER_FOUND: {
char a[AVAHI_ADDRESS_STR_MAX];
avahi_address_snprint(a, sizeof(a), address);
// convert protocol
QAbstractSocket::NetworkLayerProtocol networkProtocol = QtAvahiServiceBrowserPrivate::converProtocol(protocol);
QStringList txtList = QtAvahiServiceBrowserPrivate::converTxtList(txt);
// create the new resolved service entry
AvahiServiceEntry entry = AvahiServiceEntry(name,
type,
QHostAddress(QString(a)),
QString(domain),
QString(host_name),
(quint16)port,
networkProtocol,
txtList,
flags);
serviceBrowser->m_serviceEntries.append(entry);
emit serviceBrowser->serviceEntryAdded(entry);
}
}
avahi_service_resolver_free(resolver);
}
QStringList QtAvahiServiceBrowserPrivate::converTxtList(AvahiStringList *txt)
{
if (!txt)
return QStringList();
QStringList txtList;
txtList.append(QString(reinterpret_cast<char *>(txt->text)));
while (txt->next) {
AvahiStringList *next = txt->next;
txtList.append(QString(reinterpret_cast<char *>(next->text)));
txt = next;
}
return txtList;
}
QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserPrivate::converProtocol(const AvahiProtocol &protocol)
{
QAbstractSocket::NetworkLayerProtocol networkProtocol;
switch (protocol) {
case AVAHI_PROTO_INET:
networkProtocol = QAbstractSocket::IPv4Protocol;
break;
case AVAHI_PROTO_INET6:
networkProtocol = QAbstractSocket::IPv6Protocol;
break;
case AVAHI_PROTO_UNSPEC:
networkProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
break;
}
return networkProtocol;
}

View File

@ -0,0 +1,79 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef QTAVAHISERVICEBROWSERPRIVATE_H
#define QTAVAHISERVICEBROWSERPRIVATE_H
#include <QStringList>
#include <QAbstractSocket>
#include <avahi-client/lookup.h>
#include "qtavahiclient.h"
#include "qtavahiservice.h"
#include "libguh.h"
class LIBGUH_EXPORT QtAvahiServiceBrowserPrivate
{
public:
QtAvahiServiceBrowserPrivate(QtAvahiClient *client);
// Callback members
static void callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
const char *type,
const char *domain,
AvahiLookupResultFlags flags,
void *userdata);
static void callbackServiceBrowser(AvahiServiceBrowser *browser,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
const char *name,
const char *type,
const char *domain,
AvahiLookupResultFlags flags,
void *userdata);
static void callbackServiceResolver(AvahiServiceResolver *resolver, AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiResolverEvent event,
const char *name,
const char *type,
const char *domain,
const char *host_name,
const AvahiAddress *address,
uint16_t port,
AvahiStringList *txt,
AvahiLookupResultFlags flags,
void *userdata);
// Convert members
static QStringList converTxtList(AvahiStringList *txt);
static QAbstractSocket::NetworkLayerProtocol converProtocol(const AvahiProtocol &protocol);
QtAvahiClient *client;
AvahiServiceTypeBrowser *serviceTypeBrowser;
QHash<QString, AvahiServiceBrowser *> serviceBrowserTable;
};
#endif // QTAVAHISERVICEBROWSERPRIVATE_H

View File

@ -1,178 +0,0 @@
/*
* This file is part of qtzeroconf. (c) 2012 Johannes Hilden
* https://github.com/johanneshilden/qtzeroconf
*
* Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
*
* qtzeroconf is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* qtzeroconf 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 qtzeroconf; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include <QDebug>
#include <QStringBuilder>
#include <avahi-client/publish.h>
#include <avahi-common/error.h>
#include <avahi-common/alternative.h>
#include "zconfserviceclient.h"
#include "zconfservice.h"
class ZConfServicePrivate
{
public:
ZConfServicePrivate()
: client(0), group(0), error(0)
{
}
static void callback(AvahiEntryGroup *group, AvahiEntryGroupState state, void *userdata)
{
Q_UNUSED(group);
ZConfService *serviceGroup = static_cast<ZConfService *>(userdata);
if (serviceGroup) {
switch (state)
{
case AVAHI_ENTRY_GROUP_ESTABLISHED:
emit serviceGroup->entryGroupEstablished();
qDebug() << ("Service '" % serviceGroup->d_ptr->name % "' successfully establised.");
break;
case AVAHI_ENTRY_GROUP_COLLISION:
emit serviceGroup->entryGroupNameCollision();
break;
case AVAHI_ENTRY_GROUP_FAILURE:
emit serviceGroup->entryGroupFailure();
qDebug() << ("Entry group failure: " % serviceGroup->errorString());
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
qDebug() << "AVAHI_ENTRY_GROUP_UNCOMMITED";
break;
case AVAHI_ENTRY_GROUP_REGISTERING:
qDebug() << "AVAHI_ENTRY_GROUP_REGISTERING";
} // end switch
}
}
ZConfServiceClient *client;
AvahiEntryGroup *group;
QString name;
in_port_t port;
QString type;
int error;
};
/*!
\class ZConfService
\ingroup hardware
\inmodule libguh
\brief This class provides Avahi Zeroconf service registration. It can be
used by server applications to announce a service on the local area network.
Typical use involves creating an instance of ZConfService and calling
registerService() with a service name and port number.
*/
/*! \fn void ZConfService::entryGroupEstablished();
This signal will be emited when the service entry could be established successfully.
*/
/*! \fn void ZConfService::entryGroupNameCollision();
This signal will be emited when the service entry name collided with an other service.
*/
/*! \fn void ZConfService::entryGroupFailure();
This signal will be emited when the service entry could not be established successfully.
*/
/*! Constructs a \l{ZConfService} with the given \a parent.*/
ZConfService::ZConfService(QObject *parent)
: QObject(parent),
d_ptr(new ZConfServicePrivate)
{
d_ptr->client = new ZConfServiceClient(this);
d_ptr->client->run();
}
/*! Destroys the object and releases all resources associated with it. */
ZConfService::~ZConfService()
{
if (d_ptr->group)
avahi_entry_group_free(d_ptr->group);
delete d_ptr;
}
/*! Returns true if the service group was added and commited without error. */
bool ZConfService::isValid() const
{
return (d_ptr->group && !d_ptr->error);
}
/*! Returns a human readable error string with details of the last error that occured. */
QString ZConfService::errorString() const
{
if (!d_ptr->client->client)
return "No client!";
return avahi_strerror(avahi_client_errno(d_ptr->client->client));
}
/*!
Registers a Zeroconf service with the given \a name and \a port on the LAN. If no service \a type is specified,
"_http._tcp" is assumed.
*/
void ZConfService::registerService(QString name, in_port_t port, QString type)
{
if (!d_ptr->client->client || AVAHI_CLIENT_S_RUNNING
!= avahi_client_get_state(d_ptr->client->client)) {
qDebug() << "ZConfService error: Client is not running.";
return;
}
d_ptr->name = name;
d_ptr->port = port;
d_ptr->type = type;
if (!d_ptr->group) {
d_ptr->group = avahi_entry_group_new(d_ptr->client->client,
ZConfServicePrivate::callback,
this);
}
if (avahi_entry_group_is_empty(d_ptr->group)) {
d_ptr->error = avahi_entry_group_add_service(d_ptr->group,
AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC,
(AvahiPublishFlags) 0,
d_ptr->name.toLatin1().data(),
d_ptr->type.toLatin1().data(),
0,
0,
d_ptr->port,
NULL);
if (!d_ptr->error) {
d_ptr->error = avahi_entry_group_commit(d_ptr->group);
}
if (d_ptr->error)
qDebug() << ("Error creating service: " % errorString());
}
}
/*!
Deregisters the service associated with this object. You can reuse the same
ZConfService object at any time to register another service on the network.
*/
void ZConfService::resetService()
{
avahi_entry_group_reset(d_ptr->group);
}

View File

@ -1,57 +0,0 @@
/*
* This file is part of qtzeroconf. (c) 2012 Johannes Hilden
* https://github.com/johanneshilden/qtzeroconf
*
* Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
*
* qtzeroconf is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* qtzeroconf 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 qtzeroconf; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef ZCONFSERVICE_H
#define ZCONFSERVICE_H
#include <QObject>
#include <arpa/inet.h>
class ZConfServicePrivate;
class ZConfService : public QObject
{
Q_OBJECT
public:
explicit ZConfService(QObject *parent = 0);
~ZConfService();
bool isValid() const;
QString errorString() const;
public slots:
void registerService(QString name, in_port_t port, QString type = "_http._tcp");
void resetService();
protected:
ZConfServicePrivate *const d_ptr;
private:
Q_DECLARE_PRIVATE(ZConfService)
signals:
void entryGroupEstablished();
void entryGroupNameCollision();
void entryGroupFailure();
};
#endif // ZCONFSERVICE_H

View File

@ -1,235 +0,0 @@
/*
* This file is part of qtzeroconf. (c) 2012 Johannes Hilden
* https://github.com/johanneshilden/qtzeroconf
*
* Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
*
* qtzeroconf is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* qtzeroconf 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 qtzeroconf; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include <QHash>
#include <QStringBuilder>
#include <QDebug>
#include <avahi-common/error.h>
#include "zconfservicebrowser.h"
#include "zconfserviceclient.h"
class ZConfServiceBrowserPrivate
{
public:
ZConfServiceBrowserPrivate(ZConfServiceClient *client)
: client(client), browser(0)
{
}
static void callback(AvahiServiceBrowser *browser,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
const char *name,
const char *type,
const char *domain,
AvahiLookupResultFlags flags,
void *userdata)
{
Q_UNUSED(browser);
Q_UNUSED(flags);
ZConfServiceBrowser *serviceBrowser = static_cast<ZConfServiceBrowser *>(userdata);
if (serviceBrowser) {
switch (event) {
case AVAHI_BROWSER_FAILURE:
qDebug() << ("Avahi browser error: " % QString(avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->client))));
emit serviceBrowser->serviceBrowsingFinished();
break;
case AVAHI_BROWSER_NEW:
qDebug() << ("New service '" % QString(name) % "' of type " % QString(type) % " in domain " % QString(domain) % ".");
// We ignore the returned resolver object. In the callback
// function we free it. If the server is terminated before
// the callback function is called the server will free
// the resolver for us.
if (!(avahi_service_resolver_new(serviceBrowser->d_ptr->client->client,
interface,
protocol,
name,
serviceBrowser->d_ptr->type.toLatin1().data(),
domain,
AVAHI_PROTO_UNSPEC,
(AvahiLookupFlags) 0,
ZConfServiceBrowserPrivate::resolve,
serviceBrowser)))
qDebug() << ("Failed to resolve service '" % QString(name) % "': " % avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->client)));
break;
case AVAHI_BROWSER_REMOVE:
serviceBrowser->d_ptr->entries.remove(name);
emit serviceBrowser->serviceEntryRemoved(name);
break;
case AVAHI_BROWSER_ALL_FOR_NOW:
emit serviceBrowser->serviceBrowsingFinished();
break;
case AVAHI_BROWSER_CACHE_EXHAUSTED:
break;
}
}
}
static void resolve(AvahiServiceResolver *resolver,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiResolverEvent event,
const char *name,
const char *type,
const char *domain,
const char *host_name,
const AvahiAddress *address,
uint16_t port,
AvahiStringList *txt,
AvahiLookupResultFlags flags,
void *userdata)
{
Q_UNUSED(interface);
Q_UNUSED(type);
Q_UNUSED(txt);
ZConfServiceBrowser *serviceBrowser = static_cast<ZConfServiceBrowser *>(userdata);
if (serviceBrowser) {
switch (event) {
case AVAHI_RESOLVER_FAILURE:
qDebug() << ("Failed to resolve service '" % QString(name) % "': " % avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->client)));
break;
case AVAHI_RESOLVER_FOUND:
{
char a[AVAHI_ADDRESS_STR_MAX];
avahi_address_snprint(a, sizeof(a), address);
// convert protocol
QAbstractSocket::NetworkLayerProtocol p;
if (protocol == AVAHI_PROTO_INET) {
p = QAbstractSocket::IPv4Protocol;
} else if (protocol == AVAHI_PROTO_INET6) {
p = QAbstractSocket::IPv6Protocol;
} else {
p = QAbstractSocket::UnknownNetworkLayerProtocol;
}
QStringList txtList;
// TODO: get txt string list
// // get txt string list
// if (txt) {
// AvahiStringList *txtAtt = txt->text;
// txtAtt = (txt ? txt->next : 0);
// while (txtAtt) {
// qDebug() << txt;
// txtList.append(QString(txt->));
// }
// }
AvahiServiceEntry entry = AvahiServiceEntry(name, QHostAddress(QString(a)), QString(domain), QString(host_name), (quint16)port, p, txtList, flags);
serviceBrowser->d_ptr->entries.insert(name, entry);
emit serviceBrowser->serviceEntryAdded(name);
}
}
avahi_service_resolver_free(resolver);
}
}
typedef QHash<QString, AvahiServiceEntry> ZConfServiceEntryTable;
ZConfServiceClient *const client;
AvahiServiceBrowser *browser;
ZConfServiceEntryTable entries;
QString type;
};
/*!
\class ZConfServiceBrowser
\ingroup hardware
\inmodule libguh
\brief AvahiServiceBrowser wrapper that lets you browse for services
available on the local network. This class can be used to handle Zeroconf
service discovery in a Qt-based client application.
Instantiate a ZConfServiceBrowser object and call browse() with the desired
service type as argument (e.g., "_http._tcp" or "_ipp._tcp").
ZConfServiceBrowser will emit serviceEntryAdded() when a new service is
discovered and serviceEntryRemoved() when a service is removed from the
network.
*/
/*! \fn void ZConfServiceBrowser::serviceEntryAdded(const QString &name);
This signal will be emited when a new service entry with the given \a name was added in the network.
*/
/*! \fn void ZConfServiceBrowser::serviceEntryRemoved(const QString &name);
This signal will be emited when a new service entry with the given \a name was removed from the network.
*/
/*! Creates a Zeroconf service browser with the given \a parent. Call browse() to start browsing for services. */
ZConfServiceBrowser::ZConfServiceBrowser(QObject *parent)
: QObject(parent),
d_ptr(new ZConfServiceBrowserPrivate(new ZConfServiceClient(this)))
{
connect(d_ptr->client, SIGNAL(clientRunning()), this, SLOT(createServiceBrowser()));
}
/*! Destroys the browser object and releases all resources associated with it. */
ZConfServiceBrowser::~ZConfServiceBrowser()
{
if (d_ptr->browser)
avahi_service_browser_free(d_ptr->browser);
delete d_ptr;
}
/*!
Browses for Zeroconf services of the given \a serviceType on the LAN. This is a non-blocking call.
ZConfServiceBrowser will emit serviceEntryAdded() when a new service is
discovered and serviceEntryRemoved() when a service is removed from the
network.
*/
void ZConfServiceBrowser::browse(QString serviceType)
{
d_ptr->type = serviceType;
if(d_ptr->client)
d_ptr->client->run();
}
/*!
Returns a ZConfServiceEntry struct with detailed information about the
Zeroconf service associated with the \a name.
*/
AvahiServiceEntry ZConfServiceBrowser::serviceEntry(QString name)
{
return d_ptr->entries.value(name);
}
void ZConfServiceBrowser::createServiceBrowser()
{
if (d_ptr->browser)
return;
d_ptr->browser = avahi_service_browser_new(d_ptr->client->client,
AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC,
d_ptr->type.toLatin1().data(),
NULL,
(AvahiLookupFlags) 0,
ZConfServiceBrowserPrivate::callback,
this);
}

View File

@ -1,58 +0,0 @@
/*
* This file is part of qtzeroconf. (c) 2012 Johannes Hilden
* https://github.com/johanneshilden/qtzeroconf
*
* Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
*
* qtzeroconf is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* qtzeroconf 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 qtzeroconf; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef ZCONFSERVICEBROWSER_H
#define ZCONFSERVICEBROWSER_H
#include <QObject>
#include <stdint-gcc.h>
#include <avahi-client/lookup.h>
#include "avahiserviceentry.h"
class ZConfServiceBrowserPrivate;
class ZConfServiceBrowser : public QObject
{
Q_OBJECT
public:
explicit ZConfServiceBrowser(QObject *parent = 0);
~ZConfServiceBrowser();
void browse(QString serviceType = "_http._tcp");
AvahiServiceEntry serviceEntry(QString name);
signals:
void serviceEntryAdded(const QString &name);
void serviceEntryRemoved(const QString &name);
void serviceBrowsingFinished();
private slots:
void createServiceBrowser();
protected:
ZConfServiceBrowserPrivate *const d_ptr;
private:
Q_DECLARE_PRIVATE(ZConfServiceBrowser)
};
#endif // ZCONFSERVICEBROWSER_H

View File

@ -1,84 +0,0 @@
/*
* This file is part of qtzeroconf. (c) 2012 Johannes Hilden
* https://github.com/johanneshilden/qtzeroconf
*
* Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
*
* qtzeroconf is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* qtzeroconf 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 qtzeroconf; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include <QDebug>
#include <avahi-common/error.h>
#include "zconfserviceclient.h"
#include "qt-watch.h"
void ZConfServiceClient::run()
{
if (client)
return;
avahi_client_new(poll, (AvahiClientFlags) 0, ZConfServiceClient::callback, this, &error);
}
QString ZConfServiceClient::errorString() const
{
return avahi_strerror(error);
}
ZConfServiceClient::ZConfServiceClient(QObject *parent)
: QObject(parent),
poll(avahi_qt_poll_get()),
client(0),
error(0)
{
}
ZConfServiceClient::~ZConfServiceClient()
{
if (client)
// This will automatically free all associated browser,
// resolve and entry group objects.
avahi_client_free(client);
}
void ZConfServiceClient::callback(AvahiClient *client, AvahiClientState state, void *userdata)
{
ZConfServiceClient *service = static_cast<ZConfServiceClient *>(userdata);
if (service) {
service->client = client;
switch (state)
{
case AVAHI_CLIENT_S_RUNNING:
qDebug() << "AVAHI_CLIENT_S_RUNNING";
// The server has started up successfully and registered its host
// name on the network.
emit service->clientRunning();
break;
case AVAHI_CLIENT_FAILURE:
qDebug() << "AVAHI_CLIENT_FAILURE";
emit service->clientFailure();
break;
case AVAHI_CLIENT_S_COLLISION:
case AVAHI_CLIENT_S_REGISTERING:
qDebug() << (AVAHI_CLIENT_S_COLLISION == state
? "AVAHI_CLIENT_S_COLLISION"
: "AVAHI_CLIENT_S_REGISTERING");
emit service->clientReset();
break;
case AVAHI_CLIENT_CONNECTING:
qDebug() << "AVAHI_CLIENT_CONNECTING";
emit service->clientConnecting();
} // end switch
}
}

View File

@ -1,56 +0,0 @@
/*
* This file is part of qtzeroconf. (c) 2012 Johannes Hilden
* https://github.com/johanneshilden/qtzeroconf
*
* Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
*
* qtzeroconf is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* qtzeroconf 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 qtzeroconf; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef ZCONFSERVICECLIENT_H
#define ZCONFSERVICECLIENT_H
#include <QObject>
#include <avahi-client/client.h>
class ZConfServiceClient : public QObject
{
Q_OBJECT
signals:
void clientRunning();
void clientFailure();
void clientConnecting();
void clientReset();
private:
friend class ZConfService;
friend class ZConfServiceBrowser;
friend class ZConfServiceBrowserPrivate;
ZConfServiceClient(QObject *parent = 0);
~ZConfServiceClient();
void run();
QString errorString() const;
static void callback(AvahiClient *client, AvahiClientState state, void *userdata);
const AvahiPoll *const poll;
AvahiClient *client;
int error;
};
#endif // ZCONFSERVICECLIENT_H

View File

@ -681,14 +681,24 @@ void DevicePlugin::upnpDiscover(QString searchTarget, QString userAgent)
{
if(requiredHardware().testFlag(DeviceManager::HardwareResourceUpnpDisovery)){
deviceManager()->m_upnpDiscovery->discoverDevices(searchTarget, userAgent, pluginId());
} else {
qCWarning(dcDeviceManager) << "UPnP discovery resource not set for plugin" << pluginName();
}
}
/*! Returns the pointer to the central \l{QtAvahiService}{service} browser. */
QtAvahiServiceBrowser *DevicePlugin::avahiServiceBrowser() const
{
return deviceManager()->m_avahiBrowser;
}
#ifdef BLUETOOTH_LE
bool DevicePlugin::discoverBluetooth()
{
if(requiredHardware().testFlag(DeviceManager::HardwareResourceBluetoothLE)){
return deviceManager()->m_bluetoothScanner->discover(pluginId());
} else {
qCWarning(dcDeviceManager) << "Bluetooth LE resource not set for plugin" << pluginName();
}
return false;
}

View File

@ -76,15 +76,16 @@ public:
// Hardware input
virtual void radioData(const QList<int> &rawData) {Q_UNUSED(rawData)}
virtual void guhTimer() {}
virtual void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) {Q_UNUSED(upnpDeviceDescriptorList)}
virtual void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) { Q_UNUSED(upnpDeviceDescriptorList) }
virtual void upnpNotifyReceived(const QByteArray &notifyData) {Q_UNUSED(notifyData)}
virtual void networkManagerReplyReady(QNetworkReply *reply) {Q_UNUSED(reply)}
#ifdef BLUETOOTH_LE
virtual void bluetoothDiscoveryFinished(const QList<QBluetoothDeviceInfo> &deviceInfos) {Q_UNUSED(deviceInfos)}
virtual void bluetoothDiscoveryFinished(const QList<QBluetoothDeviceInfo> &deviceInfos) { Q_UNUSED(deviceInfos) }
#endif
// Configuration
QList<ParamType> configurationDescription() const;
DeviceManager::DeviceError setConfiguration(const ParamList &configuration);
@ -109,6 +110,9 @@ protected:
// Radio 433
bool transmitData(int delay, QList<int> rawData);
// Avahi browse services
QtAvahiServiceBrowser *avahiServiceBrowser() const;
// Bluetooth LE discovery
#ifdef BLUETOOTH_LE
bool discoverBluetooth();

View File

@ -0,0 +1,11 @@
include(../../plugins.pri)
TARGET = $$qtLibraryTarget(guh_devicepluginavahimonitor)
SOURCES += \
devicepluginavahimonitor.cpp
HEADERS += \
devicepluginavahimonitor.h

View File

@ -0,0 +1,99 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.guru> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page wifidetector.html
\title WiFi Detector
\brief Plugin to monitor devices in the local network.
\ingroup plugins
\ingroup guh-plugins
This plugin allows to find and monitor network devices in your local network by using the MAC address.
\underline{NOTE}: the application \c nmap has to be installed and guh has to run as root.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/wifidetector/devicepluginwifidetector.json
*/
#include "devicepluginavahimonitor.h"
#include "plugin/device.h"
#include "devicemanager.h"
#include "plugininfo.h"
#include <QDebug>
#include <QStringList>
#include <QNetworkInterface>
DevicePluginAvahiMonitor::DevicePluginAvahiMonitor()
{
}
DeviceManager::DeviceSetupStatus DevicePluginAvahiMonitor::setupDevice(Device *device)
{
qCDebug(dcAvahiMonitor()) << "Setup" << device->name() << device->params();
connect(avahiServiceBrowser(), SIGNAL(serviceEntryAdded(AvahiServiceEntry)), this, SLOT(onServiceEntryAdded(AvahiServiceEntry)));
connect(avahiServiceBrowser(), SIGNAL(serviceEntryRemoved(AvahiServiceEntry)), this, SLOT(onServiceEntryRemoved(AvahiServiceEntry)));
return DeviceManager::DeviceSetupStatusSuccess;
}
DeviceManager::DeviceError DevicePluginAvahiMonitor::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
if (deviceClassId != avahiDeviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound;
QList<DeviceDescriptor> deviceDescriptors;
foreach (const AvahiServiceEntry &service, avahiServiceBrowser()->serviceEntries()) {
DeviceDescriptor deviceDescriptor(avahiDeviceClassId, service.name(), service.hostAddress().toString());
deviceDescriptors.append(deviceDescriptor);
}
emit devicesDiscovered(avahiDeviceClassId, deviceDescriptors);
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::HardwareResources DevicePluginAvahiMonitor::requiredHardware() const
{
return DeviceManager::HardwareResourceNone;
}
void DevicePluginAvahiMonitor::onServiceEntryAdded(const AvahiServiceEntry &serviceEntry)
{
Q_UNUSED(serviceEntry)
}
void DevicePluginAvahiMonitor::onServiceEntryRemoved(const AvahiServiceEntry &serviceEntry)
{
Q_UNUSED(serviceEntry)
}

View File

@ -0,0 +1,48 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.guru> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DEVICEPLUGINAVAHIMONITOR_H
#define DEVICEPLUGINAVAHIMONITOR_H
#include "plugin/deviceplugin.h"
#include <QProcess>
class DevicePluginAvahiMonitor : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "devicepluginavahimonitor.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginAvahiMonitor();
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::HardwareResources requiredHardware() const override;
private slots:
void onServiceEntryAdded(const AvahiServiceEntry &serviceEntry);
void onServiceEntryRemoved(const AvahiServiceEntry &serviceEntry);
};
#endif // DEVICEPLUGINAVAHIMONITOR_H

View File

@ -0,0 +1,32 @@
{
"name": "Avahi Monitor",
"idName": "AvahiMonitor",
"id": "d83fb167-cef7-4347-8c58-fa39df7bea4f",
"vendors": [
{
"name": "guh",
"idName": "guh",
"id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
"deviceClasses": [
{
"deviceClassId": "97f0154d-6945-49b8-bd65-0a8cea0c6652",
"name": "Avahi Monitor",
"idName": "avahi",
"deviceIcon": "Network",
"basicTags": [
"Device",
"Sensor"
],
"createMethods": ["discovery"],
"paramTypes": [
{
"name": "name",
"type": "QString",
"inputType": "TextLine"
}
]
}
]
}
]
}

View File

@ -26,3 +26,5 @@ SUBDIRS += elro \
ws2812 \
orderbutton \
denon \
avahimonitor \

View File

@ -118,6 +118,8 @@ int main(int argc, char *argv[])
s_loggingFilters.insert("Rest", false);
s_loggingFilters.insert("OAuth2", false);
s_loggingFilters.insert("TimeManager", false);
s_loggingFilters.insert("Coap", false);
s_loggingFilters.insert("Avahi", false);
QHash<QString, bool> loggingFiltersPlugins;
foreach (const QJsonObject &pluginMetadata, DeviceManager::pluginsMetadata()) {

View File

@ -129,11 +129,9 @@ WebServer::WebServer(const QSslConfiguration &sslConfiguration, QObject *parent)
// Create avahi service
#ifndef TESTING_ENABLED
m_avahiService = new ZConfService(this);
connect(m_avahiService, SIGNAL(entryGroupEstablished()), this, SLOT(onEntryGroupEstablished()));
connect(m_avahiService, SIGNAL(entryGroupFailure()), this, SLOT(onEntryGroupEstablished()));
connect(m_avahiService, SIGNAL(entryGroupNameCollision()), this, SLOT(onEntryGroupEstablished()));
m_avahiService->registerService("guhd", m_port);
m_avahiService = new QtAvahiService(this);
connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &WebServer::onAvahiServiceStateChanged);
m_avahiService->registerService("guhIO", m_port);
#endif
}
@ -142,9 +140,6 @@ WebServer::~WebServer()
{
qCDebug(dcApplication) << "Shutting down \"Webserver\"";
this->close();
qCDebug(dcApplication) << "Shutting down \"Avahi Service\"";
if (m_avahiService)
m_avahiService->resetService();
}
/*! Send the given \a reply map to the corresponding client.
@ -538,19 +533,11 @@ void WebServer::onError(QAbstractSocket::SocketError error)
qCWarning(dcConnection) << QString("Client socket error %1:%2 ->").arg(socket->peerAddress().toString()).arg(socket->peerPort()) << socket->errorString();
}
void WebServer::onEntryGroupEstablished()
void WebServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state)
{
qCDebug(dcWebServer()) << "Avahi webserver service established successfully.";
}
void WebServer::onEntryGroupFailure()
{
qCWarning(dcWebServer()) << "Avahi webserver service establishment failed.";
}
void WebServer::onEntryGroupNameCollision()
{
qCWarning(dcWebServer()) << "Avahi webserver service establishment failed. Name collision.";
if (state == QtAvahiService::QtAvahiServiceStateEstablished) {
qCDebug(dcAvahi()) << "Service" << m_avahiService->name() << "established successfully";
}
}
/*! Returns true if this \l{WebServer} started successfully. */

View File

@ -34,7 +34,7 @@
#include <QSslConfiguration>
#include <QSslKey>
#include "network/avahi/zconfservice.h"
#include "network/avahi/qtavahiservice.h"
// Note: Hypertext Transfer Protocol (HTTP/1.1) from the Internet Engineering Task Force (IETF):
// https://tools.ietf.org/html/rfc7231
@ -65,7 +65,6 @@ private:
private slots:
void onTimout();
};
@ -86,7 +85,7 @@ private:
QList<WebServerClient *> m_webServerClients;
QHash<QSslSocket *, HttpRequest> m_incompleteRequests;
ZConfService *m_avahiService;
QtAvahiService *m_avahiService;
QSslConfiguration m_sslConfiguration;
bool m_useSsl;
@ -116,10 +115,7 @@ private slots:
void onEncrypted();
void onError(QAbstractSocket::SocketError error);
// avahi service
void onEntryGroupEstablished();
void onEntryGroupFailure();
void onEntryGroupNameCollision();
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
public slots: