add zeroconf support based on qt4 libraries (#667)

* Removed -HUP so the default -TERM signal is sent instead.
- hyperiond only listens for TERM and INT. HUP is often used to get an exe to reread its config

Changed pgrep to add '-x' so it wont partial match on the exe name.
- I have multiple instances with multiple hyperiond-instance1 names
- this ensures the service script only kills the right process

* reversing errant change to hyperion.systemd.sh

* added bonjour/zeroconf service discovery to the json interface.

When clients are also modified, they can
- find hyperiond on the network much more quickly than ping/portscan;
- find multiple instances running on different ports instead of assuming 19444

* Moved zeroconf calls to hyperiond.cpp

* Added mDNS/zerconf/bonjour registration for proto server

Added config options.
        "jsonServer" :
        {
                "port" : 49444,
//              "mDNSDescr" : "hyperiond jsonServer blah de blah",
                "mDNSService" : "_hyperiond_json._tcp"
        },

* cleaned up a couple of compiler warnings

* moved bitpair_to_byte initialiser to (hopefully) work with older GCC

* compiler warning in udp driver
removed some tabs in ws2812b.cpp

* formatting - spaces to tabs

* moved rpi_281x to tag sk6812-v1.0

* moving to my fork of rpi_281x

* Now uses the led device name and hostname to create the annouce name


Former-commit-id: abfa51bcf359cafa63338181c1b83ecfd231bc87
This commit is contained in:
penfold42 2016-06-01 06:55:11 +10:00 committed by brindosch
parent 03cee33784
commit 6fbfda03fa
14 changed files with 530 additions and 1 deletions

View File

@ -15,6 +15,7 @@ SET ( DEFAULT_X11 OFF )
SET ( DEFAULT_SPIDEV OFF )
SET ( DEFAULT_WS2812BPWM OFF )
SET ( DEFAULT_WS281XPWM OFF )
SET ( DEFAULT_ZEROCONF OFF )
if (APPLE)
SET ( DEFAULT_OSX ON )
@ -39,6 +40,9 @@ else ()
endif ()
# set the build options
option(ENABLE_ZEROCONF "Enable the avahi/zeroconf announce" ${DEFAULT_ZEROCONF} )
message(STATUS "ENABLE_ZEROCONF = " ${ENABLE_ZEROCONF})
option(ENABLE_AMLOGIC "Enable the AMLOGIC video grabber" ${DEFAULT_AMLOGIC} )
message(STATUS "ENABLE_AMLOGIC = " ${ENABLE_AMLOGIC})

View File

@ -30,4 +30,7 @@
// Define to enable the osx grabber
#cmakedefine ENABLE_OSX
// Define to enable the bonjour/zeroconf publishing
#cmakedefine ENABLE_ZEROCONF
#define HYPERION_VERSION_ID "${HYPERION_VERSION_ID}"

60
include/bonjour/bonjourrecord.h Executable file
View File

@ -0,0 +1,60 @@
/*
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() {}
BonjourRecord(const QString &name, const QString &regType, const QString &domain)
: serviceName(name), registeredType(regType), replyDomain(domain)
{}
BonjourRecord(const char *name, const char *regType, const char *domain)
{
serviceName = QString::fromUtf8(name);
registeredType = QString::fromUtf8(regType);
replyDomain = QString::fromUtf8(domain);
}
QString serviceName;
QString registeredType;
QString replyDomain;
bool operator==(const BonjourRecord &other) const {
return serviceName == other.serviceName
&& registeredType == other.registeredType
&& replyDomain == other.replyDomain;
}
};
Q_DECLARE_METATYPE(BonjourRecord)
#endif // BONJOURRECORD_H

View File

@ -0,0 +1,66 @@
/*
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;
#include <dns_sd.h>
class BonjourServiceRegister : public QObject
{
Q_OBJECT
public:
BonjourServiceRegister(QObject *parent = 0);
~BonjourServiceRegister();
void registerService(const BonjourRecord &record, quint16 servicePort);
inline BonjourRecord registeredRecord() const {return finalRecord; }
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;
};
#endif // BONJOURSERVICEREGISTER_H

View File

@ -11,6 +11,10 @@ if (ENABLE_PROTOBUF)
add_subdirectory(protoserver)
endif ()
if (ENABLE_ZEROCONF)
add_subdirectory(bonjour)
endif (ENABLE_ZEROCONF)
add_subdirectory(boblightserver)
add_subdirectory(leddevice)
add_subdirectory(utils)

View File

@ -0,0 +1,52 @@
# Define the current source locations
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/bonjour)
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/bonjour)
# Group the headers that go through the MOC compiler
set(Bonjour_QT_HEADERS
${CURRENT_HEADER_DIR}/bonjourrecord.h
${CURRENT_HEADER_DIR}/bonjourserviceregister.h
)
set(Bonjour_HEADERS
)
set(Bonjour_SOURCES
${CURRENT_SOURCE_DIR}/bonjourserviceregister.cpp
)
set(Bonjour_RESOURCES
)
if(ENABLE_QT5)
qt5_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS})
qt5_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress")
else(ENABLE_QT5)
qt4_wrap_cpp(Bonjour_HEADERS_MOC ${Bonjour_QT_HEADERS})
qt4_add_resources(Bonjour_RESOURCES_RCC ${Bonjour_RESOURCES} OPTIONS "-no-compress")
endif(ENABLE_QT5)
add_library(bonjour
${Bonjour_HEADERS}
${Bonjour_QT_HEADERS}
${Bonjour_SOURCES}
${Bonjour_RESOURCES}
${Bonjour_HEADERS_MOC}
${Bonjour_RESOURCES_RCC}
)
if(ENABLE_QT5)
qt5_use_modules(bonjour Widgets Network)
endif(ENABLE_QT5)
target_link_libraries(bonjour
libdns_sd.a
libavahi-client.a
libavahi-common.a
libavahi-core.a
libavahi-qt4.a
libdbus-1.a
hyperion
hyperion-utils
${QT_LIBRARIES})

View File

@ -0,0 +1,102 @@
/*
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.
*/
//#include "bonjourserviceregister.h"
#include <bonjour/bonjourserviceregister.h>
#include <QtCore/QSocketNotifier>
BonjourServiceRegister::BonjourServiceRegister(QObject *parent)
: QObject(parent), dnssref(0), bonjourSocket(0)
{
}
BonjourServiceRegister::~BonjourServiceRegister()
{
if (dnssref) {
DNSServiceRefDeallocate(dnssref);
dnssref = 0;
}
}
void BonjourServiceRegister::registerService(const BonjourRecord &record, quint16 servicePort)
{
if (dnssref) {
qWarning("Warning: Already registered a service for this object, aborting new register");
return;
}
quint16 bigEndianPort = servicePort;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
{
bigEndianPort = 0 | ((servicePort & 0x00ff) << 8) | ((servicePort & 0xff00) >> 8);
}
#endif
DNSServiceErrorType err = DNSServiceRegister(&dnssref, 0, 0, record.serviceName.toUtf8().constData(),
record.registeredType.toUtf8().constData(),
record.replyDomain.isEmpty() ? 0
: record.replyDomain.toUtf8().constData(), 0,
bigEndianPort, 0, 0, bonjourRegisterService, this);
if (err != kDNSServiceErr_NoError) {
emit error(err);
} else {
int sockfd = DNSServiceRefSockFD(dnssref);
if (sockfd == -1) {
emit error(kDNSServiceErr_Invalid);
} else {
bonjourSocket = new QSocketNotifier(sockfd, QSocketNotifier::Read, this);
connect(bonjourSocket, SIGNAL(activated(int)), this, SLOT(bonjourSocketReadyRead()));
}
}
}
void BonjourServiceRegister::bonjourSocketReadyRead()
{
DNSServiceErrorType err = DNSServiceProcessResult(dnssref);
if (err != kDNSServiceErr_NoError)
emit error(err);
}
void BonjourServiceRegister::bonjourRegisterService(DNSServiceRef, DNSServiceFlags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain,
void *data)
{
BonjourServiceRegister *serviceRegister = static_cast<BonjourServiceRegister *>(data);
if (errorCode != kDNSServiceErr_NoError) {
emit serviceRegister->error(errorCode);
} else {
serviceRegister->finalRecord = BonjourRecord(QString::fromUtf8(name),
QString::fromUtf8(regtype),
QString::fromUtf8(domain));
emit serviceRegister->serviceRegistered(serviceRegister->finalRecord);
}
}

View File

@ -0,0 +1,15 @@
HEADERS = server.h \
bonjourserviceregister.h
SOURCES = server.cpp \
main.cpp \
bonjourserviceregister.cpp
QT += network
!mac:x11:LIBS+=-ldns_sd
win32 {
LIBS+=-ldnssd
# Add your path to bonjour here.
LIBPATH=C:/Temp/mDNSResponder-107.6/mDNSWindows/DLL/Debug
INCLUDEPATH += c:/Temp/mDNSResponder-107.6/mDNSShared
}

39
libsrc/bonjour/main.cpp Executable file
View File

@ -0,0 +1,39 @@
/****************************************************************************
**
** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the example classes of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include <QApplication>
#include <QtCore>
#include <stdlib.h>
#include "server.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Server server;
server.show();
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
int x = server.exec();
return x;
}

96
libsrc/bonjour/server.cpp Executable file
View File

@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the example classes of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include <QtGui>
#include <QtNetwork>
#include <stdlib.h>
#include "server.h"
#include "bonjourserviceregister.h"
Server::Server(QWidget *parent)
: QDialog(parent)
{
setWindowModality(Qt::ApplicationModal);
statusLabel = new QLabel;
quitButton = new QPushButton(tr("Quit"));
quitButton->setAutoDefault(false);
tcpServer = new QTcpServer(this);
if (!tcpServer->listen()) {
QMessageBox::critical(this, tr("Fortune Server"),
tr("Unable to start the server: %1.")
.arg(tcpServer->errorString()));
close();
return;
}
statusLabel->setText(tr("The server is running on port %1.\n"
"Run the Fortune Client example now.")
.arg(tcpServer->serverPort()));
fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
<< tr("You've got to think about tomorrow.")
<< tr("You will be surprised by a loud noise.")
<< tr("You will feel hungry again in another hour.")
<< tr("You might have mail.")
<< tr("You cannot kill time without injuring eternity.")
<< tr("Computers are not intelligent. They only think they are.");
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune()));
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
bonjourRegister = new BonjourServiceRegister(this);
bonjourRegister->registerService(BonjourRecord(tr("Fortune Server on %1").arg(QHostInfo::localHostName()),
QLatin1String("_trollfortune._tcp"), QString()),
tcpServer->serverPort());
setWindowTitle(tr("Fortune Server"));
}
void Server::sendFortune()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << fortunes.at(qrand() % fortunes.size());
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()),
clientConnection, SLOT(deleteLater()));
clientConnection->write(block);
clientConnection->disconnectFromHost();
}

52
libsrc/bonjour/server.h Executable file
View File

@ -0,0 +1,52 @@
/****************************************************************************
**
** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the example classes of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#ifndef SERVER_H
#define SERVER_H
#include <QDialog>
class QLabel;
class QPushButton;
class QTcpServer;
class BonjourServiceRegister;
class Server : public QDialog
{
Q_OBJECT
public:
Server(QWidget *parent = 0);
private slots:
void sendFortune();
private:
QLabel *statusLabel;
QPushButton *quitButton;
QTcpServer *tcpServer;
QStringList fortunes;
BonjourServiceRegister *bonjourRegister;
};
#endif

View File

@ -29,6 +29,7 @@ JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) :
// make sure the resources are loaded (they may be left out after static linking
Q_INIT_RESOURCE(JsonSchemas);
}
JsonServer::~JsonServer()

View File

@ -35,9 +35,12 @@ if (ENABLE_PROTOBUF)
target_link_libraries(hyperiond protoserver)
endif ()
if (ENABLE_ZEROCONF)
target_link_libraries(hyperiond bonjour)
endif()
install ( TARGETS hyperiond DESTINATION "bin" COMPONENT ambilight )
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/effects DESTINATION "share/hyperion/" COMPONENT ambilight )
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT ambilight )
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/config DESTINATION "share/hyperion/" COMPONENT ambilight )

View File

@ -52,6 +52,12 @@
// Effect engine includes
#include <effectengine/EffectEngine.h>
#ifdef ENABLE_ZEROCONF
#include <bonjour/bonjourserviceregister.h>
#include <bonjour/bonjourrecord.h>
#include <QHostInfo>
#endif
// JsonServer includes
#include <jsonserver/JsonServer.h>
@ -188,6 +194,19 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer
const Json::Value & jsonServerConfig = config["jsonServer"];
jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt());
std::cout << "INFO: Json server created and started on port " << jsonServer->getPort() << std::endl;
#ifdef ENABLE_ZEROCONF
const Json::Value & deviceConfig = config["device"];
const std::string deviceName = deviceConfig.get("name", "").asString();
const std::string hostname = QHostInfo::localHostName().toStdString();
const std::string mDNSDescr = jsonServerConfig.get("mDNSDescr", hostname).asString();
const std::string mDNSService = jsonServerConfig.get("mDNSService", "_hyperiond_json._tcp").asString();
BonjourServiceRegister *bonjourRegister_json;
bonjourRegister_json = new BonjourServiceRegister();
bonjourRegister_json->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(),
QString()), jsonServerConfig["port"].asUInt());
std::cout << "INFO: Json mDNS responder started" << std::endl;
#endif
}
// Create Proto server if configuration is present
@ -196,6 +215,19 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer
const Json::Value & protoServerConfig = config["protoServer"];
protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() );
std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl;
#ifdef ENABLE_ZEROCONF
const Json::Value & deviceConfig = config["device"];
const std::string deviceName = deviceConfig.get("name", "").asString();
const std::string hostname = QHostInfo::localHostName().toStdString();
const std::string mDNSDescr = protoServerConfig.get("mDNSDescr", hostname).asString();
const std::string mDNSService = protoServerConfig.get("mDNSService", "_hyperiond_proto._tcp").asString();
BonjourServiceRegister *bonjourRegister_proto;
bonjourRegister_proto = new BonjourServiceRegister();
bonjourRegister_proto->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr).c_str(), mDNSService.c_str(),
QString()), protoServerConfig["port"].asUInt());
std::cout << "INFO: Proto mDNS responder started" << std::endl;
#endif
}
// Create Boblight server if configuration is present