populate zeroconf/avahi/bonjour records via json api (#419)

* start of integrating a bonkour service browser

* some experiments

* blub

* bonjour browser via jsonrpc ...

* fix indention

* - make leddevice as component
- extend sysinfo with domain
- add more data for  bonjour browser (e.g. split domain and hostname)

* code cleanup

* add translation

* use component names instead of ids

* fix compile
This commit is contained in:
redPanther
2017-03-21 17:55:46 +01:00
committed by GitHub
parent 9a0e1daf7b
commit 0aa467cceb
25 changed files with 601 additions and 95 deletions

View File

@@ -3,6 +3,7 @@
#include <cassert>
#include <exception>
#include <sstream>
#include <unistd.h>
// QT includes
#include <QDateTime>
@@ -13,6 +14,7 @@
#include <QCryptographicHash>
#include <QFile>
#include <QFileInfo>
#include <QHostInfo>
// hyperion include
#include <hyperion/Hyperion.h>
@@ -317,8 +319,7 @@ QSize Hyperion::getLedLayoutGridSize(const QJsonValue& ledsConfig)
LinearColorSmoothing * Hyperion::createColorSmoothing(const QJsonObject & smoothingConfig, LedDevice* leddevice)
{
LinearColorSmoothing * Hyperion::createColorSmoothing(const QJsonObject & smoothingConfig, LedDevice* leddevice){
QString type = smoothingConfig["type"].toString("linear").toLower();
LinearColorSmoothing * device = nullptr;
type = "linear"; // TODO currently hardcoded type, delete it if we have more types
@@ -390,12 +391,15 @@ Hyperion::Hyperion(const QJsonObject &qjsonConfig, const QString configFile)
, _qjsonConfig(qjsonConfig)
, _configFile(configFile)
, _timer()
, _timerBonjourResolver()
, _log(CORE_LOGGER)
, _hwLedCount(_ledString.leds().size())
, _sourceAutoSelectEnabled(true)
, _configHash()
, _ledGridSize(getLedLayoutGridSize(qjsonConfig["leds"]))
, _prevCompId(hyperion::COMP_INVALID)
, _bonjourBrowser(this)
, _bonjourResolver(this)
{
registerPriority("Off", PriorityMuxer::LOWEST_PRIORITY);
@@ -405,6 +409,10 @@ Hyperion::Hyperion(const QJsonObject &qjsonConfig, const QString configFile)
}
// set color correction activity state
const QJsonObject& color = qjsonConfig["color"].toObject();
_bonjourBrowser.browseForServiceType(QLatin1String("_hyperiond-http._tcp"));
connect(&_bonjourBrowser, SIGNAL(currentBonjourRecordsChanged(const QList<BonjourRecord>&)),this, SLOT(currentBonjourRecordsChanged(const QList<BonjourRecord> &)));
connect(&_bonjourResolver, SIGNAL(bonjourRecordResolved(const QHostInfo &, int)), this, SLOT(bonjourRecordResolved(const QHostInfo &, int)));
// initialize the image processor factory
_ledMAppingType = ImageProcessor::mappingTypeToInt(color["imageToLedMappingType"].toString());
@@ -416,11 +424,17 @@ Hyperion::Hyperion(const QJsonObject &qjsonConfig, const QString configFile)
_device = LedDeviceFactory::construct(qjsonConfig["device"].toObject(),_hwLedCount);
_deviceSmooth = createColorSmoothing(qjsonConfig["smoothing"].toObject(), _device);
getComponentRegister().componentStateChanged(hyperion::COMP_SMOOTHING, _deviceSmooth->componentState());
getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState());
// setup the timer
_timer.setSingleShot(true);
QObject::connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
_timerBonjourResolver.setSingleShot(false);
_timerBonjourResolver.setInterval(1000);
QObject::connect(&_timerBonjourResolver, SIGNAL(timeout()), this, SLOT(bonjourResolve()));
_timerBonjourResolver.start();
// create the effect engine
_effectEngine = new EffectEngine(this,qjsonConfig["effects"].toObject());
@@ -470,6 +484,48 @@ unsigned Hyperion::getLedCount() const
return _ledString.leds().size();
}
void Hyperion::currentBonjourRecordsChanged(const QList<BonjourRecord> &list)
{
_hyperionSessions.clear();
for ( auto rec : list )
{
_hyperionSessions.insert(rec.serviceName, rec);
}
}
void Hyperion::bonjourRecordResolved(const QHostInfo &hostInfo, int port)
{
if ( _hyperionSessions.contains(_bonjourCurrentServiceToResolve))
{
QString host = hostInfo.hostName();
QString domain = _hyperionSessions[_bonjourCurrentServiceToResolve].replyDomain;
if (host.endsWith("."+domain))
{
host.remove(host.length()-domain.length()-1,domain.length()+1);
}
_hyperionSessions[_bonjourCurrentServiceToResolve].hostName = host;
_hyperionSessions[_bonjourCurrentServiceToResolve].port = port;
Debug(_log, "found hyperion session: %s:%d",QSTRING_CSTR(hostInfo.hostName()), port);
}
}
void Hyperion::bonjourResolve()
{
for(auto key : _hyperionSessions.keys())
{
if (_hyperionSessions[key].port < 0)
{
_bonjourCurrentServiceToResolve = key;
_bonjourResolver.resolveBonjourRecord(_hyperionSessions[key]);
break;
}
}
}
Hyperion::BonjourRegister Hyperion::getHyperionSessions()
{
return _hyperionSessions;
}
bool Hyperion::configModified()
{
@@ -507,19 +563,19 @@ void Hyperion::registerPriority(const QString &name, const int priority/*, const
{
Info(_log, "Register new input source named '%s' for priority channel '%d'", QSTRING_CSTR(name), priority );
for(auto const &entry : _priorityRegister)
for(auto key : _priorityRegister.keys())
{
WarningIf( ( entry.first != name && entry.second == priority), _log,
"Input source '%s' uses same priority channel (%d) as '%s'.", QSTRING_CSTR(name), priority, QSTRING_CSTR(entry.first));
WarningIf( ( key != name && _priorityRegister.value(key) == priority), _log,
"Input source '%s' uses same priority channel (%d) as '%s'.", QSTRING_CSTR(name), priority, QSTRING_CSTR(key));
}
_priorityRegister.emplace(name,priority);
_priorityRegister.insert(name, priority);
}
void Hyperion::unRegisterPriority(const QString &name)
{
Info(_log, "Unregister input source named '%s' from priority register", QSTRING_CSTR(name));
_priorityRegister.erase(name);
_priorityRegister.remove(name);
}
void Hyperion::setSourceAutoSelectEnabled(bool enabled)
@@ -550,14 +606,20 @@ bool Hyperion::setCurrentSourcePriority(int priority )
void Hyperion::setComponentState(const hyperion::Components component, const bool state)
{
if (component == hyperion::COMP_SMOOTHING)
switch (component)
{
_deviceSmooth->setEnable(state);
getComponentRegister().componentStateChanged(hyperion::COMP_SMOOTHING, _deviceSmooth->componentState());
}
else
{
emit componentStateChanged(component, state);
case hyperion::COMP_SMOOTHING:
_deviceSmooth->setEnable(state);
getComponentRegister().componentStateChanged(hyperion::COMP_SMOOTHING, _deviceSmooth->componentState());
break;
case hyperion::COMP_LEDDEVICE:
_device->setEnable(state);
getComponentRegister().componentStateChanged(hyperion::COMP_LEDDEVICE, _device->componentState());
break;
default:
emit componentStateChanged(component, state);
}
}
@@ -785,10 +847,13 @@ void Hyperion::update()
}
// Write the data to the device
if (_deviceSmooth->enabled())
_deviceSmooth->setLedValues(_ledBuffer);
else
_device->setLedValues(_ledBuffer);
if (_device->enabled())
{
if (_deviceSmooth->enabled())
_deviceSmooth->setLedValues(_ledBuffer);
else
_device->setLedValues(_ledBuffer);
}
// Start the timeout-timer
if (priorityInfo.timeoutTime_ms == -1)
@@ -800,4 +865,5 @@ void Hyperion::update()
int timeout_ms = std::max(0, int(priorityInfo.timeoutTime_ms - QDateTime::currentMSecsSinceEpoch()));
_timer.start(timeout_ms);
}
}