refactored AVR connection

This commit is contained in:
nymea 2019-06-28 20:14:43 +02:00
parent 89462334a2
commit 8d60bbb719
7 changed files with 466 additions and 299 deletions

261
denon/avrconnection.cpp Normal file
View File

@ -0,0 +1,261 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@nymea.io> *
* Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "avrconnection.h"
#include "extern-plugininfo.h"
AvrConnection::AvrConnection(const QHostAddress &hostAddress, const int &port, QObject *parent) :
QObject(parent),
m_hostAddress(hostAddress),
m_port(port)
{
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::connected, this, &AvrConnection::onConnected);
connect(m_socket, &QTcpSocket::disconnected, this, &AvrConnection::onDisconnected);
connect(m_socket, &QTcpSocket::readyRead, this, &AvrConnection::readData);
// Note: error signal will be interpreted as function, not as signal in C++11
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
}
AvrConnection::~AvrConnection()
{
m_socket->close();
}
void AvrConnection::connect()
{
if (m_socket->state() == QAbstractSocket::ConnectingState) {
return;
}
m_socket->connectToHost(m_hostAddress, m_port);
}
void AvrConnection::disconnect()
{
m_socket->close();
}
QHostAddress AvrConnection::hostAddress() const
{
return m_hostAddress;
}
int AvrConnection::port() const
{
return m_port;
}
bool AvrConnection::connected()
{
return m_socket->isOpen();
}
void AvrConnection::getAllStatus()
{
sendCommand("PW?\rSI?\rMV?\rMS?\rMU?\r");
}
void AvrConnection::getChannel()
{
sendCommand("SI?\r");
}
void AvrConnection::getVolume()
{
sendCommand("MV?\r");
}
void AvrConnection::getMute()
{
sendCommand("MU?\r");
}
void AvrConnection::getPower()
{
sendCommand("PW?\r");
}
void AvrConnection::getSurroundMode()
{
sendCommand("MS?\r");
}
void AvrConnection::sendCommand(const QByteArray &message)
{
m_socket->write(message);
}
void AvrConnection::setChannel(const QByteArray &channel)
{
QByteArray cmd = "SI" + channel + "\r";
qCDebug(dcDenon) << "Change to channel:" << cmd;
sendCommand(cmd);
}
void AvrConnection::setVolume(int volume)
{
qCDebug(dcDenon) << "Set volume" << volume;
QByteArray cmd = "MV" + QByteArray::number(volume) + "\r";
sendCommand(cmd);
}
void AvrConnection::setMute(bool mute)
{
qCDebug(dcDenon) << "Set mute" << mute;
QByteArray cmd;
if (mute) {
cmd = "MUON\r";
} else {
cmd = "MUOFF\r";
}
sendCommand(cmd);
}
void AvrConnection::setPower(bool power)
{
qCDebug(dcDenon) << "Set power" << power;
QByteArray cmd;
if (power) {
cmd = "PWON\r";
} else {
cmd = "PWSTANDBY\r";
}
sendCommand(cmd);
}
void AvrConnection::setSurroundMode(const QByteArray &surroundMode)
{
qCDebug(dcDenon) << "Set surround mode" << surroundMode;
QByteArray cmd = "MS" + surroundMode + "\r";
sendCommand(cmd);
}
void AvrConnection::increaseVolume()
{
qCDebug(dcDenon) << "Execute volume increase";
QByteArray cmd = "MVUP\r";
sendCommand(cmd);
}
void AvrConnection::decreaseVolume()
{
qCDebug(dcDenon) << "Execute volume decrease";
QByteArray cmd = "MVDOWN\r";
sendCommand(cmd);
}
void AvrConnection::onConnected()
{
qCDebug(dcDenon) << "connected successfully to" << hostAddress().toString() << port();
emit connectionStatusChanged(true);
}
void AvrConnection::onDisconnected()
{
qCDebug(dcDenon) << "disconnected from" << hostAddress().toString() << port();
emit connectionStatusChanged(false);
}
void AvrConnection::onError(QAbstractSocket::SocketError socketError)
{
qCWarning(dcDenon) << "socket error:" << socketError << m_socket->errorString();
emit socketErrorOccured(socketError);
}
void AvrConnection::readData()
{
QByteArray data = m_socket->readAll();
qCDebug(dcDenon) << "Data received" << data;
if (data.contains("MV") && !data.contains("MAX")){
int index = data.indexOf("MV");
int volume = data.mid(index+2, 2).toInt();
emit volumeChanged(volume);
}
if (data.left(2).contains("SI")) {
QByteArray cmd;
if (data.contains("TUNER")) {
cmd = "TUNER";
} else if (data.contains("DVD")) {
cmd = "DVD";
} else if (data.contains("BD")) {
cmd = "BD";
} else if (data.contains("TV")) {
cmd = "TV";
} else if (data.contains("SAT/CBL")) {
cmd = "SAT/CBL";
} else if (data.contains("MPLAY")) {
cmd = "MPLAY";
} else if (data.contains("GAME")) {
cmd = "GAME";
} else if (data.contains("AUX1")) {
cmd = "AUX1";
} else if (data.contains("NET")) {
cmd = "NET";
} else if (data.contains("PANDORA")) {
cmd = "PANDORA";
} else if (data.contains("SIRIUSXM")) {
cmd = "SIRIUSXM";
} else if (data.contains("SPOTIFY")) {
cmd = "SPOTIFY";
} else if (data.contains("FLICKR")) {
cmd = "FLICKR";
} else if (data.contains("FAVORITES")) {
cmd = "FAVORITES";
} else if (data.contains("IRADIO")) {
cmd = "IRADIO";
} else if (data.contains("SERVER")) {
cmd = "SERVER";
} else if (data.contains("USB/IPOD")) {
cmd = "USB/IPOD";
} else if (data.contains("IPD")) {
cmd = "IPD";
} else if (data.contains("IRP")) {
cmd = "IRP";
} else if (data.contains("FVP")) {
cmd = "FVP";
}
emit channelChanged(cmd);
}
if (data.contains("PWON")) {
emit powerChanged(true);
}
if (data.contains("PWSTANDBY")) {
emit powerChanged(false);
}
if (data.contains("MUON")) {
emit muteChanged(false);
}
if (data.contains("MUOFF")) {
emit muteChanged(false);
}
if (data.left(2).contains("MS")) {
data.remove(0, 2);
QByteArray cmd = data;
emit surroundModeChanged(cmd);
}
}

