added plugin Storage for tokens

This commit is contained in:
nymea 2019-09-01 21:41:10 +02:00 committed by Michael Zanetti
parent 34b97e89d4
commit 4254d3cb3c
5 changed files with 283 additions and 145 deletions

View File

@ -45,15 +45,23 @@ DevicePluginSonos::~DevicePluginSonos()
Device::DeviceSetupStatus DevicePluginSonos::setupDevice(Device *device) Device::DeviceSetupStatus DevicePluginSonos::setupDevice(Device *device)
{ {
if (!m_pluginTimer) { if (!m_pluginTimer) {
hardwareManager()->pluginTimerManager()->registerTimer(1);
} }
if(!m_tokenRefreshTimer) {
m_tokenRefreshTimer = new QTimer(this);
m_tokenRefreshTimer->setSingleShot(false);
connect(m_tokenRefreshTimer, &QTimer::timeout, this, &DevicePluginSonos::onRefreshTimeout);
}
if (device->deviceClassId() == sonosConnectionDeviceClassId) { if (device->deviceClassId() == sonosConnectionDeviceClassId) {
qCDebug(dcSonos()) << "Sonos OAuth setup complete"; qCDebug(dcSonos()) << "Sonos OAuth setup complete";
Sonos *sonos = new Sonos(hardwareManager()->networkManager(), "0a8f6d44-d9d1-4474-bcfa-cfb41f8b66e8", this);
pluginStorage()->beginGroup(device->id().toString()); pluginStorage()->beginGroup(device->id().toString());
QString username = pluginStorage()->value("username").toString(); QByteArray accessToken = pluginStorage()->value("access_token").toByteArray();
QString password = pluginStorage()->value("password").toString();
pluginStorage()->endGroup(); pluginStorage()->endGroup();
Sonos *sonos = new Sonos(hardwareManager()->networkManager(), accessToken, this);
m_sonosConnections.insert(device, sonos); m_sonosConnections.insert(device, sonos);
} }
@ -98,49 +106,66 @@ DevicePairingInfo DevicePluginSonos::confirmPairing(DevicePairingInfo &devicePai
qCDebug(dcSonos()) << "Confirm pairing"; qCDebug(dcSonos()) << "Confirm pairing";
if (devicePairingInfo.deviceClassId() == sonosConnectionDeviceClassId) { if (devicePairingInfo.deviceClassId() == sonosConnectionDeviceClassId) {
qCDebug(dcSonos()) << "Secret is" << secret; qCDebug(dcSonos()) << "Secret is" << secret;
QUrl url(secret); QUrl url(secret);
QUrlQuery query(url); QUrlQuery query(url);
qCDebug(dcSonos()) << "Acess code is:" << query.queryItemValue("code"); qCDebug(dcSonos()) << "Acess code is:" << query.queryItemValue("code");
QString accessCode = query.queryItemValue("code"); QString accessCode = query.queryItemValue("code");
// Obtaining access token // Obtaining access token
url = QUrl("https://api.sonos.com/login/v3/oauth/access"); url = QUrl("https://api.sonos.com/login/v3/oauth/access");
query.clear(); query.clear();
query.addQueryItem("grant_type", "authorization_code"); query.addQueryItem("grant_type", "authorization_code");
query.addQueryItem("code", accessCode); query.addQueryItem("code", accessCode);
query.addQueryItem("redirect_uri", "https%3A%2F%2F127.0.0.1%3A8888"); query.addQueryItem("redirect_uri", "https%3A%2F%2F127.0.0.1%3A8888");
url.setQuery(query); url.setQuery(query);
QNetworkRequest request(url); QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded;charset=utf-8"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded;charset=utf-8");
QByteArray clientId = "b15cbf8c-a39c-47aa-bd93-635a96e9696c"; QByteArray clientId = "b15cbf8c-a39c-47aa-bd93-635a96e9696c";
QByteArray clientSecret = "c086ba71-e562-430b-a52f-867c6482fd11"; QByteArray clientSecret = "c086ba71-e562-430b-a52f-867c6482fd11";
QByteArray auth = QByteArray(clientId + ':' + clientSecret).toBase64(QByteArray::Base64Encoding | QByteArray::KeepTrailingEquals); QByteArray auth = QByteArray(clientId + ':' + clientSecret).toBase64(QByteArray::Base64Encoding | QByteArray::KeepTrailingEquals);
request.setRawHeader("Authorization", QString("Basic %1").arg(QString(auth)).toUtf8()); request.setRawHeader("Authorization", QString("Basic %1").arg(QString(auth)).toUtf8());
QNetworkReply *reply = hardwareManager()->networkManager()->post(request, QByteArray()); QNetworkReply *reply = hardwareManager()->networkManager()->post(request, QByteArray());
connect(reply, &QNetworkReply::finished, this, [this, reply, devicePairingInfo](){ connect(reply, &QNetworkReply::finished, this, [this, reply, devicePairingInfo](){
reply->deleteLater(); reply->deleteLater();
DevicePairingInfo info(devicePairingInfo);
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll()); QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll());
qCDebug(dcSonos()) << "Sonos accessToken reply:" << this << reply->error() << reply->errorString() << jsonDoc.toJson(); qCDebug(dcSonos()) << "Sonos accessToken reply:" << this << reply->error() << reply->errorString() << jsonDoc.toJson();
qCDebug(dcSonos()) << "Access token:" << jsonDoc.toVariant().toMap().value("access_token").toString(); if(!jsonDoc.toVariant().toMap().contains("access_token") || !jsonDoc.toVariant().toMap().contains("refresh_token") ) {
qCDebug(dcSonos()) << "expires at" << QDateTime::currentDateTime().addSecs(jsonDoc.toVariant().toMap().value("expires_in").toInt()).toString(); info.setStatus(Device::DeviceErrorSetupFailed);
qCDebug(dcSonos()) << "Refresh token:" << jsonDoc.toVariant().toMap().value("refresh_token").toString(); emit pairingFinished(info);
DevicePairingInfo info(devicePairingInfo); return;
info.setStatus(Device::DeviceErrorNoError); }
emit pairingFinished(info); qCDebug(dcSonos()) << "Access token:" << jsonDoc.toVariant().toMap().value("access_token").toString();
}); QByteArray accessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray();
devicePairingInfo.setStatus(Device::DeviceErrorAsync); qCDebug(dcSonos()) << "Refresh token:" << jsonDoc.toVariant().toMap().value("refresh_token").toString();
return devicePairingInfo; QByteArray refreshToken = jsonDoc.toVariant().toMap().value("refresh_token").toByteArray();
}
pluginStorage()->beginGroup(info.deviceId().toString());
pluginStorage()->setValue("access_token", accessToken);
pluginStorage()->setValue("refresh_token", refreshToken);
pluginStorage()->endGroup();
/*if (jsonDoc.toVariant().toMap().contains("expires_in")) {
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
qCDebug(dcSonos()) << "expires at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
m_tokenRefreshTimer->start((expireTime - 20) * 1000);
}*/
info.setStatus(Device::DeviceErrorNoError);
emit pairingFinished(info);
});
devicePairingInfo.setStatus(Device::DeviceErrorAsync);
return devicePairingInfo;
}
qCWarning(dcSonos()) << "Invalid deviceclassId -> no pairing possible with this device"; qCWarning(dcSonos()) << "Invalid deviceclassId -> no pairing possible with this device";
devicePairingInfo.setStatus(Device::DeviceErrorHardwareFailure); devicePairingInfo.setStatus(Device::DeviceErrorHardwareFailure);
return devicePairingInfo; return devicePairingInfo;
@ -149,7 +174,8 @@ DevicePairingInfo DevicePluginSonos::confirmPairing(DevicePairingInfo &devicePai
void DevicePluginSonos::postSetupDevice(Device *device) void DevicePluginSonos::postSetupDevice(Device *device)
{ {
if (device->deviceClassId() == sonosConnectionDeviceClassId) { if (device->deviceClassId() == sonosConnectionDeviceClassId) {
Sonos *sonos = m_sonosConnections.value(device);
sonos->getHouseholds();
} }
if (device->deviceClassId() == sonosGroupDeviceClassId) { if (device->deviceClassId() == sonosGroupDeviceClassId) {
@ -180,69 +206,59 @@ Device::DeviceError DevicePluginSonos::executeAction(Device *device, const Actio
Q_UNUSED(action) Q_UNUSED(action)
if (device->deviceClassId() == sonosGroupDeviceClassId) { if (device->deviceClassId() == sonosGroupDeviceClassId) {
Sonos *sonos = m_sonosConnections.value(device); Sonos *sonos = m_sonosConnections.value(device);
//int groupId = device->paramValue(sonosGroupDe) QByteArray groupId = device->paramValue(sonosGroupDeviceGroupIdParamTypeId).toByteArray();
if (!sonos) if (!sonos)
return Device::DeviceErrorInvalidParameter; return Device::DeviceErrorInvalidParameter;
if (action.actionTypeId() == sonosGroupPlayActionTypeId) { if (action.actionTypeId() == sonosGroupPlayActionTypeId) {
sonos->play(); sonos->groupPlay(groupId);
return Device::DeviceErrorAsync; return Device::DeviceErrorAsync;
} }
if (action.actionTypeId() == sonosGroupShuffleActionTypeId) { if (action.actionTypeId() == sonosGroupShuffleActionTypeId) {
bool shuffle = action.param(sonosGroupShuffleActionShuffleParamTypeId).value().toBool();
sonos->groupSetShuffle(groupId, shuffle);
return Device::DeviceErrorAsync; return Device::DeviceErrorAsync;
} }
if (action.actionTypeId() == sonosGroupRepeatActionTypeId) { if (action.actionTypeId() == sonosGroupRepeatActionTypeId) {
if (action.param(sonosGroupRepeatActionRepeatParamTypeId).value().toString() == "None") { if (action.param(sonosGroupRepeatActionRepeatParamTypeId).value().toString() == "None") {
sonos->groupSetRepeat(groupId, Sonos::RepeatModeNone);
} else if (action.param(sonosGroupShuffleActionShuffleParamTypeId).value().toString() == "One") { } else if (action.param(sonosGroupShuffleActionShuffleParamTypeId).value().toString() == "One") {
sonos->groupSetRepeat(groupId, Sonos::RepeatModeOne);
} else if (action.param(sonosGroupShuffleActionShuffleParamTypeId).value().toString() == "All") { } else if (action.param(sonosGroupShuffleActionShuffleParamTypeId).value().toString() == "All") {
sonos->groupSetRepeat(groupId, Sonos::RepeatModeAll);
} else { } else {
return Device::DeviceErrorHardwareFailure; return Device::DeviceErrorHardwareFailure;
} }
return Device::DeviceErrorAsync; return Device::DeviceErrorAsync;
} }
if (action.actionTypeId() == sonosGroupPauseActionTypeId) { if (action.actionTypeId() == sonosGroupPauseActionTypeId) {
sonos->pause(); sonos->groupPause(groupId);
return Device::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == sonosGroupStopActionTypeId) { if (action.actionTypeId() == sonosGroupStopActionTypeId) {
//sonos->stop(); sonos->groupPause(groupId);
return Device::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == sonosGroupMuteActionTypeId) { if (action.actionTypeId() == sonosGroupMuteActionTypeId) {
//bool mute = action.param(sonosGroupMuteActionMuteParamTypeId).value().toBool(); bool mute = action.param(sonosGroupMuteActionMuteParamTypeId).value().toBool();
sonos->setGroupMute(groupId, mute);
//sonos->setGroupMute();
return Device::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == sonosGroupSkipNextActionTypeId) { if (action.actionTypeId() == sonosGroupSkipNextActionTypeId) {
/*if (!m_sonosSystem->GetPlayer()->Next()) { sonos->groupSkipToNextTrack(groupId);
return Device::DeviceErrorHardwareFailure;
}*/
return Device::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == sonosGroupSkipBackActionTypeId) { if (action.actionTypeId() == sonosGroupSkipBackActionTypeId) {
/* if(!m_sonosSystem->GetPlayer()->Previous()) { sonos->groupSkipToPreviousTrack(groupId);
return Device::DeviceErrorHardwareFailure;
}*/
return Device::DeviceErrorNoError;
}
if (action.actionTypeId() == sonosGroupSkipBackActionTypeId) {
//int volume = action.param(sonosVolumeActionVolumeParamTypeId).value().toInt();
return Device::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
return Device::DeviceErrorActionTypeNotFound; return Device::DeviceErrorActionTypeNotFound;
@ -262,3 +278,43 @@ void DevicePluginSonos::onConnectionChanged()
//TODO set all groups //TODO set all groups
} }
void DevicePluginSonos::onRefreshTimeout()
{
qCDebug(dcSonos) << "Refresh authentication token";
QUrlQuery query;
query.addQueryItem("grant_type", "refresh_token");
query.addQueryItem("refresh_token", m_sonosConnectionRefreshToken);
QUrl url("https://api.sonos.com/login/v3/oauth");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded; charset=UTF-8");
QNetworkReply *reply = hardwareManager()->networkManager()->post(request, QByteArray());
connect(reply, &QNetworkReply::finished, this, [this, reply](){
reply->deleteLater();
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll());
qCDebug(dcSonos()) << "Sonos accessToken reply:" << this << reply->error() << reply->errorString() << jsonDoc.toJson();
if(!jsonDoc.toVariant().toMap().contains("access_token")) {
return;
}
qCDebug(dcSonos()) << "Access token:" << jsonDoc.toVariant().toMap().value("access_token").toString();
m_sonosConnectionAccessToken = jsonDoc.toVariant().toMap().value("access_token").toByteArray();
if (jsonDoc.toVariant().toMap().contains("expires_in")) {
int expireTime = jsonDoc.toVariant().toMap().value("expires_in").toInt();
qCDebug(dcSonos()) << "expires at" << QDateTime::currentDateTime().addSecs(expireTime).toString();
m_tokenRefreshTimer->start((expireTime - 20) * 1000);
}
});
}
void DevicePluginSonos::onHouseholdIdsReceived(QList<QByteArray> householdIds)
{
qDebug(dcSonos()) << "Household Id received, start to discover groups";
Sonos *sonos = static_cast<Sonos *>(sender());
foreach(QByteArray householdId, householdIds) {
sonos->getGroups(householdId);
}
}

View File

@ -29,6 +29,7 @@
#include <QHash> #include <QHash>
#include <QDebug> #include <QDebug>
#include <QTimer>
class DevicePluginSonos : public DevicePlugin class DevicePluginSonos : public DevicePlugin
@ -52,11 +53,20 @@ public:
private: private:
PluginTimer *m_pluginTimer = nullptr; PluginTimer *m_pluginTimer = nullptr;
QTimer *m_tokenRefreshTimer = nullptr;
QHash<Device *, Sonos *> m_sonosConnections; QHash<Device *, Sonos *> m_sonosConnections;
QList<QByteArray> m_householdIds;
QByteArray m_sonosConnectionAccessToken;
QByteArray m_sonosConnectionRefreshToken;
private slots: private slots:
void onPluginTimer(); void onPluginTimer();
void onConnectionChanged(); void onConnectionChanged();
void onRefreshTimeout();
void onHouseholdIdsReceived(QList<QByteArray> householdIds);
}; };

View File

@ -16,6 +16,8 @@
"interfaces": ["gateway"], "interfaces": ["gateway"],
"createMethods": ["user"], "createMethods": ["user"],
"setupMethod": "oauth", "setupMethod": "oauth",
"paramTypes": [
],
"stateTypes": [ "stateTypes": [
{ {
"id": "5aa4360c-61de-47d0-a72e-a19d57712e1c", "id": "5aa4360c-61de-47d0-a72e-a19d57712e1c",

View File

@ -41,9 +41,11 @@ void Sonos::getHouseholds()
{ {
QNetworkRequest request; QNetworkRequest request;
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", "Bearer" + m_accessToken); request.setRawHeader("Authorization", "Bearer " + m_accessToken);
request.setRawHeader("X-Sonos-Api-Key", m_apiKey);
request.setUrl(QUrl(m_baseControlUrl + "/households")); request.setUrl(QUrl(m_baseControlUrl + "/households"));
QNetworkReply *reply = m_networkManager->get(request); QNetworkReply *reply = m_networkManager->get(request);
qDebug(dcSonos()) << "Sending request" << request.url() << request.rawHeaderList() << request.rawHeader("Authorization");
connect(reply, &QNetworkReply::finished, this, [reply, this] { connect(reply, &QNetworkReply::finished, this, [reply, this] {
reply->deleteLater(); reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@ -58,8 +60,6 @@ void Sonos::getHouseholds()
/*QJsonDocument data = reply->readAll(); /*QJsonDocument data = reply->readAll();
if (!data.isObject()) if (!data.isObject())
return; return;
QList<HouseholdObject> households; QList<HouseholdObject> households;
emit householdObjectsReceived(households);*/ emit householdObjectsReceived(households);*/
}); });
@ -85,14 +85,38 @@ void Sonos::loadFavorite()
} }
void Sonos::getGroups() void Sonos::getGroups(const QByteArray &householdId)
{ {
QNetworkRequest request;
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", "Bearer " + m_accessToken);
request.setRawHeader("X-Sonos-Api-Key", m_apiKey);
request.setUrl(QUrl(m_baseControlUrl + "/households/" + householdId + "/groups"));
QNetworkReply *reply = m_networkManager->get(request);
connect(reply, &QNetworkReply::finished, this, [reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// Check HTTP status code
if (status != 200 || reply->error() != QNetworkReply::NoError) {
qCWarning(dcSonos()) << "Request error:" << status << reply->errorString();
return;
}
qDebug(dcSonos()) << "Received response from Sonos" << reply->readAll();
/*QJsonDocument data = reply->readAll();
if (!data.isObject())
return;
QList<HouseholdObject> households;
emit householdObjectsReceived(households);*/
});
} }
void Sonos::createGroup() void Sonos::createGroup(const QByteArray &householdId, QList<QByteArray> playerIds)
{ {
Q_UNUSED(householdId)
Q_UNUSED(playerIds)
} }
void Sonos::modifyGroupMembers() void Sonos::modifyGroupMembers()
@ -100,105 +124,126 @@ void Sonos::modifyGroupMembers()
} }
void Sonos::setGroupMembers() void Sonos::setGroupMembers(const QByteArray &groupId)
{
}
void Sonos::getGroupVolume(int groupId)
{ {
Q_UNUSED(groupId) Q_UNUSED(groupId)
} }
void Sonos::setGroupVolume(int groupId, int volume) void Sonos::getGroupVolume(const QByteArray &groupId)
{ {
Q_UNUSED(groupId) Q_UNUSED(groupId)
Q_UNUSED(volume)
} }
void Sonos::setGroupMute(int groupId, bool mute) void Sonos::setGroupVolume(const QByteArray &groupId, int volume)
{ {
Q_UNUSED(groupId) Q_UNUSED(groupId)
Q_UNUSED(mute) Q_UNUSED(volume)
} }
void Sonos::setGroupRelativeVolume(int groupId, int volumeDelta) void Sonos::setGroupMute(const QByteArray &groupId, bool mute)
{ {
Q_UNUSED(groupId) Q_UNUSED(groupId)
Q_UNUSED(volumeDelta) Q_UNUSED(mute)
} }
void Sonos::getPlaybackStatus() void Sonos::setGroupRelativeVolume(const QByteArray &groupId, int volumeDelta)
{ {
Q_UNUSED(groupId)
Q_UNUSED(volumeDelta)
}
void Sonos::getGroupPlaybackStatus(const QByteArray &groupId)
{
Q_UNUSED(groupId)
}
void Sonos::groupLoadLineIn(const QByteArray &groupId)
{
Q_UNUSED(groupId)
} }
void Sonos::loadLineIn() void Sonos::groupPlay(const QByteArray &groupId)
{ {
Q_UNUSED(groupId)
} }
void Sonos::play() void Sonos::groupPause(const QByteArray &groupId)
{ {
Q_UNUSED(groupId)
} }
void Sonos::pause() void Sonos::groupSeek(const QByteArray &groupId)
{ {
Q_UNUSED(groupId)
} }
void Sonos::seek() void Sonos::groupSeekRelative(const QByteArray &groupId, int millis)
{ {
Q_UNUSED(groupId)
Q_UNUSED(millis)
} }
void Sonos::seekRelative() void Sonos::groupSetPlayModes(const QByteArray &groupId, PlayMode playMode)
{ {
Q_UNUSED(groupId)
Q_UNUSED(playMode)
} }
void Sonos::setPlayModes() void Sonos::groupSetShuffle(const QByteArray &groupId, bool shuffle)
{ {
Q_UNUSED(groupId)
Q_UNUSED(shuffle)
} }
void Sonos::skipToNextTrack() void Sonos::groupSetRepeat(const QByteArray &groupId, RepeatMode repeatMode)
{ {
Q_UNUSED(groupId)
Q_UNUSED(repeatMode)
} }
void Sonos::skipToPreviousTrack() void Sonos::groupSetCrossfade(const QByteArray &groupId, bool crossfade)
{ {
Q_UNUSED(groupId)
Q_UNUSED(crossfade)
} }
void Sonos::togglePlayPause() void Sonos::groupSkipToNextTrack(const QByteArray &groupId)
{ {
Q_UNUSED(groupId)
} }
void Sonos::getPlayerVolume(int playerId) void Sonos::groupSkipToPreviousTrack(const QByteArray &groupId)
{ {
Q_UNUSED(playerId) Q_UNUSED(groupId)
} }
void Sonos::setPlayerVolume(int playerId, int volume) void Sonos::groupTogglePlayPause(const QByteArray &groupId)
{ {
Q_UNUSED(playerId) Q_UNUSED(groupId)
Q_UNUSED(volume)
} }
void Sonos::setPlayerRelativeVolume(int playerId, int volumeDelta) void Sonos::getPlayerVolume(const QByteArray &playerId)
{ {
Q_UNUSED(playerId) Q_UNUSED(playerId)
Q_UNUSED(volumeDelta)
} }
void Sonos::setPlayerMute(int playerId, bool mute) void Sonos::setPlayerVolume(const QByteArray &playerId, int volume)
{ {
Q_UNUSED(playerId) Q_UNUSED(playerId)
Q_UNUSED(mute) Q_UNUSED(volume)
}
void Sonos::setPlayerRelativeVolume(const QByteArray &playerId, int volumeDelta)
{
Q_UNUSED(playerId)
Q_UNUSED(volumeDelta)
}
void Sonos::setPlayerMute(const QByteArray &playerId, bool mute)
{
Q_UNUSED(playerId)
Q_UNUSED(mute)
} }
void Sonos::getPlaylist() void Sonos::getPlaylist()

View File

@ -33,19 +33,38 @@ class Sonos : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum PlayMode { enum RepeatMode {
Repeat, RepeatModeOne,
RepeatOne, RepeatModeAll,
Shuffle, RepeatModeNone
Crossfade
}; };
struct PlayMode {
bool repeat;
bool repeatOne;
bool shuffle;
bool crossfade;
};
struct PlayerObject {
};
/* Represents a Sonos household.*/
struct GroupObject {
QByteArray CoordinatorId; //Player acting as the group coordinator for the group
QByteArray groupId; //The ID of the group.
QString playbackState; //The playback state corresponding to the group.
QList<QByteArray> playerIds; //The IDs of the primary players in the group.
QString displayName; //The display name for the group, such as “Living Room” or “Kitchen + 2”.
};
/* /*
* Represents a Sonos household.*/ * Represents a Sonos household.*/
struct HouseholdObject { /*struct HouseholdObject {
QString id; //Identifies a Sonos household. QString id; //Identifies a Sonos household.
QString name; //A user-displayable name of the Sonos household QString name; //A user-displayable name of the Sonos household
}; };*/
/* /*
* The music service identifier or a pseudo-service identifier in the case of local library. */ * The music service identifier or a pseudo-service identifier in the case of local library. */
@ -160,36 +179,40 @@ public:
void getFavorites(); void getFavorites();
void loadFavorite(); void loadFavorite();
void getGroups(); void getGroups(const QByteArray &householdId);
void createGroup(); void createGroup(const QByteArray &householdId, QList<QByteArray> playerIds);
void modifyGroupMembers(); void modifyGroupMembers();
void setGroupMembers(); void setGroupMembers(const QByteArray &groupId);
//group volume //group volume
void getGroupVolume(int groupId); //Get the volume and mute state of a group. void getGroupVolume(const QByteArray &groupId); //Get the volume and mute state of a group.
void setGroupVolume(int groupId, int volume); //Set group volume to a specific level and unmute the group if muted. void setGroupVolume(const QByteArray &groupId, int volume); //Set group volume to a specific level and unmute the group if muted.
void setGroupMute(int groupId, bool mute); //Mute and unmute the group. void setGroupMute(const QByteArray &groupId, bool mute); //Mute and unmute the group.
void setGroupRelativeVolume(int groupId, int volumeDelta); //Increase or decrease group volume. void setGroupRelativeVolume(const QByteArray &groupId, int volumeDelta); //Increase or decrease group volume.
//playback //group playback
void getPlaybackStatus(); void getGroupPlaybackStatus(const QByteArray &groupId);
void loadLineIn(); void groupLoadLineIn(const QByteArray &groupId);
void play(); void groupPlay(const QByteArray &groupId);
void pause(); void groupPause(const QByteArray &groupId);
void seek(); void groupSeek(const QByteArray &groupId);
void seekRelative(); void groupSeekRelative(const QByteArray &groupId, int deltaMillis);
void setPlayModes(); void groupSetPlayModes(const QByteArray &groupId, PlayMode playMode);
void skipToNextTrack(); void groupSetShuffle(const QByteArray &groupId, bool shuffle);
void skipToPreviousTrack(); void groupSetRepeat(const QByteArray &groupId, RepeatMode repeatMode);
void togglePlayPause(); void groupSetCrossfade(const QByteArray &groupId, bool crossfade);
void groupSkipToNextTrack(const QByteArray &groupId);
void groupSkipToPreviousTrack(const QByteArray &groupId);
void groupTogglePlayPause(const QByteArray &groupId);
//playbackMetadata //playbackMetadata
// playerVolume // playerVolume
void getPlayerVolume(int playerId); void getPlayerVolume(const QByteArray &playerId);
void setPlayerVolume(int playerId, int volume); void setPlayerVolume(const QByteArray &playerId, int volume);
void setPlayerRelativeVolume(int playerId, int volumeDelta); void setPlayerRelativeVolume(const QByteArray &playerId, int volumeDelta);
void setPlayerMute(int playerId, bool mute); void setPlayerMute(const QByteArray &playerId, bool mute);
//Playlists API namespace //Playlists API namespace
void getPlaylist(); void getPlaylist();
@ -201,16 +224,18 @@ public:
void setPlayerSettings(); void setPlayerSettings();
private: private:
QByteArray m_baseAuthorizationUrl = "api.sonos.com/login/v3/oauth"; QByteArray m_baseAuthorizationUrl = "https://api.sonos.com/login/v3/oauth";
QByteArray m_baseControlUrl = "api.ws.sonos.com/control/api/v1"; QByteArray m_baseControlUrl = "https://api.ws.sonos.com/control/api/v1";
QByteArray m_accessToken; QByteArray m_accessToken;
QByteArray m_apiKey = "b15cbf8c-a39c-47aa-bd93-635a96e9696c";
NetworkAccessManager *m_networkManager = nullptr; NetworkAccessManager *m_networkManager = nullptr;
private slots: private slots:
signals: signals:
void householdIdsReceived(QList<QByteArray> householdIds);
void groupsReceived(QList<GroupObject> groups);
}; };