From fafb54834f4161e2c57825cdca893861076d1ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 25 Jun 2015 19:57:25 +0200 Subject: [PATCH] finalized lg smartv plugin with display pin setupMethod --- .../lgsmarttv/devicepluginlgsmarttv.cpp | 375 +++++++++++------- .../lgsmarttv/devicepluginlgsmarttv.h | 42 +- .../lgsmarttv/devicepluginlgsmarttv.json | 15 +- plugins/deviceplugins/lgsmarttv/tvdevice.cpp | 285 ++++++------- plugins/deviceplugins/lgsmarttv/tvdevice.h | 93 ++--- .../lgsmarttv/tveventhandler.cpp | 47 +-- .../deviceplugins/lgsmarttv/tveventhandler.h | 13 +- 7 files changed, 459 insertions(+), 411 deletions(-) diff --git a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp index d0c3d401..3c8aafab 100644 --- a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp +++ b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.cpp @@ -91,9 +91,17 @@ DevicePluginLgSmartTv::DevicePluginLgSmartTv() { } +DeviceManager::HardwareResources DevicePluginLgSmartTv::requiredHardware() const +{ + return DeviceManager::HardwareResourceTimer | + DeviceManager::HardwareResourceUpnpDisovery | + DeviceManager::HardwareResourceNetworkManager; +} + DeviceManager::DeviceError DevicePluginLgSmartTv::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) { - Q_UNUSED(params); + Q_UNUSED(params) + if(deviceClassId != lgSmartTvDeviceClassId){ return DeviceManager::DeviceErrorDeviceClassNotFound; } @@ -103,26 +111,24 @@ DeviceManager::DeviceError DevicePluginLgSmartTv::discoverDevices(const DeviceCl DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::setupDevice(Device *device) { - UpnpDeviceDescriptor upnpDeviceDescriptor; - upnpDeviceDescriptor.setFriendlyName(device->paramValue("name").toString()); - upnpDeviceDescriptor.setUuid(device->paramValue("uuid").toString()); - upnpDeviceDescriptor.setModelName(device->paramValue("model").toString()); - upnpDeviceDescriptor.setHostAddress(QHostAddress(device->paramValue("host address").toString())); - upnpDeviceDescriptor.setPort(device->paramValue("port").toInt()); - upnpDeviceDescriptor.setLocation(QUrl(device->paramValue("location").toString())); + if (device->deviceClassId() != lgSmartTvDeviceClassId) { + return DeviceManager::DeviceSetupStatusFailure; + } - TvDevice *tvDevice = new TvDevice(this, upnpDeviceDescriptor); + TvDevice *tvDevice = new TvDevice(QHostAddress(device->paramValue("host address").toString()), + device->paramValue("port").toInt(), this); + tvDevice->setUuid(device->paramValue("uuid").toString()); - // check if the key wasn't loaded + // if the key is missing, this setup call comes from a pairing procedure if (device->paramValue("key") == QString()) { // check if we know the key from the pairing procedure if (!m_tvKeys.contains(device->paramValue("uuid").toString())) { - qWarning() << "could not find any pairing key"; + qCWarning(dcLgSmartTv) << "could not find any pairing key"; return DeviceManager::DeviceSetupStatusFailure; } // use the key from the pairing procedure - tvDevice->endPairing(); QString key = m_tvKeys.value(device->paramValue("uuid").toString()); + tvDevice->setKey(key); device->setParamValue("key", key); } else { @@ -132,73 +138,32 @@ DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::setupDevice(Device *devi } } - connect(tvDevice, &TvDevice::pairingFinished, this, &DevicePluginLgSmartTv::slotPairingFinished); - connect(tvDevice, &TvDevice::sendCommandFinished, this, &DevicePluginLgSmartTv::sendingCommandFinished); - connect(tvDevice, &TvDevice::statusChanged, this, &DevicePluginLgSmartTv::statusChanged); + connect(tvDevice, &TvDevice::stateChanged, this, &DevicePluginLgSmartTv::stateChanged); m_tvList.insert(tvDevice, device); - tvDevice->requestPairing(); + pairTvDevice(device, true); return DeviceManager::DeviceSetupStatusAsync; } -DeviceManager::HardwareResources DevicePluginLgSmartTv::requiredHardware() const +void DevicePluginLgSmartTv::deviceRemoved(Device *device) { - return DeviceManager::HardwareResourceTimer | - DeviceManager::HardwareResourceUpnpDisovery | - DeviceManager::HardwareResourceNetworkManager; -} - -DeviceManager::DeviceError DevicePluginLgSmartTv::executeAction(Device *device, const Action &action) -{ - TvDevice * tvDevice = m_tvList.key(device); - - if (action.actionTypeId() == commandVolumeUpActionTypeId) { - tvDevice->sendCommand(TvDevice::VolUp, action.id()); - } else if(action.actionTypeId() == commandVolumeDownActionTypeId) { - tvDevice->sendCommand(TvDevice::VolDown, action.id()); - } else if(action.actionTypeId() == commandMuteActionTypeId) { - tvDevice->sendCommand(TvDevice::Mute, action.id()); - } else if(action.actionTypeId() == commandChannelUpActionTypeId) { - tvDevice->sendCommand(TvDevice::ChannelUp, action.id()); - } else if(action.actionTypeId() == commandChannelDownActionTypeId) { - tvDevice->sendCommand(TvDevice::ChannelDown, action.id()); - } else if(action.actionTypeId() == commandPowerOffActionTypeId) { - tvDevice->sendCommand(TvDevice::Power, action.id()); - } else if(action.actionTypeId() == commandArrowUpActionTypeId) { - tvDevice->sendCommand(TvDevice::Up, action.id()); - } else if(action.actionTypeId() == commandArrowDownActionTypeId) { - tvDevice->sendCommand(TvDevice::Down, action.id()); - } else if(action.actionTypeId() == commandArrowLeftActionTypeId) { - tvDevice->sendCommand(TvDevice::Left, action.id()); - } else if(action.actionTypeId() == commandArrowRightActionTypeId) { - tvDevice->sendCommand(TvDevice::Right, action.id()); - } else if(action.actionTypeId() == commandOkActionTypeId) { - tvDevice->sendCommand(TvDevice::Ok, action.id()); - } else if(action.actionTypeId() == commandBackActionTypeId) { - tvDevice->sendCommand(TvDevice::Back, action.id()); - } else if(action.actionTypeId() == commandHomeActionTypeId) { - tvDevice->sendCommand(TvDevice::Home, action.id()); - } else if(action.actionTypeId() == commandInputSourceActionTypeId) { - tvDevice->sendCommand(TvDevice::ExternalInput, action.id()); - } else if(action.actionTypeId() == commandExitActionTypeId) { - tvDevice->sendCommand(TvDevice::Exit, action.id()); - } else if(action.actionTypeId() == commandInfoActionTypeId) { - tvDevice->sendCommand(TvDevice::Info, action.id()); - } else if(action.actionTypeId() == commandMyAppsActionTypeId) { - tvDevice->sendCommand(TvDevice::MyApps, action.id()); - } else if(action.actionTypeId() == commandProgramListActionTypeId) { - tvDevice->sendCommand(TvDevice::ProgramList, action.id()); - } else { - return DeviceManager::DeviceErrorActionTypeNotFound; + if (!m_tvList.values().contains(device)) { + return; } - return DeviceManager::DeviceErrorAsync; + + TvDevice *tvDevice= m_tvList.key(device); + qCDebug(dcLgSmartTv) << "remove device" << device->paramValue("name").toString(); + unpairTvDevice(device); + m_tvList.remove(tvDevice); + delete tvDevice; } void DevicePluginLgSmartTv::upnpDiscoveryFinished(const QList &upnpDeviceDescriptorList) { QList deviceDescriptors; foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, upnpDeviceDescriptorList) { + qCDebug(dcLgSmartTv) << upnpDeviceDescriptor; DeviceDescriptor descriptor(lgSmartTvDeviceClassId, "Lg Smart Tv", upnpDeviceDescriptor.modelName()); ParamList params; params.append(Param("name", upnpDeviceDescriptor.friendlyName())); @@ -213,32 +178,103 @@ void DevicePluginLgSmartTv::upnpDiscoveryFinished(const QListsetupEventHandler(); + if (!tvDevice->reachable()) { + qCWarning(dcLgSmartTv) << "not reachable"; + return DeviceManager::DeviceErrorHardwareNotAvailable; + } + + if (action.actionTypeId() == commandVolumeUpActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::VolUp); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandVolumeDownActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::VolDown); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandMuteActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Mute); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandChannelUpActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ChannelUp); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandChannelDownActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ChannelDown); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandPowerOffActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Power); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandArrowUpActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Up); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandArrowDownActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Down); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandArrowLeftActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Left); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandArrowRightActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Right); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandOkActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Ok); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandBackActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Back); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandHomeActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Home); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandInputSourceActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ExternalInput); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandExitActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Exit); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandInfoActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Info); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandMyAppsActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::MyApps); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == commandProgramListActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ProgramList); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_asyncActions.insert(reply, action.id()); + } else { + return DeviceManager::DeviceErrorActionTypeNotFound; + } + return DeviceManager::DeviceErrorAsync; } DeviceManager::DeviceError DevicePluginLgSmartTv::displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) { Q_UNUSED(pairingTransactionId) - QString urlString = "http://" + deviceDescriptor.params().paramValue("host address").toString() + ":" + deviceDescriptor.params().paramValue("port").toString() + "/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")); - - QByteArray data = " showKey"; - - m_showPinReply = networkManagerPost(request, data); + QHostAddress host = QHostAddress(deviceDescriptor.params().paramValue("host address").toString()); + int port = deviceDescriptor.params().paramValue("port").toInt(); + QPair request = TvDevice::createDisplayKeyRequest(host, port); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_showPinReply.append(reply); return DeviceManager::DeviceErrorNoError; } @@ -246,18 +282,12 @@ DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::confirmPairing(const Pai { Q_UNUSED(deviceClassId) - QString urlString = "http://" + params.paramValue("host address").toString() + ":" + params.paramValue("port").toString() + "/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")); - - QByteArray data = "hello" + secret.toUtf8() + "8080"; - - QNetworkReply *pairingReply = networkManagerPost(request, data); - m_pairingTv.insert(pairingReply, pairingTransactionId); + QHostAddress host = QHostAddress(params.paramValue("host address").toString()); + int port = params.paramValue("port").toInt(); + QPair request = TvDevice::createPairingRequest(host, port, secret); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_setupPairingTv.insert(reply, pairingTransactionId); m_tvKeys.insert(params.paramValue("uuid").toString(), secret); return DeviceManager::DeviceSetupStatusAsync; @@ -267,71 +297,136 @@ void DevicePluginLgSmartTv::networkManagerReplyReady(QNetworkReply *reply) { int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (reply == m_showPinReply) { - reply->deleteLater(); - } else if (m_pairingTv.keys().contains(reply)) { - PairingTransactionId pairingTransactionId = m_pairingTv.take(reply); + if (m_showPinReply.contains(reply)) { + m_showPinReply.removeAll(reply); + if (status != 200) { + qCWarning(dcLgSmartTv) << "display pin on TV request error:" << status << reply->errorString(); + } + } else if (m_setupPairingTv.keys().contains(reply)) { + PairingTransactionId pairingTransactionId = m_setupPairingTv.take(reply); if(status != 200) { - qWarning() << "Could not pair: please check the key and retry"; + qCWarning(dcLgSmartTv) << "pair TV request error:" << status << reply->errorString(); + emit pairingFinished(pairingTransactionId, DeviceManager::DeviceSetupStatusFailure); + } else { + // End pairing before calling setupDevice, which will always try to pair + QPair request = TvDevice::createEndPairingRequest(reply->request().url()); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + m_setupEndPairingTv.insert(reply, pairingTransactionId); + } + } else if (m_setupEndPairingTv.keys().contains(reply)) { + PairingTransactionId pairingTransactionId = m_setupEndPairingTv.take(reply); + if(status != 200) { + qCWarning(dcLgSmartTv) << "end pairing TV request error:" << status << reply->errorString(); emit pairingFinished(pairingTransactionId, DeviceManager::DeviceSetupStatusFailure); } else { - qDebug() << "Paired tv successfully"; emit pairingFinished(pairingTransactionId, DeviceManager::DeviceSetupStatusSuccess); } - reply->deleteLater(); + } else if (m_asyncSetup.keys().contains(reply)) { + Device *device = m_asyncSetup.take(reply); + TvDevice *tv = m_tvList.key(device); + if(status != 200) { + qCWarning(dcLgSmartTv) << "pair TV request error:" << status << reply->errorString(); + tv->setPaired(false); + emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); + } else { + qCDebug(dcLgSmartTv) << "paired TV successfully."; + tv->setPaired(true); + refreshTv(device); + emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); + } + } else if (m_deleteTv.contains(reply)) { + m_deleteTv.removeAll(reply); + if(status != 200) { + qCWarning(dcLgSmartTv) << "end pairing TV (device deleted) request error:" << status << reply->errorString(); + } else { + qCDebug(dcLgSmartTv) << "end pairing TV (device deleted) successfully."; + } + } else if (m_volumeInfoRequests.keys().contains(reply)) { + Device *device = m_volumeInfoRequests.take(reply); + TvDevice *tv = m_tvList.key(device); + if(status != 200) { + tv->setReachable(false); + qCWarning(dcLgSmartTv) << "volume information request error:" << status << reply->errorString(); + } else { + tv->setReachable(true); + tv->onVolumeInformationUpdate(reply->readAll()); + } + } else if (m_channelInfoRequests.keys().contains(reply)) { + Device *device = m_channelInfoRequests.take(reply); + TvDevice *tv = m_tvList.key(device); + if(status != 200) { + tv->setReachable(false); + qCWarning(dcLgSmartTv) << "channel information request error:" << status << reply->errorString(); + } else { + tv->setReachable(true); + tv->onChannelInformationUpdate(reply->readAll()); + } + } else if (m_asyncActions.keys().contains(reply)) { + ActionId actionId = m_asyncActions.value(reply); + if(status != 200) { + emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorHardwareNotAvailable); + qCWarning(dcLgSmartTv) << "action request error:" << status << reply->errorString(); + } else { + emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorNoError); + } } -} - -void DevicePluginLgSmartTv::deviceRemoved(Device *device) -{ - if (!m_tvList.values().contains(device)) { - return; - } - - TvDevice *tvDevice= m_tvList.key(device); - qCDebug(dcLgSmartTv) << "remove LG SmartTv " << tvDevice->modelName(); - tvDevice->endPairing(); - m_tvList.remove(tvDevice); - delete tvDevice; + reply->deleteLater(); } void DevicePluginLgSmartTv::guhTimer() { - foreach (TvDevice *tvDevice, m_tvList.keys()) { - tvDevice->refresh(); + foreach (Device *device, m_tvList.values()) { + TvDevice *tv = m_tvList.key(device); + if (tv->paired()) { + refreshTv(device); + } else { + pairTvDevice(device); + } } } +void DevicePluginLgSmartTv::pairTvDevice(Device *device, const bool &setup) +{ + QHostAddress host = QHostAddress(device->paramValue("host address").toString()); + int port = device->paramValue("port").toInt(); + QString key = device->paramValue("key").toString(); + QPair request = TvDevice::createPairingRequest(host, port, key); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + if (setup) { + m_asyncSetup.insert(reply, device); + } else { + m_pairRequests.insert(reply, device); + } +} -void DevicePluginLgSmartTv::slotPairingFinished(const bool &success) +void DevicePluginLgSmartTv::unpairTvDevice(Device *device) +{ + QHostAddress host = QHostAddress(device->paramValue("host address").toString()); + int port = device->paramValue("port").toInt(); + QPair request = TvDevice::createEndPairingRequest(host, port); + QNetworkReply *reply = networkManagerPost(request.first, request.second); + + m_deleteTv.append(reply); +} + +void DevicePluginLgSmartTv::refreshTv(Device *device) +{ + TvDevice *tv = m_tvList.key(device); + // check volume information + QNetworkReply *volumeReply = networkManagerGet(tv->createVolumeInformationRequest()); + m_volumeInfoRequests.insert(volumeReply, device); + + // check channel information + QNetworkReply *channelReply = networkManagerGet(tv->createChannelInformationRequest()); + m_channelInfoRequests.insert(channelReply, device); +} + +void DevicePluginLgSmartTv::stateChanged() { TvDevice *tvDevice = static_cast(sender()); Device *device = m_tvList.value(tvDevice); - // ...otherwise emit deviceSetupFinished with appropriate DeviceError - if (success) { - emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); - tvDevice->refresh(); - } else { - emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); - } -} - -void DevicePluginLgSmartTv::sendingCommandFinished(const bool &success, const ActionId &actionId) -{ - if (success) { - emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorNoError); - } else { - emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorActionTypeNotFound); - } -} - -void DevicePluginLgSmartTv::statusChanged() -{ - TvDevice *tvDevice = static_cast(sender()); - Device *device = m_tvList.value(tvDevice); - - device->setStateValue(tvReachableStateTypeId, tvDevice->isReachable()); + device->setStateValue(reachableStateTypeId, tvDevice->reachable()); device->setStateValue(tv3DModeStateTypeId, tvDevice->is3DMode()); device->setStateValue(tvVolumeLevelStateTypeId, tvDevice->volumeLevel()); device->setStateValue(tvMuteStateTypeId, tvDevice->mute()); diff --git a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h index e77d1e2a..78fd97ec 100644 --- a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h +++ b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.h @@ -35,36 +35,48 @@ class DevicePluginLgSmartTv : public DevicePlugin public: explicit DevicePluginLgSmartTv(); - + DeviceManager::HardwareResources requiredHardware() const override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; - DeviceManager::HardwareResources requiredHardware() const override; - DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; - void upnpDiscoveryFinished(const QList &upnpDeviceDescriptorList) override; - void upnpNotifyReceived(const QByteArray ¬ifyData); - void postSetupDevice(Device *device) override; + void deviceRemoved(Device *device) override; + void upnpDiscoveryFinished(const QList &upnpDeviceDescriptorList) override; + + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; DeviceManager::DeviceError displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) override; DeviceManager::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList ¶ms, const QString &secret) override; void networkManagerReplyReady(QNetworkReply *reply) override; - void deviceRemoved(Device *device) override; - void guhTimer() override; private: QHash m_tvList; - QHash m_pairingTv; - QHash m_unpairTv; QHash m_tvKeys; - QNetworkReply *m_showPinReply; + + // first pairing setup + QHash m_setupPairingTv; + QHash m_setupEndPairingTv; + QList m_showPinReply; + + // async setup + QHash m_asyncSetup; + QHash m_pairRequests; + QList m_deleteTv; + + // action requests + QHash m_asyncActions; + + // update requests + QHash m_volumeInfoRequests; + QHash m_channelInfoRequests; + + void pairTvDevice(Device *device, const bool &setup = false); + void unpairTvDevice(Device *device); + void refreshTv(Device *device); private slots: - void slotPairingFinished(const bool &success); - void sendingCommandFinished(const bool &success, const ActionId &actionId); - void statusChanged(); - + void stateChanged(); }; #endif // DEVICEPLUGINLGSMARTTV_H diff --git a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.json b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.json index 61a7369f..80afcc48 100644 --- a/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.json +++ b/plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.json @@ -47,7 +47,7 @@ "stateTypes": [ { "id": "b056c36b-df87-4177-8d5d-1e7c1e8cdc7a", - "idName": "tvReachable", + "idName": "reachable", "name": "reachable", "type": "bool", "defaultValue": false @@ -64,6 +64,7 @@ "idName": "tvVolumeLevel", "name": "volume level", "type": "int", + "unit": "Percentage", "defaultValue": 0 }, { @@ -77,13 +78,15 @@ "id": "84c86670-77c7-4fc6-9e23-abca066e76aa", "idName": "tvChannelType", "name": "tv channel type", - "type": "QString" + "type": "QString", + "defaultValue": "-" }, { "id": "265dc5f7-3f4d-4002-a6fe-2a53986bcf1d", "idName": "tvChannelName", "name": "channel name", - "type": "QString" + "type": "QString", + "defaultValue": "-" }, { "id": "881629a3-4ce2-42ba-8ce6-10d90c383799", @@ -96,7 +99,8 @@ "id": "3f53e52e-1ad7-40e7-8080-76908e720cac", "idName": "tvProgramName", "name": "program name", - "type": "QString" + "type": "QString", + "defaultValue": "-" }, { "id": "e895017a-139f-410c-bfb2-4d008104e164", @@ -109,7 +113,8 @@ "id": "58b734ec-2269-4c57-99e1-e1eeee401053", "idName": "tvInputSourceLabelName", "name": "input source label", - "type": "QString" + "type": "QString", + "defaultValue": "-" } ], "actionTypes": [ diff --git a/plugins/deviceplugins/lgsmarttv/tvdevice.cpp b/plugins/deviceplugins/lgsmarttv/tvdevice.cpp index de32949f..2ab10343 100644 --- a/plugins/deviceplugins/lgsmarttv/tvdevice.cpp +++ b/plugins/deviceplugins/lgsmarttv/tvdevice.cpp @@ -21,16 +21,21 @@ #include "tvdevice.h" #include "loggingcategories.h" -TvDevice::TvDevice(QObject *parent, UpnpDeviceDescriptor upnpDeviceDescriptor) : - UpnpDevice(parent, upnpDeviceDescriptor) +TvDevice::TvDevice(const QHostAddress &hostAddress, const int &port, QObject *parent) : + QObject(parent), + m_hostAddress(hostAddress), + m_port(port), + m_paired(false), + m_reachable(false), + m_is3DMode(false), + m_mute(false), + m_volumeLevel(-1), + m_inputSourceIndex(-1), + m_channelNumber(-1) { - m_manager = new QNetworkAccessManager(this); + m_eventHandler = new TvEventHandler(hostAddress, port, this); - m_key = "0"; - m_pairingStatus = false; - m_reachable = false; - - connect(m_manager, &QNetworkAccessManager::finished, this, &TvDevice::replyFinished); + connect(m_eventHandler, &TvEventHandler::eventOccured, this, &TvDevice::eventOccured); } void TvDevice::setKey(const QString &key) @@ -43,14 +48,60 @@ QString TvDevice::key() const return m_key; } -bool TvDevice::isReachable() const +void TvDevice::setHostAddress(const QHostAddress &hostAddress) { - return m_reachable; + m_hostAddress = hostAddress; +} + +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::setUuid(const QString &uuid) +{ + m_uuid = uuid; +} + +QString TvDevice::uuid() const +{ + return m_uuid; +} + +void TvDevice::setPaired(const bool &paired) +{ + if (m_paired != paired) { + m_paired = paired; + stateChanged(); + } } bool TvDevice::paired() const { - return m_pairingStatus; + return m_paired; +} + +void TvDevice::setReachable(const bool &reachable) +{ + if (m_reachable != reachable) { + m_reachable = reachable; + emit stateChanged(); + } +} + +bool TvDevice::reachable() const +{ + return m_reachable; } bool TvDevice::is3DMode() const @@ -98,42 +149,45 @@ QString TvDevice::inputSourceLabelName() const return m_inputSourceLabel; } -void TvDevice::showPairingKey() +QPair TvDevice::createDisplayKeyRequest(const QHostAddress &host, const int &port) { - QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/pairing"; - + QString urlString = "http://" + host.toString() + ":" + QString::number(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")); QByteArray data = " showKey"; - - m_showKeyReplay = m_manager->post(request,data); + return QPair(request, data); } -void TvDevice::requestPairing() +QPair TvDevice::createPairingRequest(const QHostAddress &host, const int &port, const QString &key) { - if(m_key.isNull()){ - emit pairingFinished(false); - } - - QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/pairing"; - + QString urlString = "http://" + host.toString() + ":" + QString::number(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")); - QByteArray data = "hello" + m_key.toUtf8() + "8080"; - - m_requestPairingReplay = m_manager->post(request,data); + QByteArray data = "hello" + key.toUtf8() + "8080"; + return QPair(request, data); } -void TvDevice::endPairing() +QPair TvDevice::createEndPairingRequest(const QUrl &url) { - QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/pairing"; + QNetworkRequest request; + request.setUrl(url); + 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"; + return QPair(request, data); +} + +QPair TvDevice::createEndPairingRequest(const QHostAddress &host, const int &port) +{ + QString urlString = "http://" + host.toString() + ":" + QString::number(port) + "/udap/api/pairing"; QNetworkRequest request; request.setUrl(QUrl(urlString)); request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8")); @@ -141,81 +195,49 @@ void TvDevice::endPairing() request.setRawHeader("Connection", "Close"); QByteArray data = "byebye8080"; - - m_finishingPairingReplay = m_manager->post(request,data); + return QPair(request, data); } - -void TvDevice::sendCommand(TvDevice::RemoteKey key, ActionId actionId) -{ - m_actionId = actionId; - - if(!m_pairingStatus) { - requestPairing(); - return; - } - - QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/command"; - - QByteArray data; - data.append("HandleKeyInput"); - data.append(QString::number(key).toUtf8()); - data.append(""); - - 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")); - - m_sendCommandReplay = m_manager->post(request,data); -} - -void TvDevice::setupEventHandler() -{ - qCDebug(dcLgSmartTv) << "set up event handler " << hostAddress().toString() << port(); - m_eventHandler = new TvEventHandler(this, hostAddress(), port()); - connect(m_eventHandler, &TvEventHandler::eventOccured, this, &TvDevice::eventOccured); -} - -void TvDevice::refresh() -{ - if(paired()) { - queryChannelInformation(); - queryVolumeInformation(); - }else{ - requestPairing(); - } -} - -void TvDevice::queryVolumeInformation() +QNetworkRequest TvDevice::createVolumeInformationRequest() { QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/data?target=volume_info"; - QNetworkRequest request; request.setUrl(QUrl(urlString)); request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml")); request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0")); request.setRawHeader("Connection", "Close"); - - m_queryVolumeInformationReplay = m_manager->get(request); + return request; } -void TvDevice::queryChannelInformation() +QNetworkRequest TvDevice::createChannelInformationRequest() { QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(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); + QNetworkRequest request; + request.setUrl(QUrl(urlString)); + request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml")); + request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0")); + request.setRawHeader("Connection", "Close"); + return request; } -void TvDevice::parseVolumeInformation(const QByteArray &data) +QPair TvDevice::createPressButtonRequest(const TvDevice::RemoteKey &key) { - qCDebug(dcLgSmartTv) << printXmlData(data); + QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/command"; + 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")); + + QByteArray data; + data.append("HandleKeyInput"); + data.append(QString::number(key).toUtf8()); + data.append(""); + return QPair(request, data); +} + +void TvDevice::onVolumeInformationUpdate(const QByteArray &data) +{ + //qCDebug(dcLgSmartTv) << printXmlData(data); QXmlStreamReader xml(data); while(!xml.atEnd() && !xml.hasError()) { @@ -228,12 +250,12 @@ void TvDevice::parseVolumeInformation(const QByteArray &data) m_volumeLevel = QVariant(xml.readElementText()).toInt(); } } - emit statusChanged(); + emit stateChanged(); } -void TvDevice::parseChannelInformation(const QByteArray &data) +void TvDevice::onChannelInformationUpdate(const QByteArray &data) { - qCDebug(dcLgSmartTv) << printXmlData(data); + //qCDebug(dcLgSmartTv) << printXmlData(data); QXmlStreamReader xml(data); while(!xml.atEnd() && !xml.hasError()) { @@ -258,10 +280,10 @@ void TvDevice::parseChannelInformation(const QByteArray &data) m_inputSourceLabel = xml.readElementText(); } } - emit statusChanged(); + emit stateChanged(); } -QString TvDevice::printXmlData(QByteArray data) +QString TvDevice::printXmlData(const QByteArray &data) { QString xmlOut; QXmlStreamReader reader(data); @@ -275,87 +297,29 @@ QString TvDevice::printXmlData(QByteArray data) } } if(reader.hasError()) { - qCWarning(dcLgSmartTv) << "error reading XML device information: " << reader.errorString(); + qCWarning(dcLgSmartTv) << "error reading XML device information:" << reader.errorString(); } return xmlOut; } -void TvDevice::replyFinished(QNetworkReply *reply) -{ - int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - if(status != 200) { - m_reachable = false; - } else { - m_reachable = true; - } - - if(reply == m_showKeyReplay) { - if(status != 200) { - qCWarning(dcLgSmartTv) << "ERROR: could not request to show pairing key on screen " << status; - } - m_showKeyReplay->deleteLater(); - } - if(reply == m_requestPairingReplay) { - if(status != 200) { - m_pairingStatus = false; - emit pairingFinished(false); - qCWarning(dcLgSmartTv) << "could not pair with device" << status; - } else { - m_pairingStatus = true; - qCDebug(dcLgSmartTv) << "successfully paired with tv " << modelName(); - emit pairingFinished(true); - } - m_requestPairingReplay->deleteLater(); - } - - if(reply == m_finishingPairingReplay) { - if(status == 200) { - m_pairingStatus = false; - qCDebug(dcLgSmartTv) << "successfully unpaired from tv " << modelName(); - } - m_finishingPairingReplay->deleteLater(); - } - - if(reply == m_sendCommandReplay) { - if (status != 200) { - emit sendCommandFinished(false,m_actionId); - qCWarning(dcLgSmartTv) << "ERROR: could not send comand" << status; - } else { - m_pairingStatus = true; - qCDebug(dcLgSmartTv) << "successfully sent command to tv " << 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) { + qCDebug(dcLgSmartTv) << "event handler data received" << printXmlData(data); + // if we got a channel changed event... if(data.contains("ChannelChanged")) { - parseChannelInformation(data); + onChannelInformationUpdate(data); return; } + //TODO: handle ip address change (dhcp) notification from the tv! + // 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")) { - qCDebug(dcLgSmartTv) << "--> tv ended pairing"; - m_pairingStatus = false; - m_reachable = false; - emit statusChanged(); + qCDebug(dcLgSmartTv) << "ended pairing (host)"; + setPaired(false); + setReachable(false); return; } @@ -374,6 +338,5 @@ void TvDevice::eventOccured(const QByteArray &data) } } } - - emit statusChanged(); + emit stateChanged(); } diff --git a/plugins/deviceplugins/lgsmarttv/tvdevice.h b/plugins/deviceplugins/lgsmarttv/tvdevice.h index 37ac79cd..6ec7ba2d 100644 --- a/plugins/deviceplugins/lgsmarttv/tvdevice.h +++ b/plugins/deviceplugins/lgsmarttv/tvdevice.h @@ -35,13 +35,12 @@ #include "plugin/deviceplugin.h" #include "tveventhandler.h" -#include "network/upnpdiscovery/upnpdevice.h" -class TvDevice : public UpnpDevice +class TvDevice : public QObject { Q_OBJECT public: - explicit TvDevice(QObject *parent = 0, UpnpDeviceDescriptor upnpDeviceDescriptor = UpnpDeviceDescriptor()); + explicit TvDevice(const QHostAddress &hostAddress, const int &port, QObject *parent = 0); enum RemoteKey{ Power = 1, @@ -116,10 +115,22 @@ public: void setKey(const QString &key); QString key() const; - bool paired() const; + void setHostAddress(const QHostAddress &hostAddress); + QHostAddress hostAddress() const; + + void setPort(const int &port); + int port() const; + + void setUuid(const QString &uuid); + QString uuid() const; // States - bool isReachable() const; + void setPaired(const bool &paired); + bool paired() const; + + void setReachable(const bool &reachable); + bool reachable() const; + bool is3DMode() const; int volumeLevel() const; bool mute() const; @@ -130,55 +141,45 @@ public: 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(); + // other methods + static QPair createDisplayKeyRequest(const QHostAddress &host, const int &port); + static QPair createPairingRequest(const QHostAddress &host, const int &port, const QString &key); + static QPair createEndPairingRequest(const QUrl &url); + static QPair createEndPairingRequest(const QHostAddress &host, const int &port); + QPair createPressButtonRequest(const TvDevice::RemoteKey &key); + + QNetworkRequest createVolumeInformationRequest(); + QNetworkRequest createChannelInformationRequest(); + void onVolumeInformationUpdate(const QByteArray &data); + void onChannelInformationUpdate(const QByteArray &data); private: - 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; - - QNetworkAccessManager *m_manager; - QNetworkReply *m_showKeyReplay; - QNetworkReply *m_requestPairingReplay; - QNetworkReply *m_finishingPairingReplay; - QNetworkReply *m_sendCommandReplay; - QNetworkReply *m_queryVolumeInformationReplay; - QNetworkReply *m_queryChannelInformationReplay; - TvEventHandler *m_eventHandler; - QString printXmlData(QByteArray data); - void queryVolumeInformation(); - void queryChannelInformation(); - void parseVolumeInformation(const QByteArray &data); - void parseChannelInformation(const QByteArray &data); + QHostAddress m_hostAddress; + int m_port; + QString m_uuid; + QString m_key; + + // States + bool m_paired; + bool m_reachable; + bool m_is3DMode; + bool m_mute; + int m_volumeLevel; + int m_inputSourceIndex; + int m_channelNumber; + QString m_channelType; + QString m_channelName; + QString m_programName; + QString m_inputSourceLabel; + + QString printXmlData(const QByteArray &data); signals: - void pairingFinished(const bool &success); - void statusChanged(); - void sendCommandFinished(const bool &succeeded, const ActionId &actionId); + void stateChanged(); private slots: - void replyFinished(QNetworkReply *reply); void eventOccured(const QByteArray &data); }; diff --git a/plugins/deviceplugins/lgsmarttv/tveventhandler.cpp b/plugins/deviceplugins/lgsmarttv/tveventhandler.cpp index d9eff7e3..9540c6fe 100644 --- a/plugins/deviceplugins/lgsmarttv/tveventhandler.cpp +++ b/plugins/deviceplugins/lgsmarttv/tveventhandler.cpp @@ -21,45 +21,34 @@ #include "tveventhandler.h" #include "loggingcategories.h" -TvEventHandler::TvEventHandler(QObject *parent, QHostAddress host, int port) : - QTcpServer(parent),m_host(host),m_port(port) +TvEventHandler::TvEventHandler(const QHostAddress &host, const int &port, QObject *parent) : + QTcpServer(parent), + m_host(host), + m_port(port), + m_expectingData(false) { - listen(QHostAddress::AnyIPv4,m_port); - m_disabled = false; - m_expectingData = false; - - //TODO: handle ip address change (dhcp) notification from the tv! + listen(QHostAddress::AnyIPv4, m_port); } 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); + qCDebug(dcLgSmartTv) << "event handler -> incoming connection" << tcpSocket->peerAddress().toString() << tcpSocket->peerName(); - qCDebug(dcLgSmartTv) << "incomming connection" << tcpSocket->peerAddress().toString() << tcpSocket->peerName(); + connect(tcpSocket, &QTcpSocket::readyRead, this, &TvEventHandler::readClient); + connect(tcpSocket, &QTcpSocket::disconnected, this, &TvEventHandler::onDisconnected); } void TvEventHandler::readClient() { - if(m_disabled){ - return; - } - QTcpSocket* socket = (QTcpSocket*)sender(); // reject everything, except the tv if(socket->peerAddress() != m_host){ - qCWarning(dcLgSmartTv) << "reject connection from " << socket->peerAddress().toString(); socket->close(); - if (socket->state() == QTcpSocket::UnconnectedState) { - delete socket; - } + socket->deleteLater(); + qCWarning(dcLgSmartTv) << "event handler -> rejecting connection from " << socket->peerAddress().toString(); return; } @@ -88,23 +77,15 @@ void TvEventHandler::readClient() if (data.startsWith("POST") && !m_expectingData) { m_expectingData = true; QStringList tokens = QString(data).split(QRegExp("[ \r\n][ \r\n]*")); - qCDebug(dcLgSmartTv) << "event occured" << "http://" << m_host.toString() << ":" << m_port << tokens[1]; + qCDebug(dcLgSmartTv) << "event handler -> event occured" << "http://" << m_host.toString() << ":" << m_port << tokens[1]; } } } -void TvEventHandler::discardClient() +void TvEventHandler::onDisconnected() { QTcpSocket* socket = (QTcpSocket*)sender(); + qCDebug(dcLgSmartTv) << "event handler -> client disconnected" << socket->peerAddress(); socket->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 index c9ef9614..702e84f7 100644 --- a/plugins/deviceplugins/lgsmarttv/tveventhandler.h +++ b/plugins/deviceplugins/lgsmarttv/tveventhandler.h @@ -35,29 +35,20 @@ class TvEventHandler : public QTcpServer { Q_OBJECT public: - explicit TvEventHandler(QObject *parent = 0, QHostAddress host = QHostAddress(), int port = 8080); + explicit TvEventHandler(const QHostAddress &host, const int &port = 8080, QObject *parent = 0); 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(); + void onDisconnected(); };