View File

@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> * * Copyright (C) 2015 Simon Stürz <simon.stuerz@nymea.io> *
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> * * Copyright (C) 2019 Bernhard Trinnes <bernhard.trinnes@nymea.io> *
* * * *
* This file is part of nymea. * * This file is part of nymea. *
* * * *
@ -21,36 +21,48 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef DENONCONNECTION_H #ifndef AVRCONNECTION_H
#define DENONCONNECTION_H #define AVRCONNECTION_H
#include <QObject> #include <QObject>
#include <QTcpSocket> #include <QTcpSocket>
#include <QHostAddress> #include <QHostAddress>
class DenonConnection : public QObject class AvrConnection : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DenonConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = 0); explicit AvrConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = nullptr);
~DenonConnection(); ~AvrConnection();
void connectDenon(); void connect();
void disconnectDenon(); void disconnect();
QHostAddress hostAddress() const; QHostAddress hostAddress() const;
int port() const; int port() const;
bool connected(); bool connected();
void sendData(const QByteArray &message); void getAllStatus();
void getChannel();
void getVolume();
void getMute();
void getPower();
void getSurroundMode();
void setChannel(const QByteArray &channel);
void setVolume(int volume);
void setMute(bool mute);
void setPower(bool power);
void setSurroundMode(const QByteArray &surroundMode);
void increaseVolume();
void decreaseVolume();
private: private:
QTcpSocket *m_socket; QTcpSocket *m_socket = nullptr;
QHostAddress m_hostAddress; QHostAddress m_hostAddress;
int m_port; int m_port;
bool m_connected;
void sendCommand(const QByteArray &message);
private slots: private slots:
void onConnected(); void onConnected();
@ -58,13 +70,14 @@ private slots:
void onError(QAbstractSocket::SocketError socketError); void onError(QAbstractSocket::SocketError socketError);
void readData(); void readData();
void setConnected(const bool &connected);
signals: signals:
void socketErrorOccured(QAbstractSocket::SocketError socketError); void socketErrorOccured(QAbstractSocket::SocketError socketError);
void connectionStatusChanged(); void connectionStatusChanged(bool status);
void dataReady(const QByteArray &data); void volumeChanged(int volume);
void muteChanged(bool mute);
void channelChanged(const QByteArray &channel);
void powerChanged(bool power);
void surroundModeChanged(const QByteArray &surroundMode);
}; };
#endif // DENONCONNECTION_H #endif // AVRCONNECTION_H

View File

@ -6,12 +6,12 @@ TARGET = $$qtLibraryTarget(nymea_deviceplugindenon)
SOURCES += \ SOURCES += \
deviceplugindenon.cpp \ deviceplugindenon.cpp \
denonconnection.cpp \
heos.cpp \ heos.cpp \
heosplayer.cpp \ heosplayer.cpp \
avrconnection.cpp
HEADERS += \ HEADERS += \
deviceplugindenon.h \ deviceplugindenon.h \
denonconnection.h \
heos.h \ heos.h \
heosplayer.h \ heosplayer.h \
avrconnection.h

View File

