added plugin Storage for tokens
This commit is contained in:
parent
34b97e89d4
commit
4254d3cb3c
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
147
sonos/sonos.cpp
147
sonos/sonos.cpp
@ -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()
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user