mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
mDNS Support (#1452)
* Allow build, if no grabbers are enabled * Align available functions to right Qt version * Update to next development version * Align available functions to right Qt version * fix workflows (apt/nightly) * Disable QNetworkConfigurationManager deprecation warnings * Initial go on Smart Pointers * Add Deallocation * Correct QT_WARNING_DISABLE_DEPRECATED (available since 5.9) * Cluster Build Variables * Hyperion Light * Address build warnings * Hyperion Light - UI * Update Protobuf to latest master * Removed compiler warnings * Added restart ability to systray * Correct Protobuf * Ignore 'no-return' warning on protobuf build * hyperion-remote: Fix auto discovery of hyperion server * Fix Qt version override * Update changelog * Remove Grabber Components, if no Grabber exists * Standalone Grabber - Fix fps default * Remote Control - Have Source Selction accrosswhole screen * Enable Blackborder detection only, if relevant input sources available * Enable Blackborder detection only, if relevant input sources available * Remote UI - rearrange containers * Checkout * Fix compilation on windows * Re-added qmdnsengine template cmake * chrono added for linux * Removed existing AVAHI/Bonjour, allow to enable/disable mDNS * hyperiond macos typo fix * Fix macOS Bundle build * Fix macOS bundle info details * Correct CMake files * Removed existing AVAHI/Bonjour (2) * Share hyperion's services via mDNS * Add mDNS Browser and mDNS for LED-Devices * Support mDNS discovery for standalone grabbers * Remove ZLib Dependency & Cleanup * mDNS - hanle 2.local2 an ".local." domains equally * Hue - Link discovery to bridge class, workaround port 443 for mDNS discovery * Fix save button state when switching between devices * Removed sessions (of other hyperions) * mDNS Publisher - Simplify service naming * mDNS refactoring & Forwarder discovery * mDNS Updates to use device service name * Consistency of standalone grabbers with mDNS Service Registry * Merge branch 'hyperion-project:master' into mDNS * Start JSON and WebServers only after Instance 0 is available * Remove bespoke qDebug Output again * MDNS updates and refactor Forwarder * Minor updates * Upgrade to CMake 3.1 * typo * macOS fix * Correct merge * - Remove dynamic linker flag from standalone dispmanX Grabber - Added ability to use system qmdns libs * Cec handler library will load at runtime * typo fix * protobuf changes * mDNS changes for Windows/macOS * test window build qmdnsengine * absolute path to protobuf cmake dir * Rework Hue Wizard supporting mDNS * LED-Devices - Retry support + Refactoring (excl. Hue) * LED-Devices - Refactoring/Retry support Hue + additional alignments * Address LGTM findings * Fix CI-Build, revert test changes * Build Windows in Release mode to avoid python problem * Correct that WebServerObject is available earlier * Ensure that instance name in logs for one instance are presented * Update content LEDs * Rework mDNS Address lookup * Fix LED UI * Fix for non mDNS Services (ignore default port) * Disbale device when now input is available * Revert back some updates, ensure last color is updated when switched on * Handle reopening case and changed IP, port for API-calls * Add UPD-DDP Device * WLED support for DDP * Fix printout * LEDDevice - Allow more retries, udapte defaults * LED-Net Devices - Select Custom device, if configured Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com> Co-authored-by: Paulchen Panther <Paulchen-Panter@protonmail.com>
This commit is contained in:
@@ -402,13 +402,6 @@ signals:
|
||||
///
|
||||
void onStartInstanceResponse(const int &tan);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// @brief Is called whenever a Hyperion instance wants the current register list
|
||||
/// @param callerInstance The instance should be returned in the answer call
|
||||
///
|
||||
void requestActiveRegister(QObject *callerInstance);
|
||||
|
||||
private:
|
||||
void stopDataConnectionss();
|
||||
|
||||
|
@@ -292,6 +292,12 @@ private:
|
||||
///
|
||||
void handleInputSourceCommand(const QJsonObject& message, const QString& command, int tan);
|
||||
|
||||
/// Handle an incoming JSON message to request remote hyperion servers providing a given hyperion service
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleServiceCommand(const QJsonObject &message, const QString &command, int tan);
|
||||
|
||||
///
|
||||
/// Handle an incoming JSON message of unknown type
|
||||
///
|
||||
|
@@ -6,10 +6,7 @@
|
||||
|
||||
// components def
|
||||
#include <utils/Components.h>
|
||||
// bonjour
|
||||
#ifdef ENABLE_AVAHI
|
||||
#include <bonjour/bonjourrecord.h>
|
||||
#endif
|
||||
|
||||
// videModes
|
||||
#include <utils/VideoMode.h>
|
||||
// settings
|
||||
@@ -21,7 +18,6 @@
|
||||
|
||||
class Hyperion;
|
||||
class ComponentRegister;
|
||||
class BonjourBrowserWrapper;
|
||||
class PriorityMuxer;
|
||||
|
||||
class JsonCB : public QObject
|
||||
@@ -73,13 +69,6 @@ private slots:
|
||||
/// @brief handle component state changes
|
||||
///
|
||||
void handleComponentState(hyperion::Components comp, bool state);
|
||||
#ifdef ENABLE_AVAHI
|
||||
///
|
||||
/// @brief handle emits from bonjour wrapper
|
||||
/// @param bRegisters The full register map
|
||||
///
|
||||
void handleBonjourChange(const QMap<QString,BonjourRecord>& bRegisters);
|
||||
#endif
|
||||
|
||||
///
|
||||
/// @brief handle emits from PriorityMuxer
|
||||
@@ -140,10 +129,7 @@ private:
|
||||
Hyperion* _hyperion;
|
||||
/// pointer of comp register
|
||||
ComponentRegister* _componentRegister;
|
||||
#ifdef ENABLE_AVAHI
|
||||
/// Bonjour instance
|
||||
BonjourBrowserWrapper* _bonjour;
|
||||
#endif
|
||||
|
||||
/// priority muxer instance
|
||||
PriorityMuxer* _prioMuxer;
|
||||
/// contains all available commands
|
||||
|
@@ -1,68 +0,0 @@
|
||||
#pragma once
|
||||
// qt incl
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QHostInfo>
|
||||
|
||||
#include <bonjour/bonjourrecord.h>
|
||||
|
||||
class BonjourServiceBrowser;
|
||||
class BonjourServiceResolver;
|
||||
class QTimer;
|
||||
|
||||
class BonjourBrowserWrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
friend class HyperionDaemon;
|
||||
///
|
||||
/// @brief Browse for hyperion services in bonjour, constructed from HyperionDaemon
|
||||
/// Searching for hyperion http service by default
|
||||
///
|
||||
BonjourBrowserWrapper(QObject * parent = nullptr);
|
||||
|
||||
public:
|
||||
|
||||
///
|
||||
/// @brief Browse for a service
|
||||
///
|
||||
bool browseForServiceType(const QString &serviceType);
|
||||
///
|
||||
/// @brief Get all available sessions
|
||||
///
|
||||
QMap<QString, BonjourRecord> getAllServices() { return _hyperionSessions; }
|
||||
|
||||
static BonjourBrowserWrapper* instance;
|
||||
static BonjourBrowserWrapper *getInstance() { return instance; }
|
||||
|
||||
signals:
|
||||
///
|
||||
/// @brief Emits whenever a change happend
|
||||
///
|
||||
void browserChange( const QMap<QString, BonjourRecord> &bRegisters );
|
||||
|
||||
private:
|
||||
/// map of service names and browsers
|
||||
QMap<QString, BonjourServiceBrowser *> _browsedServices;
|
||||
/// Resolver
|
||||
BonjourServiceResolver *_bonjourResolver;
|
||||
|
||||
// contains all current active service sessions
|
||||
QMap<QString, BonjourRecord> _hyperionSessions;
|
||||
|
||||
QString _bonjourCurrentServiceToResolve;
|
||||
/// timer to resolve changes
|
||||
QTimer *_timerBonjourResolver;
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// @brief is called whenever a BonjourServiceBrowser emits change
|
||||
void currentBonjourRecordsChanged( const QList<BonjourRecord> &list );
|
||||
/// @brief new record resolved
|
||||
void bonjourRecordResolved( const QHostInfo &hostInfo, int port );
|
||||
|
||||
///
|
||||
/// @brief timer slot which updates regularly entries
|
||||
///
|
||||
void bonjourResolve();
|
||||
};
|
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2007, Trenton Schulz
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BONJOURRECORD_H
|
||||
#define BONJOURRECORD_H
|
||||
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QString>
|
||||
|
||||
class BonjourRecord
|
||||
{
|
||||
public:
|
||||
BonjourRecord() : port(-1) {}
|
||||
BonjourRecord(const QString &name, const QString ®Type, const QString &domain)
|
||||
: serviceName(name)
|
||||
, registeredType(regType)
|
||||
, replyDomain(domain)
|
||||
, port(-1)
|
||||
{}
|
||||
|
||||
BonjourRecord(const char *name, const char *regType, const char *domain)
|
||||
: serviceName(QString::fromUtf8(name))
|
||||
, registeredType(QString::fromUtf8(regType))
|
||||
, replyDomain(QString::fromUtf8(domain))
|
||||
, port(-1)
|
||||
{
|
||||
}
|
||||
|
||||
QString serviceName;
|
||||
QString registeredType;
|
||||
QString replyDomain;
|
||||
QString hostName;
|
||||
QString address;
|
||||
int port;
|
||||
|
||||
bool operator==(const BonjourRecord &other) const
|
||||
{
|
||||
return serviceName == other.serviceName
|
||||
&& registeredType == other.registeredType
|
||||
&& replyDomain == other.replyDomain;
|
||||
}
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(BonjourRecord)
|
||||
|
||||
#endif // BONJOURRECORD_H
|
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2007, Trenton Schulz
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BONJOURSERVICEBROWSER_H
|
||||
#define BONJOURSERVICEBROWSER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#ifndef PLATFORM_AMLOGIC
|
||||
#include <dns_sd.h>
|
||||
#else
|
||||
#include <avahi-compat-libdns_sd/dns_sd.h>
|
||||
#endif
|
||||
#include "bonjour/bonjourrecord.h"
|
||||
|
||||
|
||||
class QSocketNotifier;
|
||||
class BonjourServiceBrowser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BonjourServiceBrowser(QObject *parent = 0);
|
||||
~BonjourServiceBrowser() override;
|
||||
void browseForServiceType(const QString &serviceType);
|
||||
inline QList<BonjourRecord> currentRecords() const { return bonjourRecords; }
|
||||
inline QString serviceType() const { return browsingType; }
|
||||
|
||||
signals:
|
||||
void currentBonjourRecordsChanged(const QList<BonjourRecord> &list);
|
||||
void error(DNSServiceErrorType err);
|
||||
|
||||
private slots:
|
||||
void bonjourSocketReadyRead();
|
||||
|
||||
private:
|
||||
static void DNSSD_API bonjourBrowseReply(DNSServiceRef , DNSServiceFlags flags, quint32,
|
||||
DNSServiceErrorType errorCode, const char *serviceName,
|
||||
const char *regType, const char *replyDomain, void *context);
|
||||
DNSServiceRef dnssref;
|
||||
QSocketNotifier *bonjourSocket;
|
||||
QList<BonjourRecord> bonjourRecords;
|
||||
QString browsingType;
|
||||
};
|
||||
|
||||
#endif // BONJOURSERVICEBROWSER_H
|
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2007, Trenton Schulz
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BONJOURSERVICEREGISTER_H
|
||||
#define BONJOURSERVICEREGISTER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "bonjourrecord.h"
|
||||
class QSocketNotifier;
|
||||
|
||||
#ifndef PLATFORM_AMLOGIC
|
||||
#include <dns_sd.h>
|
||||
#else
|
||||
#include <avahi-compat-libdns_sd/dns_sd.h>
|
||||
#endif
|
||||
|
||||
class BonjourServiceRegister : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BonjourServiceRegister(QObject *parent = 0);
|
||||
~BonjourServiceRegister() override;
|
||||
|
||||
void registerService(const QString& service, int port);
|
||||
void registerService(const BonjourRecord &record, quint16 servicePort, const std::vector<std::pair<std::string, std::string>>& txt = {});
|
||||
inline BonjourRecord registeredRecord() const { return finalRecord; }
|
||||
|
||||
quint16 getPort() const { return _port; }
|
||||
|
||||
signals:
|
||||
void error(DNSServiceErrorType error);
|
||||
void serviceRegistered(const BonjourRecord &record);
|
||||
|
||||
private slots:
|
||||
void bonjourSocketReadyRead();
|
||||
|
||||
private:
|
||||
static void DNSSD_API bonjourRegisterService(DNSServiceRef sdRef, DNSServiceFlags,
|
||||
DNSServiceErrorType errorCode, const char *name,
|
||||
const char *regtype, const char *domain,
|
||||
void *context);
|
||||
DNSServiceRef dnssref;
|
||||
QSocketNotifier *bonjourSocket;
|
||||
BonjourRecord finalRecord;
|
||||
|
||||
// current port
|
||||
quint16 _port = 0;
|
||||
};
|
||||
|
||||
#endif // BONJOURSERVICEREGISTER_H
|
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2007, Trenton Schulz
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BONJOURSERVICERESOLVER_H
|
||||
#define BONJOURSERVICERESOLVER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#ifndef PLATFORM_AMLOGIC
|
||||
#include <dns_sd.h>
|
||||
#else
|
||||
#include <avahi-compat-libdns_sd/dns_sd.h>
|
||||
#endif
|
||||
class QSocketNotifier;
|
||||
class QHostInfo;
|
||||
class BonjourRecord;
|
||||
|
||||
class BonjourServiceResolver : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BonjourServiceResolver(QObject *parent);
|
||||
~BonjourServiceResolver() override;
|
||||
|
||||
bool resolveBonjourRecord(const BonjourRecord &record);
|
||||
|
||||
signals:
|
||||
void bonjourRecordResolved(const QHostInfo &hostInfo, int port);
|
||||
void error(DNSServiceErrorType error);
|
||||
|
||||
private slots:
|
||||
void bonjourSocketReadyRead();
|
||||
void cleanupResolve();
|
||||
void finishConnect(const QHostInfo &hostInfo);
|
||||
|
||||
private:
|
||||
static void DNSSD_API bonjourResolveReply(DNSServiceRef sdRef, DNSServiceFlags flags,
|
||||
quint32 interfaceIndex, DNSServiceErrorType errorCode,
|
||||
const char *fullName, const char *hosttarget, quint16 port,
|
||||
quint16 txtLen, const char *txtRecord, void *context);
|
||||
DNSServiceRef dnssref;
|
||||
QSocketNotifier *bonjourSocket;
|
||||
int bonjourPort;
|
||||
};
|
||||
|
||||
#endif // BONJOURSERVICERESOLVER_H
|
@@ -7,7 +7,6 @@
|
||||
// qt
|
||||
#include <QVector>
|
||||
|
||||
class BonjourServiceRegister;
|
||||
class QTcpServer;
|
||||
class FlatBufferClient;
|
||||
class NetOrigin;
|
||||
@@ -20,6 +19,7 @@ class NetOrigin;
|
||||
class FlatBufferServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FlatBufferServer(const QJsonDocument& config, QObject* parent = nullptr);
|
||||
~FlatBufferServer() override;
|
||||
@@ -34,6 +34,12 @@ public slots:
|
||||
|
||||
void initServer();
|
||||
|
||||
signals:
|
||||
///
|
||||
/// @emits whenever the server would like to announce its service details
|
||||
///
|
||||
void publishService(const QString& serviceType, quint16 servicePort, const QByteArray& serviceName = "");
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// @brief Is called whenever a new socket wants to connect
|
||||
@@ -64,7 +70,6 @@ private:
|
||||
int _timeout;
|
||||
quint16 _port;
|
||||
const QJsonDocument _config;
|
||||
BonjourServiceRegister * _serviceRegister = nullptr;
|
||||
|
||||
QVector<FlatBufferClient*> _openConnections;
|
||||
};
|
||||
|
@@ -28,6 +28,17 @@
|
||||
class Hyperion;
|
||||
class QTcpSocket;
|
||||
class FlatBufferConnection;
|
||||
class MessageForwarderFlatbufferClientsHelper;
|
||||
|
||||
struct TargetHost {
|
||||
QHostAddress host;
|
||||
quint16 port;
|
||||
|
||||
bool operator == (TargetHost const& a) const
|
||||
{
|
||||
return ((host == a.host) && (port == a.port));
|
||||
}
|
||||
};
|
||||
|
||||
class MessageForwarder : public QObject
|
||||
{
|
||||
@@ -39,14 +50,15 @@ public:
|
||||
void addJsonTarget(const QJsonObject& targetConfig);
|
||||
void addFlatbufferTarget(const QJsonObject& targetConfig);
|
||||
|
||||
private slots:
|
||||
public slots:
|
||||
///
|
||||
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||
/// @param type settingyType from enum
|
||||
/// @param type settingsType from enum
|
||||
/// @param config configuration object
|
||||
///
|
||||
void handleSettingsUpdate(settings::type type, const QJsonDocument &config);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// @brief Handle component state change MessageForwarder
|
||||
/// @param component The component from enum
|
||||
@@ -81,15 +93,13 @@ private slots:
|
||||
|
||||
private:
|
||||
|
||||
struct TargetHost {
|
||||
QHostAddress host;
|
||||
quint16 port;
|
||||
void enableTargets(bool enable, const QJsonObject& config);
|
||||
|
||||
bool operator == (TargetHost const& a) const
|
||||
{
|
||||
return ((host == a.host) && (port == a.port));
|
||||
}
|
||||
};
|
||||
int startJsonTargets(const QJsonObject& config);
|
||||
void stopJsonTargets();
|
||||
|
||||
int startFlatbufferTargets(const QJsonObject& config);
|
||||
void stopFlatbufferTargets();
|
||||
|
||||
/// Hyperion instance
|
||||
Hyperion *_hyperion;
|
||||
@@ -105,10 +115,37 @@ private:
|
||||
|
||||
/// Flatbuffer connection for forwarding
|
||||
QList<TargetHost> _flatbufferTargets;
|
||||
QList<FlatBufferConnection*> _forwardClients;
|
||||
|
||||
/// Flag if forwarder is enabled
|
||||
bool _forwarder_enabled = true;
|
||||
|
||||
const int _priority;
|
||||
|
||||
MessageForwarderFlatbufferClientsHelper* _messageForwarderFlatBufHelper;
|
||||
};
|
||||
|
||||
class MessageForwarderFlatbufferClientsHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
MessageForwarderFlatbufferClientsHelper();
|
||||
~MessageForwarderFlatbufferClientsHelper();
|
||||
|
||||
signals:
|
||||
void addClient(const QString& origin, const TargetHost& targetHost, int priority, bool skipReply);
|
||||
void clearClients();
|
||||
|
||||
public slots:
|
||||
bool isFree() const;
|
||||
|
||||
void forwardImage(const Image<ColorRgb>& image);
|
||||
void addClientHandler(const QString& origin, const TargetHost& targetHost, int priority, bool skipReply);
|
||||
void clearClientsHandler();
|
||||
|
||||
private:
|
||||
|
||||
QList<FlatBufferConnection*> _forwardClients;
|
||||
bool _free;
|
||||
};
|
||||
|
@@ -22,6 +22,10 @@
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#ifdef Bool
|
||||
#undef Bool
|
||||
#endif
|
||||
|
||||
class X11Grabber : public Grabber , public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
|
@@ -11,7 +11,6 @@
|
||||
class QTcpServer;
|
||||
class QTcpSocket;
|
||||
class JsonClientConnection;
|
||||
class BonjourServiceRegister;
|
||||
class NetOrigin;
|
||||
|
||||
///
|
||||
@@ -31,11 +30,18 @@ public:
|
||||
JsonServer(const QJsonDocument& config);
|
||||
~JsonServer() override;
|
||||
|
||||
void initServer();
|
||||
|
||||
///
|
||||
/// @return the port number on which this TCP listens for incoming connections
|
||||
///
|
||||
uint16_t getPort() const;
|
||||
|
||||
signals:
|
||||
///
|
||||
/// @emits whenever the server would like to announce its service details
|
||||
///
|
||||
void publishService(const QString& serviceType, quint16 servicePort, const QByteArray& serviceName = "");
|
||||
|
||||
private slots:
|
||||
///
|
||||
@@ -71,7 +77,7 @@ private:
|
||||
/// port
|
||||
uint16_t _port = 0;
|
||||
|
||||
BonjourServiceRegister * _serviceRegister = nullptr;
|
||||
const QJsonDocument _config;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#ifndef LEDEVICE_H
|
||||
#ifndef LEDEVICE_H
|
||||
#define LEDEVICE_H
|
||||
|
||||
// qt includes
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
// Utility includes
|
||||
#include <utils/ColorRgb.h>
|
||||
@@ -50,6 +51,13 @@ public:
|
||||
///
|
||||
~LedDevice() override;
|
||||
|
||||
///
|
||||
/// @brief Set the common logger for LED-devices.
|
||||
///
|
||||
/// @param[in] log The logger to be used
|
||||
///
|
||||
void setLogger(Logger* log);
|
||||
|
||||
///
|
||||
/// @brief Set the current active LED-device type.
|
||||
///
|
||||
@@ -64,6 +72,8 @@ public:
|
||||
///
|
||||
void setLedCount(int ledCount);
|
||||
|
||||
void setColorOrder(const QString& colorOrder);
|
||||
|
||||
///
|
||||
/// @brief Set a device's latch time.
|
||||
///
|
||||
@@ -83,6 +93,19 @@ public:
|
||||
///
|
||||
void setRewriteTime(int rewriteTime_ms);
|
||||
|
||||
/// @brief Set a device's enablement cycle's parameters.
|
||||
///
|
||||
/// @param[in] maxEnableRetries Maximum number of attempts to enable a device, if reached retries will be stopped
|
||||
/// @param[in] enableAttemptsTimerInterval Interval in seconds between two enablement attempts
|
||||
///
|
||||
void setEnableAttempts(int maxEnablAttempts, std::chrono::seconds enableAttemptsTimerInterval);
|
||||
|
||||
/// @brief Enable a device automatically after Hyperion startup or not
|
||||
///
|
||||
/// @param[in] isAutoStart
|
||||
///
|
||||
void setAutoStart(bool isAutoStart);
|
||||
|
||||
///
|
||||
/// @brief Discover devices of this type available (for configuration).
|
||||
/// @note Mainly used for network devices. Allows to find devices, e.g. via ssdp, mDNS or cloud ways.
|
||||
@@ -120,6 +143,15 @@ public:
|
||||
///
|
||||
virtual void identify(const QJsonObject& /*params*/) {}
|
||||
|
||||
///
|
||||
/// @brief Add an authorization/client-key or token to the device
|
||||
///
|
||||
/// Used in context of a set of devices of the same type.
|
||||
///
|
||||
/// @param[in] params Parameters to address device
|
||||
/// @return A JSON structure holding the authorization key/token
|
||||
virtual QJsonObject addAuthorization(const QJsonObject& /*params*/) { return QJsonObject(); }
|
||||
|
||||
///
|
||||
/// @brief Check, if device is properly initialised
|
||||
///
|
||||
@@ -127,7 +159,7 @@ public:
|
||||
///
|
||||
/// @return True, if device is initialised
|
||||
///
|
||||
bool isInitialised() const { return _isDeviceInitialised; }
|
||||
bool isInitialised() const;
|
||||
|
||||
///
|
||||
/// @brief Check, if device is ready to be used.
|
||||
@@ -136,14 +168,14 @@ public:
|
||||
///
|
||||
/// @return True, if device is ready
|
||||
///
|
||||
bool isReady() const { return _isDeviceReady; }
|
||||
bool isReady() const;
|
||||
|
||||
///
|
||||
/// @brief Check, if device is in error state.
|
||||
///
|
||||
/// @return True, if device is in error
|
||||
///
|
||||
bool isInError() const { return _isDeviceInError; }
|
||||
bool isInError() const;
|
||||
|
||||
///
|
||||
/// @brief Prints the color values to stdout.
|
||||
@@ -152,13 +184,6 @@ public:
|
||||
///
|
||||
static void printLedValues(const std::vector<ColorRgb>& ledValues);
|
||||
|
||||
///
|
||||
/// @brief Set the common logger for LED-devices.
|
||||
///
|
||||
/// @param[in] log The logger to be used
|
||||
///
|
||||
void setLogger(Logger* log) { _log = log; }
|
||||
|
||||
public slots:
|
||||
|
||||
///
|
||||
@@ -181,47 +206,47 @@ public slots:
|
||||
/// @param[in] ledValues The color per LED
|
||||
/// @return Zero on success else negative (i.e. device is not ready)
|
||||
///
|
||||
virtual int updateLeds(const std::vector<ColorRgb>& ledValues);
|
||||
virtual int updateLeds(std::vector<ColorRgb> ledValues);
|
||||
|
||||
///
|
||||
/// @brief Get the currently defined LatchTime.
|
||||
///
|
||||
/// @return Latch time in milliseconds
|
||||
///
|
||||
int getLatchTime() const { return _latchTime_ms; }
|
||||
int getLatchTime() const;
|
||||
|
||||
///
|
||||
/// @brief Get the currently defined RewriteTime.
|
||||
///
|
||||
/// @return Rewrite time in milliseconds
|
||||
///
|
||||
int getRewriteTime() const { return _refreshTimerInterval_ms; }
|
||||
int getRewriteTime() const;
|
||||
|
||||
///
|
||||
/// @brief Get the number of LEDs supported by the device.
|
||||
///
|
||||
/// @return Number of device's LEDs, 0 = unknown number
|
||||
///
|
||||
int getLedCount() const { return _ledCount; }
|
||||
int getLedCount() const;
|
||||
|
||||
///
|
||||
/// @brief Get the current active LED-device type.
|
||||
///
|
||||
QString getActiveDeviceType() const { return _activeDeviceType; }
|
||||
QString getActiveDeviceType() const;
|
||||
|
||||
///
|
||||
/// @brief Get color order of device.
|
||||
///
|
||||
/// @return The color order
|
||||
///
|
||||
QString getColorOrder() const { return _colorOrder; }
|
||||
QString getColorOrder() const;
|
||||
|
||||
///
|
||||
/// @brief Get the LED-Device component's state.
|
||||
///
|
||||
/// @return True, if enabled
|
||||
///
|
||||
inline bool componentState() const { return _isEnabled; }
|
||||
bool componentState() const;
|
||||
|
||||
///
|
||||
/// @brief Enables the device for output.
|
||||
@@ -257,11 +282,6 @@ public slots:
|
||||
///
|
||||
virtual bool switchOff();
|
||||
|
||||
bool switchOnOff(bool onState)
|
||||
{
|
||||
return onState == true ? switchOn() : switchOff();
|
||||
}
|
||||
|
||||
signals:
|
||||
///
|
||||
/// @brief Emits whenever the LED-Device switches between on/off.
|
||||
@@ -361,6 +381,16 @@ protected:
|
||||
///
|
||||
virtual bool restoreState();
|
||||
|
||||
///
|
||||
/// @brief Start a new enable cycle
|
||||
///
|
||||
void startEnableAttemptsTimer();
|
||||
|
||||
///
|
||||
/// @brief Stop a new enable cycle
|
||||
///
|
||||
void stopEnableAttemptsTimer();
|
||||
|
||||
///
|
||||
/// @brief Converts an uint8_t array to hex string.
|
||||
///
|
||||
@@ -368,7 +398,7 @@ protected:
|
||||
/// @param size of the array
|
||||
/// @param number Number of array items to be converted.
|
||||
/// @return array as string of hex values
|
||||
QString uint8_t_to_hex_string(const uint8_t * data, const int size, int number = -1) const;
|
||||
static QString uint8_t_to_hex_string(const uint8_t * data, const int size, int number = -1) ;
|
||||
|
||||
///
|
||||
/// @brief Converts a ByteArray to hex string.
|
||||
@@ -376,7 +406,7 @@ protected:
|
||||
/// @param data ByteArray
|
||||
/// @param number Number of array items to be converted.
|
||||
/// @return array as string of hex values
|
||||
QString toHex(const QByteArray& data, int number = -1) const;
|
||||
static QString toHex(const QByteArray& data, int number = -1) ;
|
||||
|
||||
/// Current device's type
|
||||
QString _activeDeviceType;
|
||||
@@ -414,6 +444,7 @@ protected:
|
||||
QJsonObject _orignalStateValues;
|
||||
|
||||
// Device states
|
||||
|
||||
/// Is the device enabled?
|
||||
bool _isEnabled;
|
||||
|
||||
@@ -429,9 +460,6 @@ protected:
|
||||
/// Is the device in error state and stopped?
|
||||
bool _isDeviceInError;
|
||||
|
||||
/// Is the device in the switchOff process?
|
||||
bool _isInSwitchOff;
|
||||
|
||||
/// Timestamp of last write
|
||||
QDateTime _lastWriteTime;
|
||||
|
||||
@@ -459,6 +487,15 @@ private:
|
||||
/// @brief Stop refresh cycle
|
||||
void stopRefreshTimer();
|
||||
|
||||
/// Timer that enables a device (used to retry enablement, if enabled failed before)
|
||||
QTimer* _enableAttemptsTimer;
|
||||
|
||||
// Device configuration parameters
|
||||
|
||||
std::chrono::seconds _enableAttemptTimerInterval;
|
||||
int _enableAttempts;
|
||||
int _maxEnableAttempts;
|
||||
|
||||
/// Is last write refreshing enabled?
|
||||
bool _isRefreshEnabled;
|
||||
|
||||
|
@@ -94,16 +94,6 @@ signals:
|
||||
///
|
||||
int updateLeds(const std::vector<ColorRgb>& ledValues);
|
||||
|
||||
///
|
||||
/// @brief Enables the LED-Device.
|
||||
///
|
||||
void enable();
|
||||
|
||||
///
|
||||
/// @brief Disables the LED-Device.
|
||||
///
|
||||
void disable();
|
||||
|
||||
///
|
||||
/// @brief Switch the LEDs on.
|
||||
///
|
||||
@@ -113,7 +103,7 @@ signals:
|
||||
/// @brief Switch the LEDs off.
|
||||
///
|
||||
void switchOff();
|
||||
|
||||
|
||||
void stopLedDevice();
|
||||
|
||||
private slots:
|
||||
|
170
include/mdns/MdnsBrowser.h
Normal file
170
include/mdns/MdnsBrowser.h
Normal file
@@ -0,0 +1,170 @@
|
||||
#ifndef MDNS_BROWSER_H
|
||||
#define MDNS_BROWSER_H
|
||||
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
|
||||
#include <qmdnsengine/server.h>
|
||||
#include <qmdnsengine/service.h>
|
||||
|
||||
#include <qmdnsengine/browser.h>
|
||||
#include <qmdnsengine/cache.h>
|
||||
#include <qmdnsengine/resolver.h>
|
||||
#include <qmdnsengine/dns.h>
|
||||
#include <qmdnsengine/record.h>
|
||||
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
|
||||
// Utility includes
|
||||
#include <utils/Logger.h>
|
||||
|
||||
namespace {
|
||||
constexpr std::chrono::milliseconds DEFAULT_DISCOVER_TIMEOUT{ 500 };
|
||||
constexpr std::chrono::milliseconds DEFAULT_ADDRESS_RESOLVE_TIMEOUT{ 1000 };
|
||||
|
||||
} //End of constants
|
||||
|
||||
class MdnsBrowser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// Run MdnsBrowser as singleton
|
||||
|
||||
private:
|
||||
///
|
||||
/// @brief Browse for hyperion services in bonjour, constructed from HyperionDaemon
|
||||
/// Searching for hyperion http service by default
|
||||
///
|
||||
// Run MdnsBrowser as singleton
|
||||
MdnsBrowser(QObject* parent = nullptr);
|
||||
~MdnsBrowser() override;
|
||||
|
||||
public:
|
||||
|
||||
static MdnsBrowser& getInstance()
|
||||
{
|
||||
static MdnsBrowser* instance = new MdnsBrowser();
|
||||
return *instance;
|
||||
}
|
||||
|
||||
MdnsBrowser(const MdnsBrowser&) = delete;
|
||||
MdnsBrowser(MdnsBrowser&&) = delete;
|
||||
MdnsBrowser& operator=(const MdnsBrowser&) = delete;
|
||||
MdnsBrowser& operator=(MdnsBrowser&&) = delete;
|
||||
|
||||
QMdnsEngine::Service getFirstService(const QByteArray& serviceType, const QString& filter = ".*", const std::chrono::milliseconds waitTime = DEFAULT_DISCOVER_TIMEOUT) const;
|
||||
QJsonArray getServicesDiscoveredJson(const QByteArray& serviceType, const QString& filter = ".*", const std::chrono::milliseconds waitTime = std::chrono::milliseconds{ 0 }) const;
|
||||
|
||||
|
||||
void printCache(const QByteArray& name = QByteArray(), quint16 type = QMdnsEngine::ANY) const;
|
||||
|
||||
public slots:
|
||||
|
||||
///
|
||||
/// @brief Browse for a service of type
|
||||
///
|
||||
void browseForServiceType(const QByteArray& serviceType);
|
||||
|
||||
QHostAddress getHostFirstAddress(const QByteArray& hostname);
|
||||
|
||||
void onHostNameResolved(const QHostAddress& address);
|
||||
|
||||
QMdnsEngine::Record getServiceInstanceRecord(const QByteArray& serviceInstance, const std::chrono::milliseconds waitTime = DEFAULT_DISCOVER_TIMEOUT) const;
|
||||
|
||||
bool resolveAddress(Logger* log, const QString& hostname, QHostAddress& hostAddress, std::chrono::milliseconds timeout = DEFAULT_ADDRESS_RESOLVE_TIMEOUT);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Indicate that the specified service was updated
|
||||
*
|
||||
* This signal is emitted when the SRV record for a service (identified by
|
||||
* its name and type) or a TXT record has changed.
|
||||
*/
|
||||
void serviceFound(const QMdnsEngine::Service& service);
|
||||
|
||||
/**
|
||||
* @brief Indicate that the specified service was removed
|
||||
*
|
||||
* This signal is emitted when an essential record (PTR or SRV) is
|
||||
* expiring from the cache. This will also occur when an updated PTR or
|
||||
* SRV record is received with a TTL of 0.
|
||||
*/
|
||||
void serviceRemoved(const QMdnsEngine::Service& service);
|
||||
|
||||
void addressResolved(const QHostAddress address);
|
||||
|
||||
private slots:
|
||||
|
||||
void onServiceAdded(const QMdnsEngine::Service& service);
|
||||
void onServiceUpdated(const QMdnsEngine::Service& service);
|
||||
void onServiceRemoved(const QMdnsEngine::Service& service);
|
||||
|
||||
private:
|
||||
|
||||
// template <typename Func1, typename Func2, typename std::enable_if_t<std::is_member_pointer<Func2>::value, int> = 0>
|
||||
// static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
|
||||
// Func1 signal,
|
||||
// typename QtPrivate::FunctionPointer<Func2>::Object* receiver,
|
||||
// Func2 slot)
|
||||
// {
|
||||
// QMetaObject::Connection conn_normal = QObject::connect(sender, signal, receiver, slot);
|
||||
|
||||
// QMetaObject::Connection* conn_delete = new QMetaObject::Connection();
|
||||
|
||||
// *conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
|
||||
// QObject::disconnect(conn_normal);
|
||||
// QObject::disconnect(*conn_delete);
|
||||
// delete conn_delete;
|
||||
// });
|
||||
// return conn_normal;
|
||||
// }
|
||||
|
||||
template <typename Func1, typename Func2, typename std::enable_if_t<!std::is_member_pointer<Func2>::value, int> = 0>
|
||||
static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
|
||||
Func1 signal,
|
||||
Func2 slot)
|
||||
{
|
||||
QMetaObject::Connection conn_normal = QObject::connect(sender, signal, slot);
|
||||
|
||||
QMetaObject::Connection* conn_delete = new QMetaObject::Connection();
|
||||
|
||||
*conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
|
||||
QObject::disconnect(conn_normal);
|
||||
QObject::disconnect(*conn_delete);
|
||||
delete conn_delete;
|
||||
});
|
||||
return conn_normal;
|
||||
}
|
||||
|
||||
// template <typename Func1, typename Func2, typename std::enable_if_t<!std::is_member_pointer<Func2>::value, int> = 0>
|
||||
// static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
|
||||
// Func1 signal,
|
||||
// typename QtPrivate::FunctionPointer<Func2>::Object* receiver,
|
||||
// Func2 slot)
|
||||
// {
|
||||
// Q_UNUSED(receiver);
|
||||
// QMetaObject::Connection conn_normal = QObject::connect(sender, signal, slot);
|
||||
|
||||
// QMetaObject::Connection* conn_delete = new QMetaObject::Connection();
|
||||
|
||||
// *conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
|
||||
// QObject::disconnect(conn_normal);
|
||||
// QObject::disconnect(*conn_delete);
|
||||
// delete conn_delete;
|
||||
// });
|
||||
// return conn_normal;
|
||||
// }
|
||||
|
||||
/// The logger instance for mDNS-Service
|
||||
Logger* _log;
|
||||
|
||||
QMdnsEngine::Server _server;
|
||||
QMdnsEngine::Cache _cache;
|
||||
|
||||
QMap<QByteArray, QMdnsEngine::Browser*> _browsedServiceTypes;
|
||||
};
|
||||
|
||||
#endif // MDNSBROWSER_H
|
51
include/mdns/MdnsProvider.h
Normal file
51
include/mdns/MdnsProvider.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef MDNSPROVIDER_H
|
||||
#define MDNSPROVIDER_H
|
||||
|
||||
#include <qmdnsengine/server.h>
|
||||
#include <qmdnsengine/hostname.h>
|
||||
#include <qmdnsengine/provider.h>
|
||||
#include <qmdnsengine/service.h>
|
||||
|
||||
// Qt includes
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
|
||||
// Utility includes
|
||||
#include <utils/Logger.h>
|
||||
|
||||
class MdnsProvider : public QObject
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
MdnsProvider(QObject* parent = nullptr);
|
||||
~MdnsProvider() override;
|
||||
|
||||
QList<QByteArray> getServiceTypesProvided() const { return _providedServiceTypes.keys(); }
|
||||
|
||||
public slots:
|
||||
|
||||
///
|
||||
/// @brief Init MdnsProvider after thread start
|
||||
///
|
||||
void init();
|
||||
|
||||
void publishService (const QString& serviceType, quint16 servicePort, const QByteArray& serviceName = "");
|
||||
|
||||
private slots:
|
||||
|
||||
void onHostnameChanged(const QByteArray& hostname);
|
||||
|
||||
private:
|
||||
|
||||
/// The logger instance for mDNS-Service
|
||||
Logger* _log;
|
||||
|
||||
QMdnsEngine::Server* _server;
|
||||
QMdnsEngine::Hostname* _hostname;
|
||||
|
||||
/// map of services provided
|
||||
QMap<QByteArray, QMdnsEngine::Provider*> _providedServiceTypes;
|
||||
};
|
||||
|
||||
#endif // MDNSPROVIDER_H
|
38
include/mdns/MdnsServiceRegister.h
Normal file
38
include/mdns/MdnsServiceRegister.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef MDNSSERVICEREGISTER_H
|
||||
#define MDNSSERVICEREGISTER_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
|
||||
struct mdnsConfig
|
||||
{
|
||||
QByteArray serviceType;
|
||||
QString serviceNameFilter;
|
||||
};
|
||||
|
||||
typedef QMap<QString, mdnsConfig> MdnsServiceMap;
|
||||
|
||||
const MdnsServiceMap mDnsServiceMap = {
|
||||
//Hyperion
|
||||
{"jsonapi" , {"_hyperiond-json._tcp.local.", ".*"}},
|
||||
{"flatbuffer" , {"_hyperiond-flatbuf._tcp.local.", ".*"}},
|
||||
{"protobuffer" , {"_hyperiond-protobuf._tcp.local.", ".*"}},
|
||||
{"http" , {"_http._tcp.local.", ".*"}},
|
||||
{"https" , {"_https._tcp.local.", ".*"}},
|
||||
|
||||
//LED Devices
|
||||
{"cololight" , {"_hap._tcp.local.", "ColoLight.*"}},
|
||||
{"nanoleaf" , {"_nanoleafapi._tcp.local.", ".*"}},
|
||||
{"philipshue" , {"_hue._tcp.local.", ".*"}},
|
||||
{"wled" , {"_wled._tcp.local.", ".*"}},
|
||||
{"yeelight" , {"_hap._tcp.local.", "Yeelight.*|YLBulb.*"}},
|
||||
};
|
||||
|
||||
class MdnsServiceRegister {
|
||||
public:
|
||||
static QByteArray getServiceType(const QString &serviceType) { return mDnsServiceMap[serviceType].serviceType; }
|
||||
static QString getServiceNameFilter(const QString &serviceType) { return mDnsServiceMap[serviceType].serviceNameFilter; }
|
||||
static MdnsServiceMap getAllConfigs () { return mDnsServiceMap; }
|
||||
};
|
||||
|
||||
#endif // MDNSSERVICEREGISTER_H
|
@@ -24,6 +24,12 @@ public:
|
||||
ProtoServer(const QJsonDocument& config, QObject* parent = nullptr);
|
||||
~ProtoServer() override;
|
||||
|
||||
signals:
|
||||
///
|
||||
/// @emits whenever the server would like to announce its service details
|
||||
///
|
||||
void publishService(const QString& serviceType, quint16 servicePort, const QByteArray& serviceName = "");
|
||||
|
||||
public slots:
|
||||
///
|
||||
/// @brief Handle settings update
|
||||
|
@@ -31,6 +31,30 @@ struct ColorRgb
|
||||
static const ColorRgb YELLOW;
|
||||
/// 'White' RgbColor (255, 255, 255)
|
||||
static const ColorRgb WHITE;
|
||||
|
||||
ColorRgb() = default;
|
||||
|
||||
ColorRgb(uint8_t _red, uint8_t _green,uint8_t _blue):
|
||||
red(_red),
|
||||
green(_green),
|
||||
blue(_blue)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ColorRgb operator-(const ColorRgb& b) const
|
||||
{
|
||||
ColorRgb a(*this);
|
||||
a.red -= b.red;
|
||||
a.green -= b.green;
|
||||
a.blue -= b.blue;
|
||||
return a;
|
||||
}
|
||||
|
||||
QString toQString() const
|
||||
{
|
||||
return QString("(%1,%2,%3)").arg(red).arg(green).arg(blue);
|
||||
}
|
||||
};
|
||||
|
||||
/// Assert to ensure that the size of the structure is 'only' 3 bytes
|
||||
|
@@ -1,12 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <utils/Logger.h>
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QUrl>
|
||||
#include <QHostAddress>
|
||||
#include <QHostInfo>
|
||||
|
||||
#include <HyperionConfig.h>
|
||||
#include <utils/Logger.h>
|
||||
|
||||
#ifdef ENABLE_MDNS
|
||||
#include <mdns/MdnsBrowser.h>
|
||||
#endif
|
||||
|
||||
namespace NetUtils {
|
||||
|
||||
const int MAX_PORT = 65535;
|
||||
@@ -38,15 +43,15 @@ namespace NetUtils {
|
||||
///
|
||||
/// @brief Check if the port is in the valid range
|
||||
/// @param log The logger of the caller to print///
|
||||
/// @param[in] port The port to be tested
|
||||
/// @param[in] port The port to be tested (port = -1 is ignored for testing)
|
||||
/// @param[in] host A hostname/IP-address to make reference to during logging
|
||||
/// @return True on success else false
|
||||
///
|
||||
inline bool isValidPort(Logger* log, int port, const QString& host)
|
||||
{
|
||||
if (port <= 0 || port > MAX_PORT)
|
||||
if ((port <= 0 || port > MAX_PORT) && port != -1)
|
||||
{
|
||||
Error(log, "Invalid port [%d] for host: %s!", port, QSTRING_CSTR(host));
|
||||
Error(log, "Invalid port [%d] for host: (%s)! - Port must be in range [0 - %d]", port, QSTRING_CSTR(host), MAX_PORT);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -59,7 +64,7 @@ namespace NetUtils {
|
||||
/// @param[in/out] port The resolved port, if available.
|
||||
/// @return True on success else false
|
||||
///
|
||||
inline bool resolveHostPort(const QString& address, QString& host, quint16& port)
|
||||
inline bool resolveHostPort(const QString& address, QString& host, int& port)
|
||||
{
|
||||
if (address.isEmpty())
|
||||
{
|
||||
@@ -91,38 +96,109 @@ namespace NetUtils {
|
||||
}
|
||||
|
||||
///
|
||||
/// @brief Check if the port is in the valid range
|
||||
/// @param log The logger of the caller to print
|
||||
/// @param[in] address The port to be tested
|
||||
/// @param[out] hostAddress A hostname to make reference to during logging
|
||||
/// @return True on success else false
|
||||
/// @brief Resolve a hostname (DNS/mDNS) into an IP-address. A given IP address will be passed through
|
||||
/// @param[in/out] log The logger of the caller to print
|
||||
/// @param[in] hostname The hostname to be resolved
|
||||
/// @param[out] hostAddress The resolved IP-Address
|
||||
/// @return True on success else false
|
||||
///
|
||||
|
||||
inline bool resolveHostAddress(Logger* log, const QString& address, QHostAddress& hostAddress)
|
||||
inline bool resolveMdDnsHostToAddress(Logger* log, const QString& hostname, QHostAddress& hostAddress)
|
||||
{
|
||||
bool isHostAddressOK{ false };
|
||||
|
||||
if (hostAddress.setAddress(address))
|
||||
if (!hostname.isEmpty())
|
||||
{
|
||||
Debug(log, "Successfully parsed %s as an IP-address.", QSTRING_CSTR(hostAddress.toString()));
|
||||
isHostAddressOK = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QHostInfo hostInfo = QHostInfo::fromName(address);
|
||||
if (hostInfo.error() == QHostInfo::NoError)
|
||||
#ifdef ENABLE_MDNS
|
||||
if (hostname.endsWith(".local") || hostname.endsWith(".local."))
|
||||
{
|
||||
hostAddress = hostInfo.addresses().first();
|
||||
Debug(log, "Successfully resolved IP-address (%s) for hostname (%s).", QSTRING_CSTR(hostAddress.toString()), QSTRING_CSTR(address));
|
||||
isHostAddressOK = true;
|
||||
QHostAddress resolvedAddress;
|
||||
QMetaObject::invokeMethod(&MdnsBrowser::getInstance(), "resolveAddress",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, isHostAddressOK),
|
||||
Q_ARG(Logger*, log), Q_ARG(QString, hostname), Q_ARG(QHostAddress&, resolvedAddress));
|
||||
hostAddress = resolvedAddress;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
QString errortext = QString("Failed resolving IP-address for [%1], (%2) %3").arg(address).arg(hostInfo.error()).arg(hostInfo.errorString());
|
||||
Error(log, "%s", QSTRING_CSTR(errortext));
|
||||
isHostAddressOK = false;
|
||||
if (hostAddress.setAddress(hostname))
|
||||
{
|
||||
//Debug(log, "IP-address (%s) not required to be resolved.", QSTRING_CSTR(hostAddress.toString()));
|
||||
isHostAddressOK = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QHostInfo hostInfo = QHostInfo::fromName(hostname);
|
||||
if (hostInfo.error() == QHostInfo::NoError)
|
||||
{
|
||||
hostAddress = hostInfo.addresses().at(0);
|
||||
Debug(log, "Successfully resolved hostname (%s) to IP-address (%s)", QSTRING_CSTR(hostname), QSTRING_CSTR(hostAddress.toString()));
|
||||
isHostAddressOK = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QString errortext = QString("Failed resolving hostname (%1) to IP-address. Error: (%2) %3").arg(hostname).arg(hostInfo.error()).arg(hostInfo.errorString());
|
||||
Error(log, "%s", QSTRING_CSTR(errortext));
|
||||
isHostAddressOK = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isHostAddressOK;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// @brief Resolve a hostname(DNS) or mDNS service name into an IP-address. A given IP address will be passed through
|
||||
/// @param[in/out] log The logger of the caller to print
|
||||
/// @param[in] hostname The hostname/mDNS service name to be resolved
|
||||
/// @param[out] hostAddress The resolved IP-Address
|
||||
/// @param[in/out] port The port provided by the mDNS service, if not mDNS the input port is returned
|
||||
/// @return True on success else false
|
||||
///
|
||||
inline bool resolveHostToAddress(Logger* log, const QString& hostname, QHostAddress& hostAddress, int& port)
|
||||
{
|
||||
bool areHostAddressPartOK{ false };
|
||||
QString target {hostname};
|
||||
|
||||
#ifdef ENABLE_MDNS
|
||||
if (hostname.endsWith("._tcp.local"))
|
||||
{
|
||||
//Treat hostname as service instance name that requires to be resolved into an mDNS-Hostname first
|
||||
QMdnsEngine::Record service = MdnsBrowser::getInstance().getServiceInstanceRecord(hostname.toUtf8());
|
||||
if (!service.target().isEmpty())
|
||||
{
|
||||
Info(log, "Resolved service [%s] to mDNS hostname [%s], service port [%d]", QSTRING_CSTR(hostname), service.target().constData(), service.port());
|
||||
target = service.target();
|
||||
port = service.port();
|
||||
}
|
||||
else
|
||||
{
|
||||
Error(log, "Cannot resolve mDNS hostname for given service [%s]!", QSTRING_CSTR(hostname));
|
||||
return areHostAddressPartOK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QHostAddress resolvedAddress;
|
||||
if (NetUtils::resolveMdDnsHostToAddress(log, target, resolvedAddress))
|
||||
{
|
||||
hostAddress = resolvedAddress;
|
||||
if (hostname != hostAddress.toString())
|
||||
{
|
||||
Info(log, "Resolved hostname (%s) to IP-address (%s)", QSTRING_CSTR(hostname), QSTRING_CSTR(hostAddress.toString()));
|
||||
}
|
||||
|
||||
if (NetUtils::isValidPort(log, port, hostAddress.toString()))
|
||||
{
|
||||
areHostAddressPartOK = true;
|
||||
}
|
||||
}
|
||||
return areHostAddressPartOK;
|
||||
}
|
||||
|
||||
inline bool resolveHostToAddress(Logger* log, const QString& hostname, QHostAddress& hostAddress)
|
||||
{
|
||||
int ignoredPort {MAX_PORT};
|
||||
return resolveHostToAddress(log, hostname, hostAddress, ignoredPort);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@
|
||||
// settings
|
||||
#include <utils/settings.h>
|
||||
|
||||
class BonjourServiceRegister;
|
||||
class StaticFileServing;
|
||||
class QtHttpServer;
|
||||
|
||||
@@ -52,6 +51,11 @@ signals:
|
||||
///
|
||||
void portChanged(quint16 port);
|
||||
|
||||
///
|
||||
/// @emits whenever the server would like to announce its service details
|
||||
///
|
||||
void publishService(const QString& serviceType, quint16 servicePort, const QByteArray& serviceName = "");
|
||||
|
||||
public slots:
|
||||
///
|
||||
/// @brief Init server after thread start
|
||||
@@ -93,8 +97,6 @@ private:
|
||||
const QString WEBSERVER_DEFAULT_CRT_PATH = ":/hyperion.crt";
|
||||
const QString WEBSERVER_DEFAULT_KEY_PATH = ":/hyperion.key";
|
||||
quint16 WEBSERVER_DEFAULT_PORT = 8090;
|
||||
|
||||
BonjourServiceRegister * _serviceRegister = nullptr;
|
||||
};
|
||||
|
||||
#endif // WEBSERVER_H
|
||||
|
Reference in New Issue
Block a user