@ -1,108 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "denonconnection.h"
#include "extern-plugininfo.h"
DenonConnection::DenonConnection(const QHostAddress &hostAddress, const int &port, QObject *parent) :
QObject(parent),
m_hostAddress(hostAddress),
m_port(port),
m_connected(false)
{
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::connected, this, &DenonConnection::onConnected);
connect(m_socket, &QTcpSocket::disconnected, this, &DenonConnection::onDisconnected);
connect(m_socket, &QTcpSocket::readyRead, this, &DenonConnection::readData);
// Note: error signal will be interpreted as function, not as signal in C++11
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
}
DenonConnection::~DenonConnection()
{
m_socket->close();
}
void DenonConnection::connectDenon()
{
if (m_socket->state() == QAbstractSocket::ConnectingState) {
return;
}
m_socket->connectToHost(m_hostAddress, m_port);
}
void DenonConnection::disconnectDenon()
{
m_socket->close();
}
QHostAddress DenonConnection::hostAddress() const
{
return m_hostAddress;
}
int DenonConnection::port() const
{
return m_port;
}
bool DenonConnection::connected()
{
return m_connected;
}
void DenonConnection::sendData(const QByteArray &message)
{
m_socket->write(message);
}
void DenonConnection::onConnected()
{
qCDebug(dcDenon) << "connected successfully to" << hostAddress().toString() << port();
setConnected(true);
}
void DenonConnection::onDisconnected()
{
qCDebug(dcDenon) << "disconnected from" << hostAddress().toString() << port();
setConnected(false);
}
void DenonConnection::onError(QAbstractSocket::SocketError socketError)
{
qCWarning(dcDenon) << "socket error:" << socketError << m_socket->errorString();
emit socketErrorOccured(socketError);
}
void DenonConnection::readData()
{
QByteArray data = m_socket->readAll();
emit dataReady(QString(data).toUtf8());
}
void DenonConnection::setConnected(const bool &connected)
{
m_connected = connected;
emit connectionStatusChanged();
}

View File

