nymea/plugins/deviceplugins/denon/deviceplugindenon.cpp

274 lines
9.9 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.guru> *
* Copyright (C) 2016 Bernhard Trinnes <bernhard.trinnes@guh.guru> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page denon.html
\title Denon
\brief Plugin for Denon AV
\ingroup plugins
\ingroup guh-plugins
This plug-in supports the
\l {http://www.denon.de/de/product/hometheater/avreceivers/avrx1000}{Denon AV Amplifier AVR-X1000}
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/denon/deviceplugindenon.json
*/
#include "deviceplugindenon.h"
#include "plugininfo.h"
DevicePluginDenon::DevicePluginDenon()
{
}
DeviceManager::HardwareResources DevicePluginDenon::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer;
}
DeviceManager::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device)
{
qCDebug(dcDenon) << "Setup Denon device" << device->paramValue(ipParamTypeId).toString();
// Check if we already have a denon device
if (!myDevices().isEmpty()) {
qCWarning(dcDenon) << "Could not add denon device. Only one denon device allowed.";
return DeviceManager::DeviceSetupStatusFailure;
}
QHostAddress address(device->paramValue(ipParamTypeId).toString());
if (address.isNull()) {
qCWarning(dcDenon) << "Could not parse ip address" << device->paramValue(ipParamTypeId).toString();
return DeviceManager::DeviceSetupStatusFailure;
}
m_device = device;
m_denonConnection = new DenonConnection(address, 23, this);
connect(m_denonConnection.data(), &DenonConnection::connectionStatusChanged, this, &DevicePluginDenon::onConnectionChanged);
connect(m_denonConnection.data(), &DenonConnection::socketErrorOccured, this, &DevicePluginDenon::onSocketError);
connect(m_denonConnection.data(), &DenonConnection::dataReady, this, &DevicePluginDenon::onDataReceived);
m_asyncSetups.append(m_denonConnection);
m_denonConnection->connectDenon();
return DeviceManager::DeviceSetupStatusAsync;
}
void DevicePluginDenon::deviceRemoved(Device *device)
{
qCDebug(dcDenon) << "Delete " << device->name();
if (m_denonConnection.isNull()){
qCWarning(dcDenon) << "Invalid connection pointer" << device->id().toString();
return;
}
m_device.clear();
m_denonConnection->disconnectDenon();
m_denonConnection->deleteLater();
}
void DevicePluginDenon::guhTimer()
{
if (m_denonConnection.isNull())
return;
if (!m_denonConnection->connected()) {
m_denonConnection->connectDenon();
} else {
m_denonConnection->sendData("PW?\rSI?\rMV?\r");
}
}
DeviceManager::DeviceError DevicePluginDenon::executeAction(Device *device, const Action &action)
{
qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params();
if (device->deviceClassId() == AVRX1000DeviceClassId) {
// check connection state
if (m_denonConnection.isNull() || !m_denonConnection->connected())
return DeviceManager::DeviceErrorHardwareNotAvailable;
// check if the requested action is our "update" action ...
if (action.actionTypeId() == powerActionTypeId) {
// Print information that we are executing now the update action
qCDebug(dcDenon) << "set power action" << action.id();
qCDebug(dcDenon) << "power: " << action.param(powerStateParamTypeId).value().Bool;
if (action.param(powerStateParamTypeId).value().toBool() == true){
QByteArray cmd = "PWON\r";
qCDebug(dcDenon) << "Execute power: " << action.id() << cmd;
m_denonConnection->sendData(cmd);
} else {
QByteArray cmd = "PWSTANDBY\r";
qCDebug(dcDenon) << "Execute power: " << action.id() << cmd;
m_denonConnection->sendData(cmd);
}
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == volumeActionTypeId) {
QByteArray vol = action.param(volumeStateParamTypeId).value().toByteArray();
QByteArray cmd = "MV" + vol + "\r";
qCDebug(dcDenon) << "Execute volume" << action.id() << cmd;
m_denonConnection->sendData(cmd);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == channelActionTypeId) {
qCDebug(dcDenon) << "Execute update action" << action.id();
QByteArray channel = action.param(channelStateParamTypeId).value().toByteArray();
QByteArray cmd = "SI" + channel + "\r";
qCDebug(dcDenon) << "Change to channel:" << cmd;
m_denonConnection->sendData(cmd);
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
void DevicePluginDenon::onConnectionChanged()
{
if (!m_device)
return;
// if the device is connected
if (m_denonConnection->connected()) {
// and from the first setup
if (m_asyncSetups.contains(m_denonConnection)) {
m_asyncSetups.removeAll(m_denonConnection);
m_denonConnection->sendData("PW?\rSI?\rMV?\r");
emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusSuccess);
}
}
// Set connection status
m_device->setStateValue(connectedStateTypeId, m_denonConnection->connected());
}
void DevicePluginDenon::onDataReceived(const QByteArray &data)
{
qCDebug(dcDenon) << "Data received" << data;
// if there is no device, return
if (m_device.isNull())
return;
if (data.contains("MV") && !data.contains("MAX")){
int index = data.indexOf("MV");
int vol = data.mid(index+2, 2).toInt();
qCDebug(dcDenon) << "Update volume:" << vol;
m_device->setStateValue(volumeStateTypeId, vol);
}
if (data.contains("SI")) {
QString cmd = NULL;
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;
m_device->setStateValue(channelStateTypeId, cmd);
}
if (data.contains("PWON")) {
qCDebug(dcDenon) << "Update power on";
m_device->setStateValue(powerStateTypeId, true);
} else if (data.contains("PWSTANDBY")) {
qCDebug(dcDenon) << "Update power off";
m_device->setStateValue(powerStateTypeId, false);
}
}
void DevicePluginDenon::onSocketError()
{
// if there is no device, return
if (m_device.isNull())
return;
// Check if setup running for this device
if (m_asyncSetups.contains(m_denonConnection)) {
qCWarning(dcDenon()) << "Could not add device. The setup failed.";
emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusFailure);
// Delete the connection, the device will not be added and
// the connection will be created in the next setup
m_denonConnection->deleteLater();
}
}