diff --git a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp index 778d5611..0d210c00 100644 --- a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp +++ b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp @@ -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 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 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 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 tvList) @@ -336,6 +408,7 @@ void DevicePluginLgSmartTv::discoveryDone(QList 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(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()); +} + diff --git a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h index 1fcc4fb4..2a95de83 100644 --- a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h +++ b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h @@ -55,6 +55,7 @@ private slots: void discoveryDone(QList tvList); void pairingFinished(const bool &success); void sendingCommandFinished(const bool &success, const ActionId &actionId); + void statusChanged(); public slots: diff --git a/plugins/deviceplugins/lgsmarttv/lgsmarttv.pro b/plugins/deviceplugins/lgsmarttv/lgsmarttv.pro index b7cae59c..f52adbda 100644 --- a/plugins/deviceplugins/lgsmarttv/lgsmarttv.pro +++ b/plugins/deviceplugins/lgsmarttv/lgsmarttv.pro @@ -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 diff --git a/plugins/deviceplugins/lgsmarttv/tvdevice.cpp b/plugins/deviceplugins/lgsmarttv/tvdevice.cpp index 67379f9d..5699b51a 100644 --- a/plugins/deviceplugins/lgsmarttv/tvdevice.cpp +++ b/plugins/deviceplugins/lgsmarttv/tvdevice.cpp @@ -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 . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #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 = "byebye8080"; + + 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("HandleKeyInput"); @@ -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 = "byebye8080"; + 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(); +} + diff --git a/plugins/deviceplugins/lgsmarttv/tvdevice.h b/plugins/deviceplugins/lgsmarttv/tvdevice.h index c6907e38..84c85862 100644 --- a/plugins/deviceplugins/lgsmarttv/tvdevice.h +++ b/plugins/deviceplugins/lgsmarttv/tvdevice.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 . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef TVDEVICE_H #define TVDEVICE_H @@ -9,10 +27,12 @@ #include #include #include +#include #include #include #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: diff --git a/plugins/deviceplugins/lgsmarttv/tvdiscovery.cpp b/plugins/deviceplugins/lgsmarttv/tvdiscovery.cpp index a7c77206..e435517f 100644 --- a/plugins/deviceplugins/lgsmarttv/tvdiscovery.cpp +++ b/plugins/deviceplugins/lgsmarttv/tvdiscovery.cpp @@ -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 . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #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" diff --git a/plugins/deviceplugins/lgsmarttv/tvdiscovery.h b/plugins/deviceplugins/lgsmarttv/tvdiscovery.h index aff2a56c..bd35b76c 100644 --- a/plugins/deviceplugins/lgsmarttv/tvdiscovery.h +++ b/plugins/deviceplugins/lgsmarttv/tvdiscovery.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 . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef TVDISCOVERY_H #define TVDISCOVERY_H diff --git a/plugins/deviceplugins/lgsmarttv/tveventhandler.cpp b/plugins/deviceplugins/lgsmarttv/tveventhandler.cpp new file mode 100644 index 00000000..990b6ba2 --- /dev/null +++ b/plugins/deviceplugins/lgsmarttv/tveventhandler.cpp @@ -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 . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#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("deleteLater(); +} + +void TvEventHandler::enable() +{ + m_disabled = false; +} + +void TvEventHandler::disable() +{ + m_disabled = true; +} diff --git a/plugins/deviceplugins/lgsmarttv/tveventhandler.h b/plugins/deviceplugins/lgsmarttv/tveventhandler.h new file mode 100644 index 00000000..05ab953c --- /dev/null +++ b/plugins/deviceplugins/lgsmarttv/tveventhandler.h @@ -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 . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef TVEVENTHANDLER_H +#define TVEVENTHANDLER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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