@ -43,7 +43,7 @@
#include "deviceplugindenon.h" #include "deviceplugindenon.h"
#include "plugininfo.h" #include "plugininfo.h"
#include "plugin/device.h" #include "devices/device.h"
#include "network/networkaccessmanager.h" #include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h" #include "network/upnp/upnpdiscovery.h"
#include "network/upnp/upnpdiscoveryreply.h" #include "network/upnp/upnpdiscoveryreply.h"
@ -59,7 +59,7 @@ DevicePluginDenon::DevicePluginDenon()
{ {
} }
DeviceManager::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) Device::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{ {
Q_UNUSED(params) Q_UNUSED(params)
@ -67,7 +67,7 @@ DeviceManager::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassI
UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("urn:schemas-upnp-org:device:MediaRenderer:1", "nymea", 7000); UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("urn:schemas-upnp-org:device:MediaRenderer:1", "nymea", 7000);
connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginDenon::onUpnpDiscoveryFinished); connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginDenon::onUpnpDiscoveryFinished);
return DeviceManager::DeviceErrorAsync; return Device::DeviceErrorAsync;
} }
if (deviceClassId == heosDeviceClassId) { if (deviceClassId == heosDeviceClassId) {
@ -80,9 +80,9 @@ DeviceManager::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassI
*/ */
UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices(); UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices();
connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginDenon::onUpnpDiscoveryFinished); connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginDenon::onUpnpDiscoveryFinished);
return DeviceManager::DeviceErrorAsync; return Device::DeviceErrorAsync;
} }
return DeviceManager::DeviceErrorDeviceClassNotFound; return Device::DeviceErrorDeviceClassNotFound;
} }
Device::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device) Device::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device)
@ -98,18 +98,22 @@ Device::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device)
QHostAddress address(device->paramValue(AVRX1000DeviceIpParamTypeId).toString()); QHostAddress address(device->paramValue(AVRX1000DeviceIpParamTypeId).toString());
if (address.isNull()) { if (address.isNull()) {
qCWarning(dcDenon) << "Could not parse ip address" << device->paramValue(AVRX1000DeviceIpParamTypeId).toString(); qCWarning(dcDenon) << "Could not parse ip address" << device->paramValue(AVRX1000DeviceIpParamTypeId).toString();
return DeviceManager::DeviceSetupStatusFailure; return Device::DeviceSetupStatusFailure;
} }
DenonConnection *denonConnection = new DenonConnection(address, 23, this); AvrConnection *denonConnection = new AvrConnection(address, 23, this);
connect(denonConnection, &DenonConnection::connectionStatusChanged, this, &DevicePluginDenon::onAVRConnectionChanged); connect(denonConnection, &AvrConnection::connectionStatusChanged, this, &DevicePluginDenon::onAvrConnectionChanged);
connect(denonConnection, &DenonConnection::socketErrorOccured, this, &DevicePluginDenon::onAVRSocketError); connect(denonConnection, &AvrConnection::socketErrorOccured, this, &DevicePluginDenon::onAvrSocketError);
connect(denonConnection, &DenonConnection::dataReady, this, &DevicePluginDenon::onAVRDataReceived); connect(denonConnection, &AvrConnection::channelChanged, this, &DevicePluginDenon::onAvrChannelChanged);
connect(denonConnection, &AvrConnection::powerChanged, this, &DevicePluginDenon::onAvrPowerChanged);
connect(denonConnection, &AvrConnection::volumeChanged, this, &DevicePluginDenon::onAvrVolumeChanged);
connect(denonConnection, &AvrConnection::surroundModeChanged, this, &DevicePluginDenon::onAvrSurroundModeChanged);
connect(denonConnection, &AvrConnection::muteChanged, this, &DevicePluginDenon::onAvrMuteChanged);
m_asyncSetups.append(denonConnection); m_asyncSetups.append(denonConnection);
denonConnection->connectDenon(); denonConnection->connect();
m_denonConnections.insert(device, denonConnection); m_avrConnections.insert(device, denonConnection);
return DeviceManager::DeviceSetupStatusAsync; return Device::DeviceSetupStatusAsync;
} }
if (device->deviceClassId() == heosDeviceClassId) { if (device->deviceClassId() == heosDeviceClassId) {
@ -128,13 +132,13 @@ Device::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device)
heos->connectHeos(); heos->connectHeos();
m_heos.insert(device, heos); m_heos.insert(device, heos);
return DeviceManager::DeviceSetupStatusAsync; return Device::DeviceSetupStatusAsync;
} }
if (device->deviceClassId() == heosPlayerDeviceClassId) { if (device->deviceClassId() == heosPlayerDeviceClassId) {
return DeviceManager::DeviceSetupStatusSuccess; return Device::DeviceSetupStatusSuccess;
} }
return DeviceManager::DeviceSetupStatusFailure; return Device::DeviceSetupStatusFailure;
} }
void DevicePluginDenon::deviceRemoved(Device *device) void DevicePluginDenon::deviceRemoved(Device *device)
@ -142,17 +146,17 @@ void DevicePluginDenon::deviceRemoved(Device *device)
qCDebug(dcDenon) << "Delete " << device->name(); qCDebug(dcDenon) << "Delete " << device->name();
if (device->deviceClassId() == AVRX1000DeviceClassId) { if (device->deviceClassId() == AVRX1000DeviceClassId) {
DenonConnection *denonConnection = m_denonConnections.value(device); AvrConnection *denonConnection = m_avrConnections.value(device);
m_denonConnections.remove(device); m_avrConnections.remove(device);
denonConnection->disconnectDenon(); denonConnection->disconnect();
denonConnection->deleteLater(); denonConnection->deleteLater();
} }
if (device->deviceClassId() == heosDeviceClassId) { if (device->deviceClassId() == heosDeviceClassId) {
if (m_denonConnections.contains(device)) { if (m_avrConnections.contains(device)) {
DenonConnection *denonConnection = m_denonConnections.value(device); AvrConnection *denonConnection = m_avrConnections.value(device);
m_denonConnections.remove(device); m_avrConnections.remove(device);
denonConnection->disconnectDenon(); denonConnection->disconnect();
denonConnection->deleteLater(); denonConnection->deleteLater();
} }
} }
@ -166,57 +170,44 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio
{ {
qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params(); qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params();
if (device->deviceClassId() == AVRX1000DeviceClassId) { if (device->deviceClassId() == AVRX1000DeviceClassId) {
DenonConnection *denonConnection = m_denonConnections.value(device); AvrConnection *avrConnection = m_avrConnections.value(device);
if (action.actionTypeId() == AVRX1000PowerActionTypeId) { if (action.actionTypeId() == AVRX1000PowerActionTypeId) {
qCDebug(dcDenon) << "set power action" << action.id(); bool power = action.param(AVRX1000PowerActionPowerParamTypeId).value().toBool();
qCDebug(dcDenon) << "power: " << action.param(AVRX1000PowerActionPowerParamTypeId).value().Bool; avrConnection->setPower(power);
if (action.param(AVRX1000PowerActionPowerParamTypeId).value().toBool() == true) {
QByteArray cmd = "PWON\r";
qCDebug(dcDenon) << "Execute power: " << action.id() << cmd;
denonConnection->sendData(cmd);
} else {
QByteArray cmd = "PWSTANDBY\r";
qCDebug(dcDenon) << "Execute power: " << action.id() << cmd;
denonConnection->sendData(cmd);
}
return Device::DeviceErrorNoError; return Device::DeviceErrorNoError;
} else if (action.actionTypeId() == AVRX1000VolumeActionTypeId) { } else if (action.actionTypeId() == AVRX1000VolumeActionTypeId) {
QByteArray vol = action.param(AVRX1000VolumeActionVolumeParamTypeId).value().toByteArray(); int vol = action.param(AVRX1000VolumeActionVolumeParamTypeId).value().toInt();
QByteArray cmd = "MV" + vol + "\r"; avrConnection->setVolume(vol);
return Device::DeviceErrorNoError;
qCDebug(dcDenon) << "Execute volume" << action.id() << cmd;
denonConnection->sendData(cmd);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == AVRX1000ChannelActionTypeId) { } else if (action.actionTypeId() == AVRX1000ChannelActionTypeId) {
qCDebug(dcDenon) << "Execute update action" << action.id(); qCDebug(dcDenon) << "Execute update action" << action.id();
QByteArray channel = action.param(AVRX1000ChannelActionChannelParamTypeId).value().toByteArray(); QByteArray channel = action.param(AVRX1000ChannelActionChannelParamTypeId).value().toByteArray();
QByteArray cmd = "SI" + channel + "\r"; avrConnection->setChannel(channel);
return Device::DeviceErrorNoError;
qCDebug(dcDenon) << "Change to channel:" << cmd;
denonConnection->sendData(cmd);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == AVRX1000IncreaseVolumeActionTypeId) { } else if (action.actionTypeId() == AVRX1000IncreaseVolumeActionTypeId) {
QByteArray cmd = "MVUP\r";
qCDebug(dcDenon) << "Execute volume increase" << action.id() << cmd; avrConnection->increaseVolume();
denonConnection->sendData(cmd); return Device::DeviceErrorNoError;
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == AVRX1000DecreaseVolumeActionTypeId) { } else if (action.actionTypeId() == AVRX1000DecreaseVolumeActionTypeId) {
QByteArray cmd = "MVDOWN\r";
qCDebug(dcDenon) << "Execute volume decrease" << action.id() << cmd; avrConnection->decreaseVolume();
denonConnection->sendData(cmd); return Device::DeviceErrorNoError;
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == AVRX1000SurroundModeActionTypeId) {
QByteArray surroundMode = action.param(AVRX1000SurroundModeActionSurroundModeParamTypeId).value().toByteArray();
avrConnection->setSurroundMode(surroundMode);
return Device::DeviceErrorNoError;
} }
return DeviceManager::DeviceErrorActionTypeNotFound; return Device::DeviceErrorActionTypeNotFound;
} }
if (device->deviceClassId() == heosPlayerDeviceClassId) { if (device->deviceClassId() == heosPlayerDeviceClassId) {
@ -228,13 +219,13 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio
if (action.actionTypeId() == heosPlayerVolumeActionTypeId) { if (action.actionTypeId() == heosPlayerVolumeActionTypeId) {
int volume = action.param(heosPlayerVolumeActionVolumeParamTypeId).value().toInt(); int volume = action.param(heosPlayerVolumeActionVolumeParamTypeId).value().toInt();
heos->setVolume(playerId, volume); heos->setVolume(playerId, volume);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerMuteActionTypeId) { if (action.actionTypeId() == heosPlayerMuteActionTypeId) {
bool mute = action.param(heosPlayerMuteActionMuteParamTypeId).value().toBool(); bool mute = action.param(heosPlayerMuteActionMuteParamTypeId).value().toBool();
heos->setMute(playerId, mute); heos->setMute(playerId, mute);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerPlaybackStatusActionTypeId) { if (action.actionTypeId() == heosPlayerPlaybackStatusActionTypeId) {
@ -246,7 +237,7 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio
} else if (playbackStatus == "pausing") { } else if (playbackStatus == "pausing") {
heos->setPlayerState(playerId, Heos::HeosPlayerState::Pause); heos->setPlayerState(playerId, Heos::HeosPlayerState::Pause);
} }
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerShuffleActionTypeId) { if (action.actionTypeId() == heosPlayerShuffleActionTypeId) {
@ -255,45 +246,45 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio
repeatMode = Heos::HeosRepeatMode::Off; repeatMode = Heos::HeosRepeatMode::Off;
heos->setPlayMode(playerId, repeatMode, shuffle); heos->setPlayMode(playerId, repeatMode, shuffle);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerSkipBackActionTypeId) { if (action.actionTypeId() == heosPlayerSkipBackActionTypeId) {
heos->playPrevious(playerId); heos->playPrevious(playerId);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerFastRewindActionTypeId) { if (action.actionTypeId() == heosPlayerFastRewindActionTypeId) {
return DeviceManager::DeviceErrorActionTypeNotFound; return Device::DeviceErrorActionTypeNotFound;
} }
if (action.actionTypeId() == heosPlayerStopActionTypeId) { if (action.actionTypeId() == heosPlayerStopActionTypeId) {
heos->setPlayerState(playerId, Heos::HeosPlayerState::Stop); heos->setPlayerState(playerId, Heos::HeosPlayerState::Stop);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerPlayActionTypeId) { if (action.actionTypeId() == heosPlayerPlayActionTypeId) {
heos->setPlayerState(playerId, Heos::HeosPlayerState::Play); heos->setPlayerState(playerId, Heos::HeosPlayerState::Play);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerPauseActionTypeId) { if (action.actionTypeId() == heosPlayerPauseActionTypeId) {
heos->setPlayerState(playerId, Heos::HeosPlayerState::Pause); heos->setPlayerState(playerId, Heos::HeosPlayerState::Pause);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
if (action.actionTypeId() == heosPlayerFastForwardActionTypeId) { if (action.actionTypeId() == heosPlayerFastForwardActionTypeId) {
return DeviceManager::DeviceErrorActionTypeNotFound; return Device::DeviceErrorActionTypeNotFound;
} }
if (action.actionTypeId() == heosPlayerSkipNextActionTypeId) { if (action.actionTypeId() == heosPlayerSkipNextActionTypeId) {
heos->playNext(playerId); heos->playNext(playerId);
return DeviceManager::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
return DeviceManager::DeviceErrorActionTypeNotFound; return Device::DeviceErrorActionTypeNotFound;
} }
return Device::DeviceErrorDeviceClassNotFound; return Device::DeviceErrorDeviceClassNotFound;
} }
@ -324,13 +315,13 @@ void DevicePluginDenon::postSetupDevice(Device *device)
void DevicePluginDenon::onPluginTimer() void DevicePluginDenon::onPluginTimer()
{ {
foreach(DenonConnection *denonConnection, m_denonConnections.values()) { foreach(AvrConnection *denonConnection, m_avrConnections.values()) {
if (!denonConnection->connected()) { if (!denonConnection->connected()) {
denonConnection->connectDenon(); denonConnection->connect();
} }
Device *device = m_denonConnections.key(denonConnection); Device *device = m_avrConnections.key(denonConnection);
if (device->deviceClassId() == AVRX1000DeviceClassId) { if (device->deviceClassId() == AVRX1000DeviceClassId) {
denonConnection->sendData("PW?\rSI?\rMV?\r"); denonConnection->getAllStatus();
} }
} }
@ -360,113 +351,94 @@ void DevicePluginDenon::onPluginTimer()
} }
} }
void DevicePluginDenon::onAVRConnectionChanged() void DevicePluginDenon::onAvrConnectionChanged(bool status)
{ {
DenonConnection *denonConnection = static_cast<DenonConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Device *device = m_denonConnections.key(denonConnection); Device *device = m_avrConnections.key(denonConnection);
if (!device)
return;
if (device->deviceClassId() == AVRX1000DeviceClassId) { if (device->deviceClassId() == AVRX1000DeviceClassId) {
// if the device is connected // if the device is connected
if (denonConnection->connected()) { if (status) {
// and from the first setup // and from the first setup
if (m_asyncSetups.contains(denonConnection)) { if (m_asyncSetups.contains(denonConnection)) {
m_asyncSetups.removeAll(denonConnection); m_asyncSetups.removeAll(denonConnection);
denonConnection->sendData("PW?\rSI?\rMV?\r");
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess);
} }
} }
device->setStateValue(AVRX1000ConnectedStateTypeId, denonConnection->connected()); device->setStateValue(AVRX1000ConnectedStateTypeId, denonConnection->connected());
} }
} }
void DevicePluginDenon::onAVRDataReceived(const QByteArray &data) void DevicePluginDenon::onAvrVolumeChanged(int volume)
{ {
DenonConnection *denonConnection = static_cast<DenonConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Device *device = m_denonConnections.key(denonConnection); Device *device = m_avrConnections.key(denonConnection);
qCDebug(dcDenon) << "Data received" << data; if (!device)
return;
if (device->deviceClassId() == AVRX1000DeviceClassId) { if (device->deviceClassId() == AVRX1000DeviceClassId) {
if (data.contains("MV") && !data.contains("MAX")){ device->setStateValue(AVRX1000VolumeStateTypeId, volume);
int index = data.indexOf("MV"); }
int vol = data.mid(index+2, 2).toInt(); }
qCDebug(dcDenon) << "Update volume:" << vol; void DevicePluginDenon::onAvrMuteChanged(bool mute)
device->setStateValue(AVRX1000VolumeStateTypeId, vol); {
} AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Device *device = m_avrConnections.key(denonConnection);
if (!device)
return;
if (data.contains("SI")) { if (device->deviceClassId() == AVRX1000DeviceClassId) {
QString cmd; device->setStateValue(AVRX1000MuteStateTypeId, mute);
if (data.contains("TUNER")) {
cmd = "TUNER";
} else if (data.contains("DVD")) {
cmd = "DVD";
} else if (data.contains("BD")) {
cmd = "BD";
} else if (data.contains("TV")) {
cmd = "TV";
} else if (data.contains("SAT/CBL")) {
cmd = "SAT/CBL";
} else if (data.contains("MPLAY")) {
cmd = "MPLAY";
} else if (data.contains("GAME")) {
cmd = "GAME";
} else if (data.contains("AUX1")) {
cmd = "AUX1";
} else if (data.contains("NET")) {
cmd = "NET";
} else if (data.contains("PANDORA")) {
cmd = "PANDORA";
} else if (data.contains("SIRIUSXM")) {
cmd = "SIRIUSXM";
} else if (data.contains("SPOTIFY")) {
cmd = "SPOTIFY";
} else if (data.contains("FLICKR")) {
cmd = "FLICKR";
} else if (data.contains("FAVORITES")) {
cmd = "FAVORITES";
} else if (data.contains("IRADIO")) {
cmd = "IRADIO";
} else if (data.contains("SERVER")) {
cmd = "SERVER";
} else if (data.contains("USB/IPOD")) {
cmd = "USB/IPOD";
} else if (data.contains("IPD")) {
cmd = "IPD";
} else if (data.contains("IRP")) {
cmd = "IRP";
} else if (data.contains("FVP")) {
cmd = "FVP";
}
qCDebug(dcDenon) << "Update channel:" << cmd;
device->setStateValue(AVRX1000ChannelStateTypeId, cmd);
} }
}
if (data.contains("PWON")) { void DevicePluginDenon::onAvrPowerChanged(bool power)
qCDebug(dcDenon) << "Update power on"; {
device->setStateValue(AVRX1000PowerStateTypeId, true); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
} else if (data.contains("PWSTANDBY")) { Device *device = m_avrConnections.key(denonConnection);
qCDebug(dcDenon) << "Update power off"; if (!device)
device->setStateValue(AVRX1000PowerStateTypeId, false); return;
if (device->deviceClassId() == AVRX1000DeviceClassId) {
device->setStateValue(AVRX1000PowerStateTypeId, power);
} }
}
void DevicePluginDenon::onAvrSurroundModeChanged(const QByteArray &surroundMode)
{
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Device *device = m_avrConnections.key(denonConnection);
if (!device)
return;
if (device->deviceClassId() == AVRX1000DeviceClassId) {
device->setStateValue(AVRX1000SurroundModeStateTypeId, surroundMode);
} }
} }
void DevicePluginDenon::onAVRSocketError() void DevicePluginDenon::onAvrSocketError()
{ {
DenonConnection *denonConnection = static_cast<DenonConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Device *device = m_denonConnections.key(denonConnection); Device *device = m_avrConnections.key(denonConnection);
if (!device)
return;
if (device->deviceClassId() == AVRX1000DeviceClassId) { if (device->deviceClassId() == AVRX1000DeviceClassId) {
// Check if setup running for this device // Check if setup running for this device
if (m_asyncSetups.contains(denonConnection)) { if (m_asyncSetups.contains(denonConnection)) {
m_asyncSetups.removeAll(denonConnection); m_asyncSetups.removeAll(denonConnection);
qCWarning(dcDenon()) << "Could not add device. The setup failed."; qCWarning(dcDenon()) << "Could not add device. The setup failed.";
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure);
// Delete the connection, the device will not be added and // Delete the connection, the device will not be added and
// the connection will be created in the next setup // the connection will be created in the next setup
denonConnection->deleteLater(); denonConnection->deleteLater();
m_denonConnections.remove(device); m_avrConnections.remove(device);
} }
} }
} }
@ -527,7 +499,7 @@ void DevicePluginDenon::onHeosConnectionChanged()
heos->registerForChangeEvents(true); heos->registerForChangeEvents(true);
Device *device = m_heos.key(heos); Device *device = m_heos.key(heos);
if (!device->setupComplete() && heos->connected()) { if (!device->setupComplete() && heos->connected()) {
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess);
} }
} }
@ -623,3 +595,4 @@ void DevicePluginDenon::onHeosNowPlayingMediaStatusReceived(int playerId, QStrin
break; break;
} }
} }

