sonos: Add Qt6 support

qt6-qmake
Simon Stürz 2025-08-08 16:32:47 +02:00
parent 77e5b43d77
commit aba181a812
5 changed files with 96 additions and 90 deletions

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@ -29,11 +29,12 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "integrationpluginsonos.h"
#include "integrations/thing.h"
#include "network/networkaccessmanager.h"
#include "plugininfo.h"
#include "types/mediabrowseritem.h"
#include <integrations/thing.h>
#include <types/mediabrowseritem.h>
#include <network/networkaccessmanager.h>
#include <plugintimer.h>
#include <QNetworkRequest>
#include <QNetworkReply>
@ -59,7 +60,7 @@ void IntegrationPluginSonos::setupThing(ThingSetupInfo *info)
Thing *thing = info->thing();
if (thing->thingClassId() == sonosConnectionThingClassId) {
Sonos *sonos;
Sonos *sonos = nullptr;
if (m_setupSonosConnections.keys().contains(thing->id())) {
//Fresh thing setup, has already a fresh access token
qCDebug(dcSonos()) << "Sonos OAuth setup complete";
@ -143,13 +144,13 @@ void IntegrationPluginSonos::confirmPairing(ThingPairingInfo *info, const QStrin
QUrl url(secret);
QUrlQuery query(url);
QByteArray authorizationCode = query.queryItemValue("code").toLocal8Bit();
QByteArray state = query.queryItemValue("state").toLocal8Bit();
//QByteArray state = query.queryItemValue("state").toLocal8Bit();
//TODO evaluate state if it equals the given state
Sonos *sonos = m_setupSonosConnections.value(info->thingId());
if (!sonos) {
qWarning(dcSonos()) << "No sonos connection found for thing:" << info->thingName();
qCWarning(dcSonos()) << "No sonos connection found for thing:" << info->thingName();
m_setupSonosConnections.remove(info->thingId());
info->finish(Thing::ThingErrorHardwareFailure);
return;
@ -157,7 +158,7 @@ void IntegrationPluginSonos::confirmPairing(ThingPairingInfo *info, const QStrin
sonos->getAccessTokenFromAuthorizationCode(authorizationCode);
connect(sonos, &Sonos::authenticationStatusChanged, info, [this, info, sonos](bool authenticated){
if(!authenticated) {
qWarning(dcSonos()) << "Authentication process failed" << info->thingName();
qCWarning(dcSonos()) << "Authentication process failed" << info->thingName();
m_setupSonosConnections.remove(info->thingId());
sonos->deleteLater();
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("Authentication failed. Please try again."));
@ -188,7 +189,7 @@ void IntegrationPluginSonos::postSetupThing(Thing *thing)
foreach (Thing *connectionDevice, myThings().filterByThingClassId(sonosConnectionThingClassId)) {
Sonos *sonos = m_sonosConnections.value(connectionDevice);
if (!sonos) {
qWarning(dcSonos()) << "No sonos connection found to" << connectionDevice->name();
qCWarning(dcSonos()) << "No sonos connection found to" << connectionDevice->name();
continue;
}
foreach (Thing *groupDevice, myThings().filterByParentId(connectionDevice->id())) {
@ -210,7 +211,7 @@ void IntegrationPluginSonos::postSetupThing(Thing *thing)
foreach (Thing *thing, myThings().filterByThingClassId(sonosConnectionThingClassId)) {
Sonos *sonos = m_sonosConnections.value(thing);
if (!sonos) {
qWarning(dcSonos()) << "No sonos connection found to" << thing->name();
qCWarning(dcSonos()) << "No sonos connection found to" << thing->name();
continue;
}
//get groups for each household in order to add or remove groups
@ -269,7 +270,7 @@ void IntegrationPluginSonos::executeAction(ThingActionInfo *info)
QString groupId = thing->paramValue(sonosGroupThingGroupIdParamTypeId).toString();
if (!sonos) {
qWarning(dcSonos()) << "Action cannot be executed: Sonos connection not available";
qCWarning(dcSonos()) << "Action cannot be executed: Sonos connection not available";
return info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Sonos thing is not available."));
}
@ -368,7 +369,7 @@ void IntegrationPluginSonos::browseThing(BrowseResult *result)
return;
}
qDebug(dcSonos()) << "Browse Device" << result->itemId();
qCDebug(dcSonos()) << "Browse Device" << result->itemId();
QString householdId = result->thing()->paramValue(sonosGroupThingHouseholdIdParamTypeId).toString();
if (result->itemId().isEmpty()){
BrowserItem item;
@ -382,7 +383,7 @@ void IntegrationPluginSonos::browseThing(BrowseResult *result)
} else if (result->itemId() == m_browseFavoritesPrefix) {
QUuid requestId = sonosConnection->getFavorites(householdId);
m_pendingBrowseResult.insert(requestId, result);
connect(result, &BrowseResult::aborted,[requestId, this](){m_pendingBrowseResult.remove(requestId);});
connect(result, &BrowseResult::aborted, this, [requestId, this](){ m_pendingBrowseResult.remove(requestId); });
} else {
//TODO add media browsing
result->finish(Thing::ThingErrorItemNotFound);
@ -403,7 +404,7 @@ void IntegrationPluginSonos::browserItem(BrowserItemResult *result)
if (result->itemId().startsWith(m_browseFavoritesPrefix)) {
QUuid requestId = sonosConnection->getFavorites(householdId);
m_pendingBrowserItemResult.insert(requestId, result);
connect(result, &BrowserItemResult::aborted, [requestId, this](){m_pendingBrowserItemResult.remove(requestId);});
connect(result, &BrowserItemResult::aborted, this, [requestId, this](){ m_pendingBrowserItemResult.remove(requestId); });
} else {
//TODO add media browsing
result->finish(Thing::ThingErrorItemNotFound);
@ -423,7 +424,7 @@ void IntegrationPluginSonos::executeBrowserItem(BrowserActionInfo *info)
favoriteId.remove('/');
QUuid requestId = sonosConnection->loadFavorite(groupId, favoriteId);
m_pendingBrowserExecution.insert(requestId, info);
connect(info, &BrowserActionInfo::aborted,[requestId, this](){m_pendingBrowserExecution.remove(requestId);});
connect(info, &BrowserActionInfo::aborted, this, [requestId, this](){ m_pendingBrowserExecution.remove(requestId); });
} else {
//TODO add media browsing
info->finish(Thing::ThingErrorItemNotFound);
@ -436,6 +437,7 @@ void IntegrationPluginSonos::onConnectionChanged(bool connected)
Thing *thing = m_sonosConnections.key(sonos);
if (!thing)
return;
thing->setStateValue(sonosConnectionConnectedStateTypeId, connected);
foreach (Thing *groupDevice, myThings().filterByParentId(thing->id())) {
@ -491,7 +493,7 @@ void IntegrationPluginSonos::onFavoritesReceived(QUuid requestId, const QString
item.setDisplayName(favorite.name);
item.setDescription(favorite.description);
result->addItem(item);
qDebug(dcSonos()) << "Favorite: " << favorite.name << favorite.description;
qCDebug(dcSonos()) << "Favorite: " << favorite.name << favorite.description;
}
result->finish(Thing::ThingErrorNoError);
@ -527,7 +529,7 @@ void IntegrationPluginSonos::onPlaylistsReceived(const QString &householdId, QLi
Sonos *sonos = static_cast<Sonos *>(sender());
foreach(Sonos::PlaylistObject playlist, playlists) {
qDebug(dcSonos()) << "Playlist: " << playlist.name << playlist.type << playlist.trackCount;
qCDebug(dcSonos()) << "Playlist: " << playlist.name << playlist.type << playlist.trackCount;
sonos->getPlaylist(householdId, playlist.id); //Get the playlist details
}
}
@ -535,9 +537,9 @@ void IntegrationPluginSonos::onPlaylistsReceived(const QString &householdId, QLi
void IntegrationPluginSonos::onPlaylistSummaryReceived(const QString &householdId, Sonos::PlaylistSummaryObject playlistSummary)
{
Q_UNUSED(householdId);
qDebug(dcSonos()) << "Playlist summary received: " << playlistSummary.name;
qCDebug(dcSonos()) << "Playlist summary received: " << playlistSummary.name;
foreach(Sonos::PlaylistTrackObject track, playlistSummary.tracks) {
qDebug(dcSonos()) << "---- Track: " << track.name << track.album << track.artist;
qCDebug(dcSonos()) << "---- Track: " << track.name << track.album << track.artist;
}
}
@ -553,7 +555,7 @@ void IntegrationPluginSonos::onGroupsReceived(const QString &householdId, QList<
Thing *groupDevice = myThings().findByParams(ParamList() << Param(sonosGroupThingGroupIdParamTypeId, groupObject.groupId));
if (groupDevice) {
if (groupDevice->name() != groupObject.displayName) {
qDebug(dcSonos()) << "Updating group name" << groupDevice->name() << "to" << groupObject.displayName;
qCDebug(dcSonos()) << "Updating group name" << groupDevice->name() << "to" << groupObject.displayName;
groupDevice->setName(groupObject.displayName);
}
} else {

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@ -31,13 +31,18 @@
#ifndef INTEGRATIONPLUGINSONOS_H
#define INTEGRATIONPLUGINSONOS_H
#include "integrations/integrationplugin.h"
#include "plugintimer.h"
#include "sonos.h"
#include <integrations/integrationplugin.h>
#include <QHash>
#include <QDebug>
#include "sonos.h"
class PluginTimer;
class BrowseResult;
class BrowseResult;
class BrowserItemResult;
class IntegrationPluginSonos : public IntegrationPlugin
{
Q_OBJECT

View File

@ -52,12 +52,12 @@ Sonos::Sonos(NetworkAccessManager *networkmanager, const QByteArray &clientKey,
QUrl Sonos::getLoginUrl(const QUrl &redirectUrl)
{
if (m_clientKey.isEmpty()) {
qWarning(dcSonos()) << "Client key not defined!";
qCWarning(dcSonos()) << "Client key not defined!";
return QUrl("");
}
if (redirectUrl.isEmpty()){
qWarning(dcSonos()) << "No redirect uri defined!";
qCWarning(dcSonos()) << "No redirect uri defined!";
}
m_redirectUri = QUrl::toPercentEncoding(redirectUrl.toString());
@ -91,7 +91,7 @@ void Sonos::getHouseholds()
request.setRawHeader("X-Sonos-Api-Key", m_clientKey);
request.setUrl(QUrl(m_baseControlUrl + "/households"));
QNetworkReply *reply = m_networkManager->get(request);
qDebug(dcSonos()) << "Sending request" << request.url() << request.rawHeaderList() << request.rawHeader("Authorization");
qCDebug(dcSonos()) << "Sending request" << request.url() << request.rawHeaderList() << request.rawHeader("Authorization");
connect(reply, &QNetworkReply::finished, this, [reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@ -113,13 +113,13 @@ void Sonos::getHouseholds()
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug(dcSonos()) << "Household ID: Recieved invalide JSON object";
qCDebug(dcSonos()) << "Household ID: Recieved invalide JSON object";
return;
}
QList<QString> households;
foreach (const QVariant &variant, data.toVariant().toMap().value("households").toList()) {
QVariantMap obj = variant.toMap();
//qDebug(dcSonos()) << "Household ID received:" << obj["id"].toString();
//qCDebug(dcSonos()) << "Household ID received:" << obj["id"].toString();
households.append(obj["id"].toString());
}
emit householdIdsReceived(households);
@ -140,7 +140,7 @@ QUuid Sonos::loadFavorite(const QString &groupId, const QString &favouriteId)
object.insert("favoriteId", favouriteId);
object.insert("playOnCompletion", true);
QJsonDocument doc(object);
qDebug(dcSonos()) << "Sending request" << doc.toJson();
qCDebug(dcSonos()) << "Sending request" << doc.toJson();
QNetworkReply *reply = m_networkManager->post(request, doc.toJson(QJsonDocument::Compact));
connect(reply, &QNetworkReply::finished, this, [reply, actionId, this] {
@ -205,7 +205,7 @@ QUuid Sonos::getFavorites(const QString &householdId)
return;
QVariantList array = data.toVariant().toMap().value("items").toList();
//qDebug(dcSonos()) << "Favorites received:" << data.toJson();
//qCDebug(dcSonos()) << "Favorites received:" << data.toJson();
QList<FavoriteObject> favorites;
foreach (const QVariant &variant, array) {
@ -249,7 +249,7 @@ void Sonos::getGroups(const QString &householdId)
emit connectionChanged(true);
emit authenticationStatusChanged(true);
//qDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
//qCDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError)
@ -262,7 +262,7 @@ void Sonos::getGroups(const QString &householdId)
QList<GroupObject> groupObjects;
foreach (const QVariant &value, array) {
QVariantMap obj = value.toMap();
//qDebug(dcSonos()) << "Group ID received:" << obj["id"].toString();
//qCDebug(dcSonos()) << "Group ID received:" << obj["id"].toString();
GroupObject group;
group.groupId = obj["id"].toString();
group.displayName = obj["name"].toString();
@ -304,7 +304,7 @@ void Sonos::getGroupVolume(const QString &groupId)
emit connectionChanged(true);
emit authenticationStatusChanged(true);
//qDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
//qCDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
@ -335,7 +335,7 @@ QUuid Sonos::setGroupVolume(const QString &groupId, int volume)
QJsonObject object;
object.insert("volume", volume);
QJsonDocument doc(object);
qDebug(dcSonos()) << "Set volume:" << groupId << doc.toJson(QJsonDocument::Compact);
qCDebug(dcSonos()) << "Set volume:" << groupId << doc.toJson(QJsonDocument::Compact);
QNetworkReply *reply = m_networkManager->post(request, doc.toJson(QJsonDocument::Compact));
connect(reply, &QNetworkReply::finished, this, [reply, actionId, groupId, this] {
@ -375,7 +375,7 @@ QUuid Sonos::setGroupMute(const QString &groupId, bool mute)
object.insert("muted", mute);
QJsonDocument doc(object);
qDebug(dcSonos()) << "Set mute:" << groupId << doc.toJson(QJsonDocument::Compact);
qCDebug(dcSonos()) << "Set mute:" << groupId << doc.toJson(QJsonDocument::Compact);
QNetworkReply *reply = m_networkManager->post(request, doc.toJson(QJsonDocument::Compact));
connect(reply, &QNetworkReply::finished, this, [reply, actionId, groupId, this] {
@ -415,7 +415,7 @@ QUuid Sonos::setGroupRelativeVolume(const QString &groupId, int volumeDelta)
object.insert("volumeDelta", QJsonValue::fromVariant(volumeDelta));
QJsonDocument doc(object);
qDebug(dcSonos()) << "Relative volume:" << groupId << volumeDelta;
qCDebug(dcSonos()) << "Relative volume:" << groupId << volumeDelta;
QNetworkReply *reply = m_networkManager->post(request, doc.toJson(QJsonDocument::Compact));
connect(reply, &QNetworkReply::finished, this, [reply, actionId, groupId, this] {
@ -476,7 +476,7 @@ void Sonos::getGroupPlaybackStatus(const QString &groupId)
QJsonObject object = data.object();
playBack.itemId = object["itemId"].toString();
playBack.positionMillis = object["positionMillis"].toInt();
playBack.previousItemId = object["previousItemId"].toInt();
playBack.previousItemId = QString::number(object["previousItemId"].toInt());
playBack.previousPositionMillis = object["previousPositionMillis"].toInt();
QString playBackState = object["playbackState"].toString();
if (playBackState.contains("BUFFERING")) {
@ -505,7 +505,7 @@ void Sonos::getGroupPlaybackStatus(const QString &groupId)
QUuid Sonos::groupLoadLineIn(const QString &groupId)
{
qDebug(dcSonos()) << "Load line in:" << groupId;
qCDebug(dcSonos()) << "Load line in:" << groupId;
QNetworkRequest request;
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", "Bearer " + m_accessToken);
@ -547,7 +547,7 @@ QUuid Sonos::groupPlay(const QString &groupId)
request.setUrl(QUrl(m_baseControlUrl + "/groups/" + groupId + "/playback/play"));
QUuid actionId = QUuid::createUuid();
qDebug(dcSonos()) << "Play:" << groupId;
qCDebug(dcSonos()) << "Play:" << groupId;
QNetworkReply *reply = m_networkManager->post(request, "");
connect(reply, &QNetworkReply::finished, this, [reply, actionId, groupId, this] {
@ -583,7 +583,7 @@ QUuid Sonos::groupPause(const QString &groupId)
request.setUrl(QUrl(m_baseControlUrl + "/groups/" + groupId + "/playback/pause"));
QUuid actionId = QUuid::createUuid();
qDebug(dcSonos()) << "Pause:" << groupId;
qCDebug(dcSonos()) << "Pause:" << groupId;
QNetworkReply *reply = m_networkManager->post(request, "");
connect(reply, &QNetworkReply::finished, this, [reply, actionId, groupId, this] {
@ -780,15 +780,15 @@ QUuid Sonos::groupSetRepeat(const QString &groupId, RepeatMode repeatMode)
QJsonObject object;
QJsonObject playModesObject;
if (repeatMode == RepeatModeAll) {
qDebug(dcSonos()) << "Setting repeat mode all";
qCDebug(dcSonos()) << "Setting repeat mode all";
playModesObject["repeat"] = true;
playModesObject["repeatOne"] = false;
} else if (repeatMode == RepeatModeOne) {
qDebug(dcSonos()) << "Setting repeat mode one";
qCDebug(dcSonos()) << "Setting repeat mode one";
playModesObject["repeat"] = false;
playModesObject["repeatOne"] = true;
} else if (repeatMode == RepeatModeNone) {
qDebug(dcSonos()) << "Setting repeat mode none";
qCDebug(dcSonos()) << "Setting repeat mode none";
playModesObject["repeat"] = false;
playModesObject["repeatOne"] = false;
}
@ -1024,21 +1024,21 @@ void Sonos::getGroupMetadataStatus(const QString &groupId)
ArtistObject artist;
QJsonObject artistObject = trackObject["artist"].toObject();
artist.name = artistObject["name"].toString();
//qDebug(dcSonos()) << "Track object contains artist" << artist.name;
//qCDebug(dcSonos()) << "Track object contains artist" << artist.name;
track.artist = artist;
}
if (trackObject.contains("album")) {
AlbumObject album;
QJsonObject albumObject = trackObject["album"].toObject();
album.name = albumObject["name"].toString();
//qDebug(dcSonos()) << "Track object contains album" << album.name;
//qCDebug(dcSonos()) << "Track object contains album" << album.name;
track.album = album;
}
if (trackObject.contains("service")) {
ServiceObject service;
QJsonObject serviceObject = trackObject["service"].toObject();
service.name = serviceObject["name"].toString();
//qDebug(dcSonos()) << "Track object contains service" << service.name;
//qCDebug(dcSonos()) << "Track object contains service" << service.name;
track.service = service;
}
if (trackObject.contains("id")) {
@ -1067,21 +1067,21 @@ void Sonos::getGroupMetadataStatus(const QString &groupId)
ArtistObject artist;
QJsonObject artistObject = trackObject.value("artist").toObject();
artist.name = artistObject["name"].toString();
//qDebug(dcSonos()) << "Track object contains artist" << artist.name;
//qCDebug(dcSonos()) << "Track object contains artist" << artist.name;
track.artist = artist;
}
if (trackObject.contains("album")) {
AlbumObject album;
QJsonObject albumObject = trackObject.value("album").toObject();
album.name = albumObject["name"].toString();
//qDebug(dcSonos()) << "Track object contains album" << album.name;
//qCDebug(dcSonos()) << "Track object contains album" << album.name;
track.album = album;
}
if (trackObject.contains("service")) {
ServiceObject service;
QJsonObject serviceObject = trackObject.value("service").toObject();
service.name = serviceObject["name"].toString();
//qDebug(dcSonos()) << "Track object contains service" << service.name;
//qCDebug(dcSonos()) << "Track object contains service" << service.name;
track.service = service;
}
if (trackObject.contains("id")) {
@ -1127,7 +1127,7 @@ void Sonos::getPlayerVolume(const QByteArray &playerId)
emit connectionChanged(true);
emit authenticationStatusChanged(true);
//qDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
//qCDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
@ -1153,7 +1153,7 @@ QUuid Sonos::setPlayerVolume(const QByteArray &playerId, int volume)
request.setUrl(QUrl(m_baseControlUrl + "/players/" + playerId + "/playerVolume"));
QUuid actionId = QUuid::createUuid();
qDebug(dcSonos()) << "Setting volume:" << playerId << volume;
qCDebug(dcSonos()) << "Setting volume:" << playerId << volume;
QJsonObject object;
object.insert("volume", QJsonValue::fromVariant(volume));
@ -1292,7 +1292,7 @@ void Sonos::getPlaylist(const QString &householdId, const QString &playlistId)
emit connectionChanged(true);
emit authenticationStatusChanged(true);
//qDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
//qCDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
@ -1345,7 +1345,7 @@ void Sonos::getPlaylists(const QString &householdId)
emit connectionChanged(true);
emit authenticationStatusChanged(true);
//qDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
//qCDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
QJsonParseError error;
QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error);
if (!data.isObject()) {
@ -1504,7 +1504,7 @@ void Sonos::onRefreshTimeout()
void Sonos::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
{
if (refreshToken.isEmpty()) {
qWarning(dcSonos()) << "No refresh token given!";
qCWarning(dcSonos()) << "No refresh token given!";
emit authenticationStatusChanged(false);
return;
}
@ -1530,7 +1530,7 @@ void Sonos::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (status != 200 || reply->error() != QNetworkReply::NoError) {
if(jsonDoc.toVariant().toMap().contains("error_description")) {
qWarning(dcSonos()) << "Access token error:" << jsonDoc.toVariant().toMap().value("error_description").toString();
qCWarning(dcSonos()) << "Access token error:" << jsonDoc.toVariant().toMap().value("error_description").toString();
}
emit authenticationStatusChanged(false);
return;
@ -1545,7 +1545,7 @@ void Sonos::getAccessTokenFromRefreshToken(const QByteArray &refreshToken)
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
qCDebug(dcSonos()) << "Access token expires at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
if (!m_tokenRefreshTimer) {
qWarning(dcSonos()) << "Access token refresh timer not initialized";
qCWarning(dcSonos()) << "Access token refresh timer not initialized";
return;
}
m_tokenRefreshTimer->start((expireTime - 20) * 1000);
@ -1558,11 +1558,11 @@ void Sonos::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC
{
// Obtaining access token
if(authorizationCode.isEmpty())
qWarning(dcSonos) << "No auhtorization code given!";
qCWarning(dcSonos()) << "No auhtorization code given!";
if(m_clientKey.isEmpty())
qWarning(dcSonos) << "Client key not set!";
qCWarning(dcSonos()) << "Client key not set!";
if(m_clientSecret.isEmpty())
qWarning(dcSonos) << "Client secret not set!";
qCWarning(dcSonos()) << "Client secret not set!";
QUrl url = QUrl(m_baseAuthorizationUrl);
QUrlQuery query;
@ -1588,21 +1588,21 @@ void Sonos::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC
case 400:
if(!jsonDoc.toVariant().toMap().contains("error")) {
if(jsonDoc.toVariant().toMap().value("error").toString() == "invalid_client") {
qWarning(dcSonos()) << "Client token provided doesnt correspond to client that generated auth code.";
qCWarning(dcSonos()) << "Client token provided doesnt correspond to client that generated auth code.";
}
if(jsonDoc.toVariant().toMap().value("error").toString() == "invalid_redirect_uri") {
qWarning(dcSonos()) << "Missing redirect_uri parameter.";
qCWarning(dcSonos()) << "Missing redirect_uri parameter.";
}
if(jsonDoc.toVariant().toMap().value("error").toString() == "invalid_code") {
qWarning(dcSonos()) << "Expired authorization code.";
qCWarning(dcSonos()) << "Expired authorization code.";
}
}
return;
case 401:
qWarning(dcSonos()) << "Client does not have permission to use this API.";
qCWarning(dcSonos()) << "Client does not have permission to use this API.";
return;
case 405:
qWarning(dcSonos()) << "Wrong HTTP method used.";
qCWarning(dcSonos()) << "Wrong HTTP method used.";
return;
default:
break;
@ -1622,7 +1622,7 @@ void Sonos::getAccessTokenFromAuthorizationCode(const QByteArray &authorizationC
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
qCDebug(dcSonos()) << "expires at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
if (!m_tokenRefreshTimer) {
qWarning(dcSonos()) << "Token refresh timer not initialized";
qCWarning(dcSonos()) << "Token refresh timer not initialized";
emit authenticationStatusChanged(false);
return;
}

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Copyright 2013 - 2025, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
@ -34,8 +34,7 @@
#include <QObject>
#include <QTimer>
#include "network/networkaccessmanager.h"
#include "integrations/thing.h"
#include <network/networkaccessmanager.h>
class Sonos : public QObject
{
@ -271,6 +270,24 @@ public:
void getPlayerSettings(const QString &playerId);
QUuid setPlayerSettings(const QString &playerId, PlayerSettingsObject settings);
signals:
void connectionChanged(bool connected);
void authenticationStatusChanged(bool authenticated);
void householdIdsReceived(const QList<QString> &householdIds);
void favoritesReceived(const QUuid &requestId, const QString &householdId, const QList<Sonos::FavoriteObject> &favorites);
void playlistsReceived(const QString &householdId, const QList<Sonos::PlaylistObject> &playlists);
void groupsReceived(const QString &householdId, const QList<Sonos::GroupObject> &groups);
void playlistSummaryReceived(const QString &householdId, Sonos::PlaylistSummaryObject playlistSummary);
void playBackStatusReceived(const QString &groupId, Sonos::PlayBackObject playBack);
void metadataStatusReceived(const QString &groupId, Sonos::MetadataStatus metaDataStatus);
void volumeReceived(const QString &groupId, Sonos::VolumeObject groupVolume);
void playerVolumeReceived(const QString &playerId, Sonos::VolumeObject playerVolume);
void playerSettingsRecieved(const QString &playerId, Sonos::PlayerSettingsObject playerSettings);
void actionExecuted(const QUuid &actionId, bool success);
private:
QByteArray m_baseAuthorizationUrl = "https://api.sonos.com/login/v3/oauth/access";
QByteArray m_baseControlUrl = "https://api.ws.sonos.com/control/api/v1";
@ -283,25 +300,9 @@ private:
NetworkAccessManager *m_networkManager = nullptr;
QTimer *m_tokenRefreshTimer = nullptr;
private slots:
void onRefreshTimeout();
signals:
void connectionChanged(bool connected);
void authenticationStatusChanged(bool authenticated);
void householdIdsReceived(QList<QString> householdIds);
void favoritesReceived(QUuid requestId, const QString &householdId, QList<FavoriteObject> favorites);
void playlistsReceived(const QString &householdId, QList<PlaylistObject> playlists);
void groupsReceived(const QString &householdId, QList<GroupObject> groups);
void playlistSummaryReceived(const QString &householdId, PlaylistSummaryObject playlistSummary);
void playBackStatusReceived(const QString &groupId, PlayBackObject playBack);
void metadataStatusReceived(const QString &groupId, MetadataStatus metaDataStatus);
void volumeReceived(const QString &groupId, VolumeObject groupVolume);
void playerVolumeReceived(const QString &playerId, VolumeObject playerVolume);
void playerSettingsRecieved(const QString &playerId, PlayerSettingsObject playerSettings);
void actionExecuted(QUuid actionId, bool success);
};
#endif // SONOS_H

View File

@ -2,12 +2,10 @@ include(../plugins.pri)
QT += network
TARGET = $$qtLibraryTarget(nymea_integrationpluginsonos)
SOURCES += \
integrationpluginsonos.cpp \
sonos.cpp \
sonos.cpp
HEADERS += \
integrationpluginsonos.h \
sonos.h \
sonos.h