bluos: Add Qt6 support

This commit is contained in:
Simon Stürz 2025-08-07 15:08:47 +02:00
parent 68d8cf1c40
commit 259e0c7d1d
5 changed files with 77 additions and 75 deletions

View File

@ -38,9 +38,9 @@
BluOS::BluOS(NetworkAccessManager *networkmanager, QHostAddress hostAddress, int port, QObject *parent) : BluOS::BluOS(NetworkAccessManager *networkmanager, QHostAddress hostAddress, int port, QObject *parent) :
QObject(parent), QObject(parent),
m_networkManager(networkmanager),
m_hostAddress(hostAddress), m_hostAddress(hostAddress),
m_port(port), m_port(port)
m_networkManager(networkmanager)
{ {
} }
@ -121,7 +121,7 @@ QUuid BluOS::setVolume(uint volume)
int volume = 0; int volume = 0;
bool mute = false; bool mute = false;
if (xml.readNextStartElement()) { if (xml.readNextStartElement()) {
if (xml.name() == "volume") { if (xml.name() == QString("volume")) {
if(xml.attributes().hasAttribute("mute")) { if(xml.attributes().hasAttribute("mute")) {
mute = xml.attributes().value("mute").toInt(); mute = xml.attributes().value("mute").toInt();
} }
@ -277,7 +277,7 @@ QUuid BluOS::setRepeat(RepeatMode repeatMode)
return; return;
} }
if (xml.readNextStartElement()) { if (xml.readNextStartElement()) {
if (xml.name() == "playlist") { if (xml.name() == QString("playlist")) {
if (xml.attributes().hasAttribute("repeat")) { if (xml.attributes().hasAttribute("repeat")) {
RepeatMode mode = RepeatMode(xml.attributes().value("repeat").toInt()); RepeatMode mode = RepeatMode(xml.attributes().value("repeat").toInt());
emit repeatModeReceived(mode); emit repeatModeReceived(mode);
@ -323,9 +323,9 @@ QUuid BluOS::listPresets()
} }
QList<Preset> presetList; QList<Preset> presetList;
if (xml.readNextStartElement()) { if (xml.readNextStartElement()) {
if (xml.name() == "presets") { if (xml.name() == QString("presets")) {
while(xml.readNextStartElement()){ while(xml.readNextStartElement()){
if(xml.name() == "preset"){ if(xml.name() == QString("preset")){
Preset preset; Preset preset;
if (xml.attributes().hasAttribute("id")) { if (xml.attributes().hasAttribute("id")) {
preset.Id = xml.attributes().value("id").toInt(); preset.Id = xml.attributes().value("id").toInt();
@ -417,9 +417,9 @@ QUuid BluOS::getSources()
} }
QList<Source> sourceList; QList<Source> sourceList;
if (xml.readNextStartElement()) { if (xml.readNextStartElement()) {
if (xml.name() == "browse") { if (xml.name() == QString("browse")) {
while(xml.readNextStartElement()){ while(xml.readNextStartElement()){
if(xml.name() == "item"){ if(xml.name() == QString("item")){
Source source; Source source;
if (xml.attributes().hasAttribute("text")) { if (xml.attributes().hasAttribute("text")) {
source.Text = xml.attributes().value("text").toString(); source.Text = xml.attributes().value("text").toString();
@ -483,9 +483,9 @@ QUuid BluOS::browseSource(const QString &key)
} }
QList<Source> sourceList; QList<Source> sourceList;
if (xml.readNextStartElement()) { if (xml.readNextStartElement()) {
if (xml.name() == "browse") { if (xml.name() == QString("browse")) {
while(xml.readNextStartElement()){ while(xml.readNextStartElement()){
if(xml.name() == "item"){ if(xml.name() == QString("item")){
Source source; Source source;
if (xml.attributes().hasAttribute("text")) { if (xml.attributes().hasAttribute("text")) {
source.Text = xml.attributes().value("text").toString(); source.Text = xml.attributes().value("text").toString();
@ -648,23 +648,23 @@ bool BluOS::parseState(const QByteArray &state)
StatusResponse statusResponse; StatusResponse statusResponse;
if (xml.readNextStartElement()) { if (xml.readNextStartElement()) {
if (xml.name() == "status") { if (xml.name() == QString("status")) {
while(xml.readNextStartElement()){ while(xml.readNextStartElement()){
if(xml.name() == "artist"){ if(xml.name() == QString("artist")){
statusResponse.Artist = xml.readElementText(); statusResponse.Artist = xml.readElementText();
} else if(xml.name() == "album"){ } else if(xml.name() == QString("album")){
statusResponse.Album = xml.readElementText(); statusResponse.Album = xml.readElementText();
} else if(xml.name() == "name"){ } else if(xml.name() == QString("name")){
statusResponse.Name = xml.readElementText(); statusResponse.Name = xml.readElementText();
} else if(xml.name() == "service"){ } else if(xml.name() == QString("service")){
statusResponse.Service = xml.readElementText(); statusResponse.Service = xml.readElementText();
} else if(xml.name() == "serviceIcon"){ } else if(xml.name() == QString("serviceIcon")){
statusResponse.ServiceIcon = xml.readElementText(); statusResponse.ServiceIcon = xml.readElementText();
} else if(xml.name() == "shuffle"){ } else if(xml.name() == QString("shuffle")){
statusResponse.Shuffle = xml.readElementText().toInt(); statusResponse.Shuffle = xml.readElementText().toInt();
} else if(xml.name() == "repeat"){ } else if(xml.name() == QString("repeat")){
statusResponse.Shuffle = xml.readElementText().toInt(); statusResponse.Shuffle = xml.readElementText().toInt();
} else if(xml.name() == "state"){ } else if(xml.name() == QString("state")){
QString playback = xml.readElementText(); QString playback = xml.readElementText();
if (playback == "play") { if (playback == "play") {
statusResponse.State = PlaybackState::Playing; statusResponse.State = PlaybackState::Playing;
@ -680,15 +680,15 @@ bool BluOS::parseState(const QByteArray &state)
statusResponse.State = PlaybackState::Stopped; statusResponse.State = PlaybackState::Stopped;
qCWarning(dcBluOS()) << "State response, unhandled playback mode" << playback; qCWarning(dcBluOS()) << "State response, unhandled playback mode" << playback;
} }
} else if(xml.name() == "volume"){ } else if(xml.name() == QString("volume")){
statusResponse.Volume = xml.readElementText().toInt(); statusResponse.Volume = xml.readElementText().toInt();
} else if(xml.name() == "mute"){ } else if(xml.name() == QString("mute")){
statusResponse.Mute = xml.readElementText().toInt(); statusResponse.Mute = xml.readElementText().toInt();
} else if(xml.name() == "image") { } else if(xml.name() == QString("image")) {
statusResponse.Image = xml.readElementText(); statusResponse.Image = xml.readElementText();
} else if(xml.name() == "title1") { } else if(xml.name() == QString("title1")) {
statusResponse.Title = xml.readElementText(); statusResponse.Title = xml.readElementText();
} else if(xml.name() == "group") { } else if(xml.name() == QString("group")) {
statusResponse.Group = xml.readElementText(); statusResponse.Group = xml.readElementText();
} else { } else {
xml.skipCurrentElement(); xml.skipCurrentElement();

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -31,13 +31,13 @@
#ifndef BLUOS_H #ifndef BLUOS_H
#define BLUOS_H #define BLUOS_H
#include <QObject>
#include <QTimer>
#include <QHostAddress>
#include <QUuid> #include <QUuid>
#include <QTimer>
#include <QObject>
#include <QHostAddress>
#include "network/networkaccessmanager.h" #include <integrations/thing.h>
#include "integrations/thing.h" #include <network/networkaccessmanager.h>
class BluOS : public QObject class BluOS : public QObject
{ {
@ -98,6 +98,7 @@ public:
}; };
explicit BluOS(NetworkAccessManager *networkManager, QHostAddress hostAddress, int port, QObject *parent = nullptr); explicit BluOS(NetworkAccessManager *networkManager, QHostAddress hostAddress, int port, QObject *parent = nullptr);
int port(); int port();
QHostAddress hostAddress(); QHostAddress hostAddress();
@ -130,24 +131,24 @@ public:
QUuid removeGroupPlayer(QHostAddress address, int port); QUuid removeGroupPlayer(QHostAddress address, int port);
private: private:
NetworkAccessManager *m_networkManager = nullptr;
QHostAddress m_hostAddress; QHostAddress m_hostAddress;
int m_port; int m_port;
NetworkAccessManager *m_networkManager = nullptr;
QUuid playBackControl(PlaybackCommand command); QUuid playBackControl(PlaybackCommand command);
bool parseState(const QByteArray &state); bool parseState(const QByteArray &state);
signals: signals:
void connectionChanged(bool connected); void connectionChanged(bool connected);
void actionExecuted(QUuid actionId, bool success); void actionExecuted(const QUuid &actionId, bool success);
void statusReceived(const StatusResponse &status); void statusReceived(const BluOS::StatusResponse &status);
void volumeReceived(int volume, bool mute); void volumeReceived(int volume, bool mute);
void shuffleStateReceived(bool state); void shuffleStateReceived(bool state);
void repeatModeReceived(RepeatMode mode); void repeatModeReceived(BluOS::RepeatMode mode);
void presetsReceived(QUuid requestId, const QList<Preset> &presets); void presetsReceived(const QUuid &requestId, const QList<BluOS::Preset> &presets);
void sourcesReceived(QUuid requestId, const QList<Source> &sources); void sourcesReceived(const QUuid &requestId, const QList<BluOS::Source> &sources);
void browseResultReceived(QUuid requestId, const QList<Source> &sources); void browseResultReceived(const QUuid &requestId, const QList<BluOS::Source> &sources);
}; };
#endif // BLUOS_H #endif // BLUOS_H

View File

@ -1,6 +1,6 @@
include(../plugins.pri) include(../plugins.pri)
QT += network QT *= network
SOURCES += \ SOURCES += \
integrationpluginbluos.cpp \ integrationpluginbluos.cpp \

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -31,10 +31,10 @@
#include "integrationpluginbluos.h" #include "integrationpluginbluos.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "integrations/thing.h"
#include "network/networkaccessmanager.h" #include <integrations/thing.h>
#include "types/mediabrowseritem.h" #include <types/mediabrowseritem.h>
#include "types/browseritem.h" #include <types/browseritem.h>
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -158,42 +158,42 @@ void IntegrationPluginBluOS::executeAction(ThingActionInfo *info)
qCWarning(dcBluOS()) << "Unhandled Playback mode"; qCWarning(dcBluOS()) << "Unhandled Playback mode";
} }
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerPlayActionTypeId) { } else if (action.actionTypeId() == bluosPlayerPlayActionTypeId) {
QUuid requestId = bluos->play(); QUuid requestId = bluos->play();
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerPauseActionTypeId) { } else if (action.actionTypeId() == bluosPlayerPauseActionTypeId) {
QUuid requestId = bluos->pause(); QUuid requestId = bluos->pause();
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerStopActionTypeId) { } else if (action.actionTypeId() == bluosPlayerStopActionTypeId) {
QUuid requestId = bluos->stop(); QUuid requestId = bluos->stop();
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerSkipNextActionTypeId) { } else if (action.actionTypeId() == bluosPlayerSkipNextActionTypeId) {
QUuid requestId = bluos->skip(); QUuid requestId = bluos->skip();
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerSkipBackActionTypeId) { } else if (action.actionTypeId() == bluosPlayerSkipBackActionTypeId) {
QUuid requestId = bluos->back(); QUuid requestId = bluos->back();
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerVolumeActionTypeId) { } else if (action.actionTypeId() == bluosPlayerVolumeActionTypeId) {
uint volume = action.param(bluosPlayerVolumeActionVolumeParamTypeId).value().toUInt(); uint volume = action.param(bluosPlayerVolumeActionVolumeParamTypeId).value().toUInt();
QUuid requestId = bluos->setVolume(volume); QUuid requestId = bluos->setVolume(volume);
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerMuteActionTypeId) { } else if (action.actionTypeId() == bluosPlayerMuteActionTypeId) {
bool mute = action.param(bluosPlayerMuteActionMuteParamTypeId).value().toBool(); bool mute = action.param(bluosPlayerMuteActionMuteParamTypeId).value().toBool();
QUuid requestId = bluos->setMute(mute); QUuid requestId = bluos->setMute(mute);
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerShuffleActionTypeId) { } else if (action.actionTypeId() == bluosPlayerShuffleActionTypeId) {
bool shuffle = action.param(bluosPlayerShuffleActionShuffleParamTypeId).value().toBool(); bool shuffle = action.param(bluosPlayerShuffleActionShuffleParamTypeId).value().toBool();
QUuid requestId = bluos->setShuffle(shuffle); QUuid requestId = bluos->setShuffle(shuffle);
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerRepeatActionTypeId) { } else if (action.actionTypeId() == bluosPlayerRepeatActionTypeId) {
QString repeat = action.param(bluosPlayerRepeatActionRepeatParamTypeId).value().toString(); QString repeat = action.param(bluosPlayerRepeatActionRepeatParamTypeId).value().toString();
QUuid requestId; QUuid requestId;
@ -207,17 +207,17 @@ void IntegrationPluginBluOS::executeAction(ThingActionInfo *info)
qCWarning(dcBluOS()) << "Unhandled Repeat Mode"; qCWarning(dcBluOS()) << "Unhandled Repeat Mode";
} }
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerIncreaseVolumeActionTypeId) { } else if (action.actionTypeId() == bluosPlayerIncreaseVolumeActionTypeId) {
uint step = action.param(bluosPlayerIncreaseVolumeActionStepParamTypeId).value().toUInt(); uint step = action.param(bluosPlayerIncreaseVolumeActionStepParamTypeId).value().toUInt();
QUuid requestId = bluos->setVolume(qMin<uint>(100, thing->stateValue(bluosPlayerVolumeStateTypeId).toUInt() + step)); QUuid requestId = bluos->setVolume(qMin<uint>(100, thing->stateValue(bluosPlayerVolumeStateTypeId).toUInt() + step));
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else if (action.actionTypeId() == bluosPlayerDecreaseVolumeActionTypeId) { } else if (action.actionTypeId() == bluosPlayerDecreaseVolumeActionTypeId) {
uint step = action.param(bluosPlayerDecreaseVolumeActionStepParamTypeId).value().toUInt(); uint step = action.param(bluosPlayerDecreaseVolumeActionStepParamTypeId).value().toUInt();
QUuid requestId = bluos->setVolume(qMax<uint>(0, thing->stateValue(bluosPlayerVolumeStateTypeId).toUInt() - step)); QUuid requestId = bluos->setVolume(qMax<uint>(0, thing->stateValue(bluosPlayerVolumeStateTypeId).toUInt() - step));
m_asyncActions.insert(requestId, info); m_asyncActions.insert(requestId, info);
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);}); connect(info, &ThingActionInfo::aborted, this, [this, requestId] {m_asyncActions.remove(requestId);});
} else { } else {
qCWarning(dcBluOS()) << "Execute Action, unhandled action type id" << action.actionTypeId(); qCWarning(dcBluOS()) << "Execute Action, unhandled action type id" << action.actionTypeId();
return info->finish(Thing::ThingErrorThingClassNotFound); return info->finish(Thing::ThingErrorThingClassNotFound);
@ -414,7 +414,7 @@ void IntegrationPluginBluOS::onActionExecuted(QUuid requestId, bool success)
} else { } else {
info->finish(Thing::ThingErrorHardwareFailure); info->finish(Thing::ThingErrorHardwareFailure);
} }
m_pluginTimer->timeout(); // get a status update emit m_pluginTimer->timeout(); // get a status update
} }
} }

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright 2013 - 2020, nymea GmbH * Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io * Contact: contact@nymea.io
* *
* This file is part of nymea. * This file is part of nymea.
@ -33,10 +33,10 @@
#include "bluos.h" #include "bluos.h"
#include "integrations/integrationplugin.h" #include <integrations/integrationplugin.h>
#include "platform/platformzeroconfcontroller.h" #include <platform/platformzeroconfcontroller.h>
#include "network/zeroconf/zeroconfservicebrowser.h" #include <network/zeroconf/zeroconfservicebrowser.h>
#include "plugintimer.h" #include <plugintimer.h>
#include <QUdpSocket> #include <QUdpSocket>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
@ -86,5 +86,6 @@ private slots:
void onPresetsReceived(QUuid requestId, const QList<BluOS::Preset> &presets); void onPresetsReceived(QUuid requestId, const QList<BluOS::Preset> &presets);
void onSourcesReceived(QUuid requestId, const QList<BluOS::Source> &sources); void onSourcesReceived(QUuid requestId, const QList<BluOS::Source> &sources);
void onBrowseResultReceived(QUuid requestId, const QList<BluOS::Source> &sources); void onBrowseResultReceived(QUuid requestId, const QList<BluOS::Source> &sources);
}; };
#endif // INTEGRATIONPLUGINBLUOS_H #endif // INTEGRATIONPLUGINBLUOS_H