View File

@ -24,10 +24,9 @@
#ifndef DEVICEPLUGINDENON_H #ifndef DEVICEPLUGINDENON_H
#define DEVICEPLUGINDENON_H #define DEVICEPLUGINDENON_H
#include "devicemanager.h" #include "devices/deviceplugin.h"
#include "plugin/deviceplugin.h"
#include "plugintimer.h" #include "plugintimer.h"
#include "denonconnection.h" #include "avrconnection.h"
#include "heos.h" #include "heos.h"
#include <QPair> #include <QPair>
@ -47,18 +46,18 @@ class DevicePluginDenon : public DevicePlugin
public: public:
explicit DevicePluginDenon(); explicit DevicePluginDenon();
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; Device::DeviceSetupStatus setupDevice(Device *device) override;
void postSetupDevice(Device * device) override; void postSetupDevice(Device * device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; Device::DeviceError executeAction(Device *device, const Action &action) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
private: private:
PluginTimer *m_pluginTimer = nullptr; PluginTimer *m_pluginTimer = nullptr;
QHash<Device *, DenonConnection*> m_denonConnections; QHash<Device *, AvrConnection*> m_avrConnections;
QHash<Device *, Heos*> m_heos; QHash<Device *, Heos*> m_heos;
QList<DenonConnection *> m_asyncSetups; QList<AvrConnection *> m_asyncSetups;
QHash<int, Device *> m_playerIds; QHash<int, Device *> m_playerIds;
QHash<int, Device *> m_discoveredPlayerIds; QHash<int, Device *> m_discoveredPlayerIds;
@ -67,11 +66,6 @@ private:
private slots: private slots:
void onPluginTimer(); void onPluginTimer();
void onAVRConnectionChanged();
void onAVRDataReceived(const QByteArray &data);
void onAVRSocketError();
void onUpnpDiscoveryFinished(); void onUpnpDiscoveryFinished();
void onHeosConnectionChanged(); void onHeosConnectionChanged();
@ -82,6 +76,14 @@ private slots:
void onHeosMuteStatusReceived(int playerId, bool mute); void onHeosMuteStatusReceived(int playerId, bool mute);
void onHeosVolumeStatusReceived(int playerId, int volume); void onHeosVolumeStatusReceived(int playerId, int volume);
void onHeosNowPlayingMediaStatusReceived(int playerId, QString source, QString artist, QString album, QString Song, QString artwork); void onHeosNowPlayingMediaStatusReceived(int playerId, QString source, QString artist, QString album, QString Song, QString artwork);
void onAvrConnectionChanged(bool status);
void onAvrSocketError();
void onAvrVolumeChanged(int volume);
void onAvrChannelChanged(const QByteArray &channel);
void onAvrMuteChanged(bool mute);
void onAvrPowerChanged(bool power);
void onAvrSurroundModeChanged(const QByteArray &surroundMode);
}; };
#endif // DEVICEPLUGINDENON_H #endif // DEVICEPLUGINDENON_H

