added states and event handling from tv
This commit is contained in:
parent
07ac559665
commit
202def72a7
@ -27,6 +27,16 @@ VendorId lgVendorId = VendorId("a9af9673-78db-4226-a16b-f34b304f7041");
|
||||
DeviceClassId lgSmartTvDeviceClassId = DeviceClassId("1d41b5a8-74ff-4a12-b365-c7bbe610848f");
|
||||
|
||||
StateTypeId tvReachableStateTypeId = StateTypeId("b056c36b-df87-4177-8d5d-1e7c1e8cdc7a");
|
||||
StateTypeId tv3DModeStateTypeId = StateTypeId("8ad3d77f-d340-495d-8c2a-5569a80e9d36");
|
||||
StateTypeId tvVolumeLevelStateTypeId = StateTypeId("07d39a6e-7eab-42d0-851d-9f3bcd3bbb57");
|
||||
StateTypeId tvMuteStateTypeId = StateTypeId("a6ac9061-3de7-403a-a646-790ca5d73764");
|
||||
StateTypeId tvChannelTypeStateTypeId = StateTypeId("84c86670-77c7-4fc6-9e23-abca066e76aa");
|
||||
StateTypeId tvChannelNameStateTypeId = StateTypeId("265dc5f7-3f4d-4002-a6fe-2a53986bcf1d");
|
||||
StateTypeId tvChannelNumberStateTypeId = StateTypeId("881629a3-4ce2-42ba-8ce6-10d90c383799");
|
||||
StateTypeId tvProgramNameStateTypeId = StateTypeId("3f53e52e-1ad7-40e7-8080-76908e720cac");
|
||||
StateTypeId tvInputSourceIndexStateTypeId = StateTypeId("e895017a-139f-410c-bfb2-4d008104e164");
|
||||
StateTypeId tvInputSourceLabelNameStateTypeId = StateTypeId("58b734ec-2269-4c57-99e1-e1eeee401053");
|
||||
|
||||
|
||||
ActionTypeId commandVolumeUpActionTypeId = ActionTypeId("ac5d7dcd-dfe8-4a94-9ab9-21b3f804b39e");
|
||||
ActionTypeId commandVolumeDownActionTypeId = ActionTypeId("62b17bec-f461-4ffa-93d1-67a9430d55e1");
|
||||
@ -80,6 +90,7 @@ QList<DeviceClass> DevicePluginLgSmartTv::supportedDevices() const
|
||||
paramTypes.append(ParamType("uuid", QVariant::String));
|
||||
paramTypes.append(ParamType("model", QVariant::String));
|
||||
paramTypes.append(ParamType("host address", QVariant::String));
|
||||
paramTypes.append(ParamType("port", QVariant::Int));
|
||||
paramTypes.append(ParamType("location", QVariant::String));
|
||||
paramTypes.append(ParamType("manufacturer", QVariant::String));
|
||||
paramTypes.append(ParamType("key", QVariant::String));
|
||||
@ -95,6 +106,60 @@ QList<DeviceClass> DevicePluginLgSmartTv::supportedDevices() const
|
||||
reachableState.setDefaultValue(false);
|
||||
tvStates.append(reachableState);
|
||||
|
||||
StateType tv3DModeState(tv3DModeStateTypeId);
|
||||
tv3DModeState.setName("3D Mode");
|
||||
tv3DModeState.setType(QVariant::Bool);
|
||||
tv3DModeState.setDefaultValue(false);
|
||||
tvStates.append(tv3DModeState);
|
||||
|
||||
StateType tvVolumeLevelState(tvVolumeLevelStateTypeId);
|
||||
tvVolumeLevelState.setName("volume level");
|
||||
tvVolumeLevelState.setType(QVariant::Int);
|
||||
tvVolumeLevelState.setDefaultValue(-1);
|
||||
tvStates.append(tvVolumeLevelState);
|
||||
|
||||
StateType tvMuteState(tvMuteStateTypeId);
|
||||
tvMuteState.setName("mute");
|
||||
tvMuteState.setType(QVariant::Bool);
|
||||
tvMuteState.setDefaultValue(false);
|
||||
tvStates.append(tvMuteState);
|
||||
|
||||
StateType tvChannelTypeState(tvChannelTypeStateTypeId);
|
||||
tvChannelTypeState.setName("channel type");
|
||||
tvChannelTypeState.setType(QVariant::String);
|
||||
tvChannelTypeState.setDefaultValue("");
|
||||
tvStates.append(tvChannelTypeState);
|
||||
|
||||
StateType tvChannelNameState(tvChannelNameStateTypeId);
|
||||
tvChannelNameState.setName("channel name");
|
||||
tvChannelNameState.setType(QVariant::String);
|
||||
tvChannelNameState.setDefaultValue("");
|
||||
tvStates.append(tvChannelNameState);
|
||||
|
||||
StateType tvChannelNumberState(tvChannelNumberStateTypeId);
|
||||
tvChannelNumberState.setName("channel number");
|
||||
tvChannelNumberState.setType(QVariant::Int);
|
||||
tvChannelNumberState.setDefaultValue(-1);
|
||||
tvStates.append(tvChannelNumberState);
|
||||
|
||||
StateType tvProgramNameState(tvProgramNameStateTypeId);
|
||||
tvProgramNameState.setName("program name");
|
||||
tvProgramNameState.setType(QVariant::String);
|
||||
tvProgramNameState.setDefaultValue("");
|
||||
tvStates.append(tvProgramNameState);
|
||||
|
||||
StateType tvInputSourceIndexState(tvInputSourceIndexStateTypeId);
|
||||
tvInputSourceIndexState.setName("input source index");
|
||||
tvInputSourceIndexState.setType(QVariant::Int);
|
||||
tvInputSourceIndexState.setDefaultValue(-1);
|
||||
tvStates.append(tvInputSourceIndexState);
|
||||
|
||||
StateType tvInputSourceLabelNameState(tvInputSourceLabelNameStateTypeId);
|
||||
tvInputSourceLabelNameState.setName("input source label");
|
||||
tvInputSourceLabelNameState.setType(QVariant::String);
|
||||
tvInputSourceLabelNameState.setDefaultValue("");
|
||||
tvStates.append(tvInputSourceLabelNameState);
|
||||
|
||||
deviceClassLgSmartTv.setStateTypes(tvStates);
|
||||
|
||||
// Actions
|
||||
@ -201,12 +266,16 @@ QPair<DeviceManager::DeviceSetupStatus, QString> DevicePluginLgSmartTv::setupDev
|
||||
tvDevice->setUuid(device->paramValue("uuid").toString());
|
||||
tvDevice->setModelName(device->paramValue("model").toString());
|
||||
tvDevice->setHostAddress(QHostAddress(device->paramValue("host address").toString()));
|
||||
tvDevice->setPort(device->paramValue("port").toInt());
|
||||
tvDevice->setLocation(QUrl(device->paramValue("location").toString()));
|
||||
tvDevice->setUuid(device->paramValue("manufacturer").toString());
|
||||
// key if there is one...
|
||||
|
||||
tvDevice->setupEventHandler();
|
||||
|
||||
connect(tvDevice, &TvDevice::pairingFinished, this, &DevicePluginLgSmartTv::pairingFinished);
|
||||
connect(tvDevice, &TvDevice::sendCommandFinished, this, &DevicePluginLgSmartTv::sendingCommandFinished);
|
||||
connect(tvDevice, &TvDevice::statusChanged, this, &DevicePluginLgSmartTv::statusChanged);
|
||||
|
||||
tvDevice->requestPairing();
|
||||
m_tvList.insert(tvDevice,device);
|
||||
@ -308,6 +377,7 @@ void DevicePluginLgSmartTv::deviceRemoved(Device *device)
|
||||
TvDevice *tvDevice= m_tvList.key(device);
|
||||
qDebug() << "remove LG Smart Tv " << tvDevice->modelName();
|
||||
m_tvList.remove(tvDevice);
|
||||
tvDevice->deleteLater();
|
||||
}
|
||||
|
||||
QString DevicePluginLgSmartTv::pluginName() const
|
||||
@ -322,7 +392,9 @@ PluginId DevicePluginLgSmartTv::pluginId() const
|
||||
|
||||
void DevicePluginLgSmartTv::guhTimer()
|
||||
{
|
||||
|
||||
foreach (TvDevice *tvDevice, m_tvList.keys()) {
|
||||
tvDevice->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginLgSmartTv::discoveryDone(QList<TvDevice*> tvList)
|
||||
@ -336,6 +408,7 @@ void DevicePluginLgSmartTv::discoveryDone(QList<TvDevice*> tvList)
|
||||
params.append(Param("model", device->modelName()));
|
||||
params.append(Param("host address", device->hostAddress().toString()));
|
||||
params.append(Param("location", device->location().toString()));
|
||||
params.append(Param("port", device->port()));
|
||||
params.append(Param("manufacturer", device->manufacturer()));
|
||||
params.append(Param("key", device->key()));
|
||||
descriptor.setParams(params);
|
||||
@ -351,6 +424,7 @@ void DevicePluginLgSmartTv::pairingFinished(const bool &success)
|
||||
|
||||
if(success){
|
||||
emit deviceSetupFinished(device,DeviceManager::DeviceSetupStatusSuccess,QString(""));
|
||||
tvDevice->refresh();
|
||||
}else{
|
||||
emit deviceSetupFinished(device,DeviceManager::DeviceSetupStatusFailure,QString("Could not pair with tv."));
|
||||
}
|
||||
@ -365,4 +439,21 @@ void DevicePluginLgSmartTv::sendingCommandFinished(const bool &success, const Ac
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginLgSmartTv::statusChanged()
|
||||
{
|
||||
TvDevice *tvDevice = static_cast<TvDevice*>(sender());
|
||||
Device *device = m_tvList.value(tvDevice);
|
||||
|
||||
device->setStateValue(tvReachableStateTypeId, tvDevice->reachable());
|
||||
device->setStateValue(tv3DModeStateTypeId, tvDevice->is3DMode());
|
||||
device->setStateValue(tvVolumeLevelStateTypeId, tvDevice->volumeLevel());
|
||||
device->setStateValue(tvMuteStateTypeId, tvDevice->mute());
|
||||
device->setStateValue(tvChannelTypeStateTypeId, tvDevice->channelType());
|
||||
device->setStateValue(tvChannelNameStateTypeId, tvDevice->channelName());
|
||||
device->setStateValue(tvChannelNumberStateTypeId, tvDevice->channelNumber());
|
||||
device->setStateValue(tvProgramNameStateTypeId, tvDevice->programName());
|
||||
device->setStateValue(tvInputSourceIndexStateTypeId, tvDevice->inputSourceIndex());
|
||||
device->setStateValue(tvInputSourceLabelNameStateTypeId, tvDevice->inputSourceLabelName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -55,6 +55,7 @@ private slots:
|
||||
void discoveryDone(QList<TvDevice *> tvList);
|
||||
void pairingFinished(const bool &success);
|
||||
void sendingCommandFinished(const bool &success, const ActionId &actionId);
|
||||
void statusChanged();
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
@ -2,16 +2,18 @@ include(../../plugins.pri)
|
||||
|
||||
TARGET = $$qtLibraryTarget(guh_devicepluginlgsmarttv)
|
||||
|
||||
QT+= network
|
||||
QT+= network xml
|
||||
|
||||
SOURCES += \
|
||||
devicepluginlgsmarttv.cpp \
|
||||
tvdiscovery.cpp \
|
||||
tvdevice.cpp
|
||||
tvdevice.cpp \
|
||||
tveventhandler.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginlgsmarttv.h \
|
||||
tvdiscovery.h \
|
||||
tvdevice.h
|
||||
tvdevice.h \
|
||||
tveventhandler.h
|
||||
|
||||
|
||||
|
||||
@ -1,3 +1,21 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "tvdevice.h"
|
||||
|
||||
TvDevice::TvDevice(QObject *parent) :
|
||||
@ -5,7 +23,9 @@ TvDevice::TvDevice(QObject *parent) :
|
||||
{
|
||||
m_manager = new QNetworkAccessManager(this);
|
||||
|
||||
// TODO: make dynamic...displayPin setup
|
||||
m_key = "539887";
|
||||
|
||||
m_pairingStatus = false;
|
||||
m_reachable = false;
|
||||
|
||||
@ -32,6 +52,16 @@ QHostAddress TvDevice::hostAddress() const
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
void TvDevice::setPort(const int &port)
|
||||
{
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
int TvDevice::port() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
void TvDevice::setName(const QString &name)
|
||||
{
|
||||
m_name = name;
|
||||
@ -102,12 +132,54 @@ bool TvDevice::paired() const
|
||||
return m_pairingStatus;
|
||||
}
|
||||
|
||||
bool TvDevice::is3DMode() const
|
||||
{
|
||||
return m_is3DMode;
|
||||
}
|
||||
|
||||
int TvDevice::volumeLevel() const
|
||||
{
|
||||
return m_volumeLevel;
|
||||
}
|
||||
|
||||
bool TvDevice::mute() const
|
||||
{
|
||||
return m_mute;
|
||||
}
|
||||
|
||||
QString TvDevice::channelType() const
|
||||
{
|
||||
return m_channelType;
|
||||
}
|
||||
|
||||
QString TvDevice::channelName() const
|
||||
{
|
||||
return m_channelName;
|
||||
}
|
||||
|
||||
int TvDevice::channelNumber() const
|
||||
{
|
||||
return m_channelNumber;
|
||||
}
|
||||
|
||||
QString TvDevice::programName() const
|
||||
{
|
||||
return m_programName;
|
||||
}
|
||||
|
||||
int TvDevice::inputSourceIndex() const
|
||||
{
|
||||
return m_inputSourceIndex;
|
||||
}
|
||||
|
||||
QString TvDevice::inputSourceLabelName() const
|
||||
{
|
||||
return m_inputSourceLabel;
|
||||
}
|
||||
|
||||
void TvDevice::showPairingKey()
|
||||
{
|
||||
qDebug() << "request show pairing key on screen...";
|
||||
qDebug() << "--------------------------------------------";
|
||||
|
||||
QString urlString = "http://" + m_hostAddress.toString() + ":8080/udap/api/pairing";
|
||||
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/pairing";
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
@ -125,7 +197,7 @@ void TvDevice::requestPairing()
|
||||
emit pairingFinished(false);
|
||||
}
|
||||
|
||||
QString urlString = "http://" + m_hostAddress.toString() +":8080/udap/api/pairing";
|
||||
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/pairing";
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
@ -137,6 +209,22 @@ void TvDevice::requestPairing()
|
||||
m_requestPairingReplay = m_manager->post(request,data);
|
||||
}
|
||||
|
||||
void TvDevice::endPairing()
|
||||
{
|
||||
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/pairing";
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0 guh"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>byebye</name><port>8080</port></api></envelope>";
|
||||
|
||||
m_finishingPairingReplay = m_manager->post(request,data);
|
||||
}
|
||||
|
||||
|
||||
void TvDevice::sendCommand(TvDevice::RemoteKey key, ActionId actionId)
|
||||
{
|
||||
m_actionId = actionId;
|
||||
@ -146,7 +234,7 @@ void TvDevice::sendCommand(TvDevice::RemoteKey key, ActionId actionId)
|
||||
return;
|
||||
}
|
||||
|
||||
QString urlString = "http://" + m_hostAddress.toString() +":8080/udap/api/command";
|
||||
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/command";
|
||||
|
||||
QByteArray data;
|
||||
data.append("<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"command\"><name>HandleKeyInput</name><value>");
|
||||
@ -161,18 +249,113 @@ void TvDevice::sendCommand(TvDevice::RemoteKey key, ActionId actionId)
|
||||
m_sendCommandReplay = m_manager->post(request,data);
|
||||
}
|
||||
|
||||
void TvDevice::finishingPairing()
|
||||
void TvDevice::setupEventHandler()
|
||||
{
|
||||
QString urlString = "http://" + m_hostAddress.toString() +":8080/udap/api/pairing";
|
||||
//qDebug() << "set up event handler " << m_hostAddress.toString() << m_port;
|
||||
m_eventHandler = new TvEventHandler(this,m_hostAddress,m_port);
|
||||
connect(m_eventHandler, &TvEventHandler::eventOccured, this, &TvDevice::eventOccured);
|
||||
}
|
||||
|
||||
void TvDevice::refresh()
|
||||
{
|
||||
if(paired()){
|
||||
queryChannelInformation();
|
||||
queryVolumeInformation();
|
||||
}
|
||||
}
|
||||
|
||||
void TvDevice::queryVolumeInformation()
|
||||
{
|
||||
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/data?target=volume_info";
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0 guh"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>byebye</name><port>8080</port></api></envelope>";
|
||||
m_queryVolumeInformationReplay = m_manager->get(request);
|
||||
}
|
||||
|
||||
m_finishingPairingReplay = m_manager->post(request,data);
|
||||
void TvDevice::queryChannelInformation()
|
||||
{
|
||||
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/data?target=cur_channel";
|
||||
|
||||
QNetworkRequest deviceRequest;
|
||||
deviceRequest.setUrl(QUrl(urlString));
|
||||
deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml"));
|
||||
deviceRequest.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
|
||||
deviceRequest.setRawHeader("Connection", "Close");
|
||||
|
||||
m_queryChannelInformationReplay = m_manager->get(deviceRequest);
|
||||
}
|
||||
|
||||
void TvDevice::parseVolumeInformation(const QByteArray &data)
|
||||
{
|
||||
//qDebug() << printXmlData(data);
|
||||
QXmlStreamReader xml(data);
|
||||
|
||||
while(!xml.atEnd() && !xml.hasError()){
|
||||
xml.readNext();
|
||||
|
||||
if(xml.name() == "mute"){
|
||||
m_mute = QVariant(xml.readElementText()).toBool();
|
||||
}
|
||||
if(xml.name() == "level"){
|
||||
m_volumeLevel = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
}
|
||||
emit statusChanged();
|
||||
}
|
||||
|
||||
void TvDevice::parseChannelInformation(const QByteArray &data)
|
||||
{
|
||||
//qDebug() << printXmlData(data);
|
||||
QXmlStreamReader xml(data);
|
||||
|
||||
while(!xml.atEnd() && !xml.hasError()){
|
||||
xml.readNext();
|
||||
|
||||
if(xml.name() == "chtype"){
|
||||
m_channelType = xml.readElementText();
|
||||
}
|
||||
if(xml.name() == "major"){
|
||||
m_channelNumber = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
if(xml.name() == "chname"){
|
||||
m_channelName = xml.readElementText();
|
||||
}
|
||||
if(xml.name() == "progName"){
|
||||
m_programName = xml.readElementText();
|
||||
}
|
||||
if(xml.name() == "inputSourceIdx"){
|
||||
m_inputSourceIndex = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
if(xml.name() == "labelName"){
|
||||
m_inputSourceLabel = xml.readElementText();
|
||||
}
|
||||
}
|
||||
emit statusChanged();
|
||||
}
|
||||
|
||||
QString TvDevice::printXmlData(QByteArray data)
|
||||
{
|
||||
QString xmlOut;
|
||||
QXmlStreamReader reader(data);
|
||||
QXmlStreamWriter writer(&xmlOut);
|
||||
writer.setAutoFormatting(true);
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
if (!reader.isWhitespace()) {
|
||||
writer.writeCurrentToken(reader);
|
||||
}
|
||||
}
|
||||
if(reader.hasError()){
|
||||
qDebug() << "ERROR reading XML device information: " << reader.errorString();
|
||||
qDebug() << "--------------------------------------------";
|
||||
}
|
||||
return xmlOut;
|
||||
}
|
||||
|
||||
void TvDevice::replyFinished(QNetworkReply *reply)
|
||||
@ -189,6 +372,7 @@ void TvDevice::replyFinished(QNetworkReply *reply)
|
||||
if(status != 200){
|
||||
qWarning() << "ERROR: could not request to show pairing key on screen " << status;
|
||||
}
|
||||
m_showKeyReplay->deleteLater();
|
||||
}
|
||||
if(reply == m_requestPairingReplay){
|
||||
if(status != 200){
|
||||
@ -198,7 +382,9 @@ void TvDevice::replyFinished(QNetworkReply *reply)
|
||||
}else{
|
||||
m_pairingStatus = true;
|
||||
qDebug() << "successfully paired with tv " << m_modelName;
|
||||
emit pairingFinished(true); }
|
||||
emit pairingFinished(true);
|
||||
}
|
||||
m_requestPairingReplay->deleteLater();
|
||||
}
|
||||
|
||||
if(reply == m_finishingPairingReplay){
|
||||
@ -206,6 +392,7 @@ void TvDevice::replyFinished(QNetworkReply *reply)
|
||||
m_pairingStatus = false;
|
||||
qDebug() << "successfully unpaired from tv " << m_modelName;
|
||||
}
|
||||
m_finishingPairingReplay->deleteLater();
|
||||
}
|
||||
|
||||
if(reply == m_sendCommandReplay){
|
||||
@ -216,7 +403,59 @@ void TvDevice::replyFinished(QNetworkReply *reply)
|
||||
m_pairingStatus = true;
|
||||
qDebug() << "successfully sent command to tv " << m_modelName;
|
||||
emit sendCommandFinished(true,m_actionId);
|
||||
refresh();
|
||||
}
|
||||
m_sendCommandReplay->deleteLater();
|
||||
}
|
||||
if(reply == m_queryVolumeInformationReplay){
|
||||
parseVolumeInformation(reply->readAll());
|
||||
m_queryVolumeInformationReplay->deleteLater();
|
||||
}
|
||||
if(reply == m_queryChannelInformationReplay){
|
||||
parseChannelInformation(reply->readAll());
|
||||
m_queryChannelInformationReplay->deleteLater();
|
||||
}
|
||||
|
||||
emit statusChanged();
|
||||
}
|
||||
|
||||
void TvDevice::eventOccured(const QByteArray &data)
|
||||
{
|
||||
// if we got a channel changed event...
|
||||
if(data.contains("ChannelChanged")){
|
||||
parseChannelInformation(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// qDebug() << "---------------------------------";
|
||||
// qDebug() << printXmlData(data);
|
||||
|
||||
// if the tv suspends, it will send a byebye message, which means
|
||||
// the pairing will be closed.
|
||||
if(data.contains("api type=\"pairing\"") && data.contains("byebye")){
|
||||
qDebug() << "--> tv ended pairing";
|
||||
m_pairingStatus = false;
|
||||
m_reachable = false;
|
||||
emit statusChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
// check if this is a 3DMode changed event
|
||||
QXmlStreamReader xml(data);
|
||||
|
||||
while(!xml.atEnd() && !xml.hasError()){
|
||||
xml.readNext();
|
||||
|
||||
if(xml.name() == "name"){
|
||||
if(xml.readElementText() == "3DMode"){
|
||||
xml.readNext();
|
||||
if(xml.name() == "value"){
|
||||
m_is3DMode = QVariant(xml.readElementText()).toBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit statusChanged();
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,21 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TVDEVICE_H
|
||||
#define TVDEVICE_H
|
||||
|
||||
@ -9,10 +27,12 @@
|
||||
#include <QNetworkRequest>
|
||||
#include <QUrl>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QXmlStreamAttributes>
|
||||
|
||||
#include "plugin/deviceplugin.h"
|
||||
#include "tveventhandler.h"
|
||||
|
||||
class TvDevice : public QObject
|
||||
{
|
||||
@ -89,12 +109,16 @@ public:
|
||||
MyApps = 417
|
||||
};
|
||||
|
||||
// propertys
|
||||
void setLocation(const QUrl &location);
|
||||
QUrl location() const;
|
||||
|
||||
void setHostAddress(const QHostAddress &hostAddress);
|
||||
QHostAddress hostAddress() const;
|
||||
|
||||
void setPort(const int &port);
|
||||
int port() const;
|
||||
|
||||
void setName(const QString &name);
|
||||
QString name() const;
|
||||
|
||||
@ -113,16 +137,32 @@ public:
|
||||
void setKey(const QString &key);
|
||||
QString key() const;
|
||||
|
||||
bool reachable() const;
|
||||
bool paired() const;
|
||||
|
||||
// States
|
||||
bool reachable() const;
|
||||
bool is3DMode() const;
|
||||
int volumeLevel() const;
|
||||
bool mute() const;
|
||||
QString channelType() const;
|
||||
QString channelName() const;
|
||||
int channelNumber() const;
|
||||
QString programName() const;
|
||||
int inputSourceIndex() const;
|
||||
QString inputSourceLabelName() const;
|
||||
|
||||
// public actions
|
||||
void showPairingKey();
|
||||
void requestPairing();
|
||||
void endPairing();
|
||||
void sendCommand(TvDevice::RemoteKey key, ActionId actionId);
|
||||
void setupEventHandler();
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
QUrl m_location;
|
||||
QHostAddress m_hostAddress;
|
||||
int m_port;
|
||||
QString m_name;
|
||||
QString m_modelName;
|
||||
QString m_manufacturer;
|
||||
@ -130,7 +170,18 @@ private:
|
||||
QString m_uuid;
|
||||
QString m_key;
|
||||
bool m_pairingStatus;
|
||||
|
||||
// States
|
||||
bool m_is3DMode;
|
||||
bool m_reachable;
|
||||
int m_volumeLevel;
|
||||
bool m_mute;
|
||||
QString m_channelType;
|
||||
QString m_channelName;
|
||||
int m_channelNumber;
|
||||
QString m_programName;
|
||||
int m_inputSourceIndex;
|
||||
QString m_inputSourceLabel;
|
||||
|
||||
ActionId m_actionId;
|
||||
|
||||
@ -139,8 +190,16 @@ private:
|
||||
QNetworkReply *m_requestPairingReplay;
|
||||
QNetworkReply *m_finishingPairingReplay;
|
||||
QNetworkReply *m_sendCommandReplay;
|
||||
QNetworkReply *m_queryVolumeInformationReplay;
|
||||
QNetworkReply *m_queryChannelInformationReplay;
|
||||
|
||||
void finishingPairing();
|
||||
TvEventHandler *m_eventHandler;
|
||||
|
||||
QString printXmlData(QByteArray data);
|
||||
void queryVolumeInformation();
|
||||
void queryChannelInformation();
|
||||
void parseVolumeInformation(const QByteArray &data);
|
||||
void parseChannelInformation(const QByteArray &data);
|
||||
|
||||
signals:
|
||||
void pairingFinished(const bool &success);
|
||||
@ -149,7 +208,7 @@ signals:
|
||||
|
||||
private slots:
|
||||
void replyFinished(QNetworkReply *reply);
|
||||
|
||||
void eventOccured(const QByteArray &data);
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
@ -1,3 +1,21 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "tvdiscovery.h"
|
||||
|
||||
TvDiscovery::TvDiscovery(QObject *parent) :
|
||||
@ -124,11 +142,6 @@ void TvDiscovery::readData()
|
||||
device->setHostAddress(sender);
|
||||
device->setUuid(uuid);
|
||||
|
||||
// qDebug() << "--> UPnP searcher discovered a TV...";
|
||||
// qDebug() << "location: " << location.toString();
|
||||
// qDebug() << "ip: " << sender.toString();
|
||||
// qDebug() << "uuid: " << uuid;
|
||||
// qDebug() << "--------------------------------------------";
|
||||
m_tvList.append(device);
|
||||
requestDeviceInformation(device);
|
||||
}
|
||||
@ -196,6 +209,9 @@ void TvDiscovery::parseDeviceInformation(QByteArray data)
|
||||
QString modelName;
|
||||
QString deviceType;
|
||||
QString manufacturer;
|
||||
int port;
|
||||
|
||||
qDebug() << printXmlData(data);
|
||||
|
||||
while(!xml.atEnd() && !xml.hasError()){
|
||||
xml.readNext();
|
||||
@ -226,12 +242,17 @@ void TvDiscovery::parseDeviceInformation(QByteArray data)
|
||||
if(xml.name() == "uuid" && xml.isStartElement()){
|
||||
uuid = xml.readElementText();
|
||||
}
|
||||
//check if we have port part of message
|
||||
if(xml.name() == "port"){
|
||||
port = xml.readElementText().toInt();
|
||||
}
|
||||
|
||||
xml.readNext();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
foreach (TvDevice *device, m_tvList) {
|
||||
// find our device with this uuid
|
||||
if(device->uuid() == uuid){
|
||||
@ -239,6 +260,7 @@ void TvDiscovery::parseDeviceInformation(QByteArray data)
|
||||
device->setModelName(modelName);
|
||||
device->setDeviceType(deviceType);
|
||||
device->setManufacturer(manufacturer);
|
||||
device->setPort(port);
|
||||
|
||||
qDebug() << "--> fetched TV information...";
|
||||
qDebug() << "name: " << device->name();
|
||||
@ -246,6 +268,7 @@ void TvDiscovery::parseDeviceInformation(QByteArray data)
|
||||
qDebug() << "device type: " << device->deviceType();
|
||||
qDebug() << "manufacturer: " << device->manufacturer();
|
||||
qDebug() << "address: " << device->hostAddress().toString();
|
||||
qDebug() << "port: " << device->port();
|
||||
qDebug() << "location: " << device->location().toString();
|
||||
qDebug() << "uuid: " << device->uuid();
|
||||
qDebug() << "--------------------------------------------";
|
||||
@ -253,6 +276,7 @@ void TvDiscovery::parseDeviceInformation(QByteArray data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TvDiscovery::discover(int timeout)
|
||||
{
|
||||
QString searchMessage("M-SEARCH * HTTP/1.1\r\n"
|
||||
|
||||
@ -1,3 +1,21 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TVDISCOVERY_H
|
||||
#define TVDISCOVERY_H
|
||||
|
||||
|
||||
108
plugins/deviceplugins/lgsmarttv/tveventhandler.cpp
Normal file
108
plugins/deviceplugins/lgsmarttv/tveventhandler.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "tveventhandler.h"
|
||||
|
||||
TvEventHandler::TvEventHandler(QObject *parent, QHostAddress host, int port) :
|
||||
QTcpServer(parent),m_host(host),m_port(port)
|
||||
{
|
||||
listen(QHostAddress::AnyIPv4,m_port);
|
||||
m_disabled = false;
|
||||
m_expectingData = false;
|
||||
|
||||
//TODO: handle ip address change (dhcp) notification from the tv!
|
||||
}
|
||||
|
||||
void TvEventHandler::incomingConnection(qintptr socket)
|
||||
{
|
||||
if(m_disabled){
|
||||
return;
|
||||
}
|
||||
|
||||
QTcpSocket* tcpSocket = new QTcpSocket(this);
|
||||
connect(tcpSocket, &QTcpSocket::readyRead, this, &TvEventHandler::readClient);
|
||||
connect(tcpSocket, &QTcpSocket::disconnected, this, &TvEventHandler::discardClient);
|
||||
tcpSocket->setSocketDescriptor(socket);
|
||||
|
||||
//qDebug() << "incomming connection" << s->peerAddress().toString() << s->peerName();
|
||||
}
|
||||
|
||||
void TvEventHandler::readClient()
|
||||
{
|
||||
if(m_disabled){
|
||||
return;
|
||||
}
|
||||
|
||||
QTcpSocket* socket = (QTcpSocket*)sender();
|
||||
|
||||
// reject everything, except the tv
|
||||
if(socket->peerAddress() != m_host){
|
||||
qWarning() << "reject connection from " << socket->peerAddress().toString();
|
||||
socket->close();
|
||||
if (socket->state() == QTcpSocket::UnconnectedState) {
|
||||
delete socket;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// the tv sends first the header (POST /udap/api/.... HTTP/1.1)
|
||||
// in the scond package the tv sends the information (xml format)
|
||||
while(!socket->atEnd()){
|
||||
QByteArray data = socket->readAll();
|
||||
|
||||
// check if we got information
|
||||
if(data.startsWith("<?xml") && m_expectingData){
|
||||
m_expectingData = false;
|
||||
|
||||
// Answere with OK
|
||||
QTextStream textStream(socket);
|
||||
textStream.setAutoDetectUnicode(true);
|
||||
textStream << "HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: text/html; charset=\"utf-8\"\r\n"
|
||||
"User-Agent: UDAP/2.0 guh\r\n"
|
||||
<< "Date: " << QDateTime::currentDateTime().toString() << "\n";
|
||||
|
||||
emit eventOccured(data);
|
||||
}
|
||||
|
||||
// check if we got header
|
||||
if (data.startsWith("POST") && !m_expectingData) {
|
||||
m_expectingData = true;
|
||||
// QStringList tokens = QString(data).split(QRegExp("[ \r\n][ \r\n]*"));
|
||||
// qDebug() << "==================================";
|
||||
// qDebug() << "event occured" << "http://" << m_host.toString() << ":" << m_port << tokens[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TvEventHandler::discardClient()
|
||||
{
|
||||
QTcpSocket* socket = (QTcpSocket*)sender();
|
||||
socket->deleteLater();
|
||||
}
|
||||
|
||||
void TvEventHandler::enable()
|
||||
{
|
||||
m_disabled = false;
|
||||
}
|
||||
|
||||
void TvEventHandler::disable()
|
||||
{
|
||||
m_disabled = true;
|
||||
}
|
||||
62
plugins/deviceplugins/lgsmarttv/tveventhandler.h
Normal file
62
plugins/deviceplugins/lgsmarttv/tveventhandler.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef TVEVENTHANDLER_H
|
||||
#define TVEVENTHANDLER_H
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include <QTextStream>
|
||||
#include <QRegExp>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
class TvEventHandler : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TvEventHandler(QObject *parent = 0, QHostAddress host = QHostAddress(), int port = 8080);
|
||||
void incomingConnection(qintptr socket) override;
|
||||
|
||||
private:
|
||||
QHostAddress m_host;
|
||||
int m_port;
|
||||
bool m_disabled;
|
||||
|
||||
bool m_expectingData;
|
||||
|
||||
QNetworkAccessManager *m_manager;
|
||||
|
||||
signals:
|
||||
void eventOccured(const QByteArray &path);
|
||||
void byebyeEvent();
|
||||
|
||||
private slots:
|
||||
void readClient();
|
||||
void discardClient();
|
||||
|
||||
public slots:
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
};
|
||||
|
||||
#endif // TVEVENTHANDLER_H
|
||||
Reference in New Issue
Block a user