View File

@ -94,6 +94,32 @@
"FVP" "FVP"
], ],
"defaultValue": "TUNER" "defaultValue": "TUNER"
},
{
"displayName": "Surround mode",
"id": "4f203bdd-691c-4384-a934-2d49a5448f0a",
"name": "surroundMode",
"displayNameEvent": "Surround mode changed",
"displayNameAction": "Set surround mode",
"type": "QString",
"writable": true,
"possibleValues": [
"MOVIE",
"MUSIC",
"GAME",
"PURE DIRECT",
"DIRECT",
"STEREO",
"STANDARD",
"DOLBY DIGITAL",
"DTS SUROUND",
"MCH STEREO",
"ROCK ARENA",
"JAZZ CLUB",
"MONO MOVIE",
"MATRIX"
],
"defaultValue": "MOVIE"
} }
], ],
"actionTypes": [ "actionTypes": [
@ -156,8 +182,8 @@
{ {
"id": "4d1790bf-28c6-4c1f-8892-ba1a0ef140f5", "id": "4d1790bf-28c6-4c1f-8892-ba1a0ef140f5",
"name": "connected", "name": "connected",
"displayName": "connected", "displayName": "Connected",
"displayNameEvent": "connected changed", "displayNameEvent": "Connected changed",
"defaultValue": false, "defaultValue": false,
"type": "bool" "type": "bool"
} }
@ -200,7 +226,7 @@
"id": "9a4e527e-057c-4b19-8a02-605cc8349f5e", "id": "9a4e527e-057c-4b19-8a02-605cc8349f5e",
"name": "connected", "name": "connected",
"displayName": "connected", "displayName": "connected",
"displayNameEvent": "connected changed", "displayNameEvent": "Connected changed",
"type": "bool", "type": "bool",
"defaultValue": false, "defaultValue": false,
"cached": false "cached": false
@ -208,9 +234,9 @@
{ {
"id": "fcc89c7c-b793-4b6f-a3dc-0e0e3a86748f", "id": "fcc89c7c-b793-4b6f-a3dc-0e0e3a86748f",
"name": "mute", "name": "mute",
"displayName": "mute", "displayName": "Mute",
"displayNameEvent": "mute changed", "displayNameEvent": "Mute changed",
"displayNameAction": "set mute", "displayNameAction": "Set mute",
"type": "bool", "type": "bool",
"defaultValue": false, "defaultValue": false,
"cached": false, "cached": false,
@ -219,7 +245,7 @@
{ {
"id": "6d4886a1-fa5d-4889-96c5-7a1c206f59be", "id": "6d4886a1-fa5d-4889-96c5-7a1c206f59be",
"name": "volume", "name": "volume",
"displayName": "volume", "displayName": "Volume",
"displayNameEvent": "volume changed", "displayNameEvent": "volume changed",
"displayNameAction": "set volume", "displayNameAction": "set volume",
"type": "int", "type": "int",