diff --git a/lgsmarttv/devicepluginlgsmarttv.cpp b/lgsmarttv/devicepluginlgsmarttv.cpp index c677d6dc..7636304f 100644 --- a/lgsmarttv/devicepluginlgsmarttv.cpp +++ b/lgsmarttv/devicepluginlgsmarttv.cpp @@ -70,44 +70,69 @@ DeviceManager::DeviceError DevicePluginLgSmartTv::discoverDevices(const DeviceCl Q_UNUSED(params) Q_UNUSED(deviceClassId) - qCDebug(dcLgSmartTv()) << "Start discovering"; - UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("udap:rootservice","UDAP/2.0"); - connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginLgSmartTv::onUpnpDiscoveryFinished); + if (deviceClassId == lgSmartTvDeviceClassId) { + qCDebug(dcLgSmartTv()) << "Start discovering"; + UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("udap:rootservice","UDAP/2.0"); + connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginLgSmartTv::onUpnpDiscoveryFinished); + } + + if (deviceClassId == webosTvDeviceClassId) { + qCDebug(dcLgSmartTv()) << "Start discovering"; + UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices(""); + connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginLgSmartTv::onWebosUpnpDiscoveryFinished); + } + return DeviceManager::DeviceErrorAsync; } DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::setupDevice(Device *device) { - qCDebug(dcLgSmartTv()) << "Setup LG smart TV" << device->name() << device->params(); - QHostAddress address = QHostAddress(device->paramValue(lgSmartTvDeviceHostAddressParamTypeId).toString()); - TvDevice *tvDevice = new TvDevice(address, device->paramValue(lgSmartTvDevicePortParamTypeId).toInt(), this); - tvDevice->setUuid(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString()); + qCDebug(dcLgSmartTv()) << "Setup device" << device->name() << device->params(); - // If the key is missing, this setup call comes from a pairing procedure - if (device->paramValue(lgSmartTvDeviceKeyParamTypeId) == QString()) { - // Check if we know the key from the pairing procedure - if (!m_tvKeys.contains(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString())) { - qCWarning(dcLgSmartTv) << "could not find any pairing key"; - return DeviceManager::DeviceSetupStatusFailure; + if (device->deviceClassId() == lgSmartTvDeviceClassId) { + QHostAddress address = QHostAddress(device->paramValue(lgSmartTvDeviceHostAddressParamTypeId).toString()); + TvDevice *tvDevice = new TvDevice(address, device->paramValue(lgSmartTvDevicePortParamTypeId).toInt(), this); + tvDevice->setUuid(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString()); + + // If the key is missing, this setup call comes from a pairing procedure + if (device->paramValue(lgSmartTvDeviceKeyParamTypeId) == QString()) { + // Check if we know the key from the pairing procedure + if (!m_tvKeys.contains(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString())) { + qCWarning(dcLgSmartTv) << "could not find any pairing key"; + return DeviceManager::DeviceSetupStatusFailure; + } + // Use the key from the pairing procedure + QString key = m_tvKeys.value(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString()); + tvDevice->setKey(key); + device->setParamValue(lgSmartTvDeviceKeyParamTypeId, key); + } else { + //Add the key for editing + if (!m_tvKeys.contains(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString())) { + m_tvKeys.insert(tvDevice->uuid(), tvDevice->key()); + } } - // Use the key from the pairing procedure - QString key = m_tvKeys.value(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString()); - tvDevice->setKey(key); - device->setParamValue(lgSmartTvDeviceKeyParamTypeId, key); - } else { - //Add the key for editing - if (!m_tvKeys.contains(device->paramValue(lgSmartTvDeviceUuidParamTypeId).toString())) { - m_tvKeys.insert(tvDevice->uuid(), tvDevice->key()); + + connect(tvDevice, &TvDevice::stateChanged, this, &DevicePluginLgSmartTv::stateChanged); + m_tvList.insert(tvDevice, device); + + + if (!m_pluginTimer) { + m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5); + connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginLgSmartTv::onPluginTimer); } } - connect(tvDevice, &TvDevice::stateChanged, this, &DevicePluginLgSmartTv::stateChanged); - m_tvList.insert(tvDevice, device); + if (device->deviceClassId() == webosTvDeviceClassId) { + QHostAddress hostAddress = QHostAddress(device->paramValue(webosTvDeviceHostAddressParamTypeId).toString()); + WebosConnection *webosConnection = new WebosConnection(this); + webosConnection->setHostAddress(hostAddress); + connect(webosConnection, &WebosConnection::connectedChanged, this, [device](bool connected){ + device->setStateValue(webosTvConnectedStateTypeId, connected); + }); - if (!m_pluginTimer) { - m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5); - connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginLgSmartTv::onPluginTimer); + m_webosTvs.insert(webosConnection, device); + webosConnection->connectTv(); } return DeviceManager::DeviceSetupStatusSuccess; @@ -115,16 +140,27 @@ DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::setupDevice(Device *devi void DevicePluginLgSmartTv::deviceRemoved(Device *device) { - if (!m_tvList.values().contains(device)) - return; + qCDebug(dcLgSmartTv()) << "Remove device" << device; - TvDevice *tvDevice= m_tvList.key(device); - qCDebug(dcLgSmartTv) << "Remove device" << device->name(); - unpairTvDevice(device); - m_tvList.remove(tvDevice); - delete tvDevice; + if (device->deviceClassId() == lgSmartTvDeviceClassId) { + if (!m_tvList.values().contains(device)) + return; - if (m_tvList.isEmpty() && m_pluginTimer) { + TvDevice *tvDevice= m_tvList.key(device); + qCDebug(dcLgSmartTv) << "Remove device" << device->name(); + unpairTvDevice(device); + m_tvList.remove(tvDevice); + delete tvDevice; + } + + if (device->deviceClassId() == webosTvDeviceClassId) { + WebosConnection *connection = m_webosTvs.key(device); + m_webosTvs.remove(connection); + delete connection; + } + + + if (myDevices().isEmpty() && m_pluginTimer) { hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer); m_pluginTimer = nullptr; } @@ -132,112 +168,119 @@ void DevicePluginLgSmartTv::deviceRemoved(Device *device) void DevicePluginLgSmartTv::postSetupDevice(Device *device) { - pairTvDevice(device); + if (device->deviceClassId() == lgSmartTvDeviceClassId) { + pairTvDevice(device); + } } DeviceManager::DeviceError DevicePluginLgSmartTv::executeAction(Device *device, const Action &action) { - TvDevice * tvDevice = m_tvList.key(device); + if (device->deviceClassId() == lgSmartTvDeviceClassId) { - if (!tvDevice->reachable()) { - qCWarning(dcLgSmartTv) << "Device not reachable"; - return DeviceManager::DeviceErrorHardwareNotAvailable; + TvDevice * tvDevice = m_tvList.key(device); + + if (!tvDevice->reachable()) { + qCWarning(dcLgSmartTv) << "Device not reachable"; + return DeviceManager::DeviceErrorHardwareNotAvailable; + } + + if (action.actionTypeId() == lgSmartTvCommandVolumeUpActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::VolUp); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandVolumeDownActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::VolDown); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandMuteActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Mute); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandChannelUpActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ChannelUp); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandChannelDownActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ChannelDown); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandPowerOffActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Power); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandArrowUpActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Up); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandArrowDownActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Down); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandArrowLeftActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Left); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandArrowRightActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Right); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandOkActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Ok); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandBackActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Back); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandHomeActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Home); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandInputSourceActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ExternalInput); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandExitActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Exit); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandInfoActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::Info); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandMyAppsActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::MyApps); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else if(action.actionTypeId() == lgSmartTvCommandProgramListActionTypeId) { + QPair request = tvDevice->createPressButtonRequest(TvDevice::ProgramList); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + m_asyncActions.insert(reply, action.id()); + } else { + return DeviceManager::DeviceErrorActionTypeNotFound; + } + return DeviceManager::DeviceErrorAsync; } - if (action.actionTypeId() == lgSmartTvCommandVolumeUpActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::VolUp); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandVolumeDownActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::VolDown); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandMuteActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Mute); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandChannelUpActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::ChannelUp); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandChannelDownActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::ChannelDown); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandPowerOffActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Power); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandArrowUpActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Up); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandArrowDownActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Down); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandArrowLeftActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Left); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandArrowRightActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Right); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandOkActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Ok); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandBackActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Back); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandHomeActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Home); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandInputSourceActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::ExternalInput); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandExitActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Exit); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandInfoActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::Info); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandMyAppsActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::MyApps); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else if(action.actionTypeId() == lgSmartTvCommandProgramListActionTypeId) { - QPair request = tvDevice->createPressButtonRequest(TvDevice::ProgramList); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_asyncActions.insert(reply, action.id()); - } else { - return DeviceManager::DeviceErrorActionTypeNotFound; - } - return DeviceManager::DeviceErrorAsync; + return DeviceManager::DeviceErrorNoError; } DeviceManager::DeviceError DevicePluginLgSmartTv::displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) @@ -256,16 +299,17 @@ DeviceManager::DeviceError DevicePluginLgSmartTv::displayPin(const PairingTransa DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList ¶ms, const QString &secret) { - Q_UNUSED(deviceClassId) + if (deviceClassId == lgSmartTvDeviceClassId) { - QHostAddress host = QHostAddress(params.paramValue(lgSmartTvDeviceHostAddressParamTypeId).toString()); - int port = params.paramValue(lgSmartTvDevicePortParamTypeId).toInt(); - QPair request = TvDevice::createPairingRequest(host, port, secret); - QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); - connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); + QHostAddress host = QHostAddress(params.paramValue(lgSmartTvDeviceHostAddressParamTypeId).toString()); + int port = params.paramValue(lgSmartTvDevicePortParamTypeId).toInt(); + QPair request = TvDevice::createPairingRequest(host, port, secret); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second); + connect(reply, &QNetworkReply::finished, this, &DevicePluginLgSmartTv::onNetworkManagerReplyFinished); - m_setupPairingTv.insert(reply, pairingTransactionId); - m_tvKeys.insert(params.paramValue(lgSmartTvDeviceUuidParamTypeId).toString(), secret); + m_setupPairingTv.insert(reply, pairingTransactionId); + m_tvKeys.insert(params.paramValue(lgSmartTvDeviceUuidParamTypeId).toString(), secret); + } return DeviceManager::DeviceSetupStatusAsync; } @@ -353,6 +397,21 @@ void DevicePluginLgSmartTv::onUpnpDiscoveryFinished() } +void DevicePluginLgSmartTv::onWebosUpnpDiscoveryFinished() +{ + qCDebug(dcLgSmartTv()) << "Upnp discovery finished"; + + UpnpDiscoveryReply *reply = static_cast(sender()); + if (reply->error() != UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError) { + qCWarning(dcLgSmartTv()) << "Upnp discovery error" << reply->error(); + } + reply->deleteLater(); + foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, reply->deviceDescriptors()) { + qCDebug(dcLgSmartTv) << upnpDeviceDescriptor; + } + +} + void DevicePluginLgSmartTv::onNetworkManagerReplyFinished() { QNetworkReply *reply = static_cast(sender()); diff --git a/lgsmarttv/devicepluginlgsmarttv.h b/lgsmarttv/devicepluginlgsmarttv.h index d587d956..9ee6d0e2 100644 --- a/lgsmarttv/devicepluginlgsmarttv.h +++ b/lgsmarttv/devicepluginlgsmarttv.h @@ -25,6 +25,7 @@ #include "tvdevice.h" #include "plugintimer.h" +#include "webosconnection.h" #include "plugin/deviceplugin.h" #include "network/upnp/upnpdevicedescriptor.h" @@ -37,7 +38,7 @@ class DevicePluginLgSmartTv : public DevicePlugin public: explicit DevicePluginLgSmartTv(); - ~DevicePluginLgSmartTv(); + ~DevicePluginLgSmartTv() override; void init() override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; @@ -54,6 +55,8 @@ private: QHash m_tvList; QHash m_tvKeys; + QHash m_webosTvs; + // first pairing setup QHash m_setupPairingTv; QHash m_setupEndPairingTv; @@ -77,6 +80,7 @@ private: private slots: void onPluginTimer(); void onUpnpDiscoveryFinished(); + void onWebosUpnpDiscoveryFinished(); void onNetworkManagerReplyFinished(); void stateChanged(); }; diff --git a/lgsmarttv/devicepluginlgsmarttv.json b/lgsmarttv/devicepluginlgsmarttv.json index a1a2c826..2d4d5a7d 100644 --- a/lgsmarttv/devicepluginlgsmarttv.json +++ b/lgsmarttv/devicepluginlgsmarttv.json @@ -239,6 +239,90 @@ "displayName": "program list" } ] + }, + { + "id": "99ef3b2a-707b-425d-b6a0-026c1d2a0215", + "name": "webosTv", + "displayName": "LG WebOS Smart Tv", + "createMethods": [ "Discovery" ], + "setupMethod": "PushButton", + "interfaces": ["connectable", "extendedvolumecontroller", "mediacontroller" ], + "pairingInfo": "Please accept the remote application shown on the Tv.", + "paramTypes": [ + { + "id": "3c9fef21-af12-49ce-af06-44bfe6a21521", + "name": "hostAddress", + "displayName": "host address", + "type": "QString", + "inputType": "IPv4Address" + }, + { + "id": "63688bd4-b9e5-4865-96e8-9bf94d63b10a", + "name": "apiKey", + "displayName": "API key", + "type": "QString", + "inputType": "Password" + } + ], + "stateTypes": [ + { + "id": "b056c36b-df87-4177-8d5d-1e7c1e8cdc7a", + "name": "connected", + "displayName": "Reachable", + "displayNameEvent": "Reachable changed", + "type": "bool", + "defaultValue": false + }, + { + "id": "8e49fe17-617d-4d2e-bf36-0a05e5687887", + "name": "mute", + "displayName": "Mute", + "displayNameEvent": "Mute changed", + "displayNameAction": "Set mute", + "type": "bool", + "defaultValue": false, + "writable": true + }, + { + "id": "40551b26-a7b2-4d02-ab22-fa6a9c731c4f", + "displayName": "Volume", + "displayNameEvent": "Volume changed", + "displayNameAction": "Set volume", + "maxValue": 100, + "minValue": 0, + "name": "volume", + "type": "int", + "defaultValue": 10, + "writable": true + } + ], + "actionTypes": [ + { + "id": "35cdb587-956a-4310-8e4c-85fdc240943e", + "displayName": "Skip back", + "name": "skipBack" + }, + { + "id": "04bb9eca-2ac5-4a49-a10b-1f10d612e394", + "displayName": "Stop", + "name": "stop" + }, + { + "id": "5ded6518-c5f6-4043-9a4b-bf838c2029e4", + "displayName": "Play", + "name": "play" + }, + { + "id": "9e6b2085-cef8-4c23-ae1a-c48cb359bccb", + "displayName": "Pause", + "name": "pause" + }, + { + "id": "3a922eee-832f-4e8c-b13b-00fb788ac8be", + "displayName": "SkipNext", + "name": "skipNext" + } + ] } ] } diff --git a/lgsmarttv/lgsmarttv.pro b/lgsmarttv/lgsmarttv.pro index 575ad2d0..7890cfda 100644 --- a/lgsmarttv/lgsmarttv.pro +++ b/lgsmarttv/lgsmarttv.pro @@ -2,16 +2,18 @@ include(../plugins.pri) TARGET = $$qtLibraryTarget(nymea_devicepluginlgsmarttv) -QT+= network xml +QT+= network xml websockets SOURCES += \ devicepluginlgsmarttv.cpp \ tvdevice.cpp \ - tveventhandler.cpp + tveventhandler.cpp \ + webosconnection.cpp HEADERS += \ devicepluginlgsmarttv.h \ tvdevice.h \ - tveventhandler.h + tveventhandler.h \ + webosconnection.h diff --git a/lgsmarttv/webosconnection.cpp b/lgsmarttv/webosconnection.cpp new file mode 100644 index 00000000..53cf352e --- /dev/null +++ b/lgsmarttv/webosconnection.cpp @@ -0,0 +1,108 @@ +#include "webosconnection.h" +#include "extern-plugininfo.h" + +#include + +WebosConnection::WebosConnection(QObject *parent) : + QObject(parent) +{ + m_websocket = new QWebSocket("", QWebSocketProtocol::VersionLatest, this); + + connect(m_websocket, &QWebSocket::connected, this, &WebosConnection::onConnected); + connect(m_websocket, &QWebSocket::disconnected, this, &WebosConnection::onDisconnected); + connect(m_websocket, &QWebSocket::stateChanged, this, &WebosConnection::onStateChanged); + connect(m_websocket, &QWebSocket::textMessageReceived, this, &WebosConnection::onTextMessageReceived); +} + +QHostAddress WebosConnection::hostAddress() const +{ + return m_hostAddress; +} + +void WebosConnection::setHostAddress(const QHostAddress &hostAddress) +{ + m_hostAddress = hostAddress; +} + +bool WebosConnection::connected() const +{ + return m_websocket->state() == QAbstractSocket::ConnectedState; +} + +void WebosConnection::sendRequest(const QVariantMap &request) +{ + m_websocket->sendTextMessage(QJsonDocument::fromVariant(request).toJson()); + m_id++; +} + +void WebosConnection::getVolume() +{ + qCDebug(dcLgSmartTv()) << "WebOS get volume"; + // {"type":"request","id":"status_' + i +'","uri":"ssap://audio/getVolume"} + QVariantMap request; + request.insert("type", "request"); + request.insert("id", QString("status_%1").arg(m_id)); + request.insert("uri", "ssap://audio/getVolume"); + + sendRequest(request); +} + +void WebosConnection::onConnected() +{ + qCDebug(dcLgSmartTv()) << "WebOS connected to" << m_hostAddress.toString(); + emit connectedChanged(true); + m_id = 0; + + registerClient(); + getVolume(); +} + +void WebosConnection::onDisconnected() +{ + qCDebug(dcLgSmartTv()) << "WebOS disconnected from" << m_hostAddress.toString() << m_websocket->closeReason(); + emit connectedChanged(false); +} + +void WebosConnection::onStateChanged(const QAbstractSocket::SocketState &state) +{ + qCDebug(dcLgSmartTv()) << "WebOS connection state changed" << state; +} + +void WebosConnection::onTextMessageReceived(const QString &message) +{ + qCDebug(dcLgSmartTv()) << "WebOS message received" << message; +} + +void WebosConnection::registerClient() +{ +// QVariantMap request; +// request.insert("type", "request"); +// request.insert("id", QString("register_%1").arg(m_id)); + +// QVariantMap payload; +// payload.insert("forcePairing", false); +// payload.insert("pairingType", "PROMPT"); + +// QVariantMap manifest; +// manifest.insert("manifestVersion", 1); +// manifest.insert("appVersion", "1.1"); +// payload.insert("manifest", manifest); + +// request.insert("payload", payload); + +// request.insert("uri", "ssap://audio/getVolume"); + QByteArray requestData("{\"type\":\"register\",\"id\":\"register_0\",\"payload\":{\"forcePairing\":false,\"pairingType\":\"PROMPT\",\"manifest\":{\"manifestVersion\":1,\"appVersion\":\"1.1\",\"signed\":{\"created\":\"20140509\",\"appId\":\"com.lge.test\",\"vendorId\":\"com.lge\",\"localizedAppNames\":{\"\":\"LG Remote App\",\"ko-KR\":\"리모컨 앱\",\"zxx-XX\":\"ЛГ Rэмotэ AПП\"},\"localizedVendorNames\":{\"\":\"LG Electronics\"},\"permissions\":[\"TEST_SECURE\",\"CONTROL_INPUT_TEXT\",\"CONTROL_MOUSE_AND_KEYBOARD\",\"READ_INSTALLED_APPS\",\"READ_LGE_SDX\",\"READ_NOTIFICATIONS\",\"SEARCH\",\"WRITE_SETTINGS\",\"WRITE_NOTIFICATION_ALERT\",\"CONTROL_POWER\",\"READ_CURRENT_CHANNEL\",\"READ_RUNNING_APPS\",\"READ_UPDATE_INFO\",\"UPDATE_FROM_REMOTE_APP\",\"READ_LGE_TV_INPUT_EVENTS\",\"READ_TV_CURRENT_TIME\"],\"serial\":\"2f930e2d2cfe083771f68e4fe7bb07\"},\"permissions\":[\"LAUNCH\",\"LAUNCH_WEBAPP\",\"APP_TO_APP\",\"CLOSE\",\"TEST_OPEN\",\"TEST_PROTECTED\",\"CONTROL_AUDIO\",\"CONTROL_DISPLAY\",\"CONTROL_INPUT_JOYSTICK\",\"CONTROL_INPUT_MEDIA_RECORDING\",\"CONTROL_INPUT_MEDIA_PLAYBACK\",\"CONTROL_INPUT_TV\",\"CONTROL_POWER\",\"READ_APP_STATUS\",\"READ_CURRENT_CHANNEL\",\"READ_INPUT_DEVICE_LIST\",\"READ_NETWORK_STATE\",\"READ_RUNNING_APPS\",\"READ_TV_CHANNEL_LIST\",\"WRITE_NOTIFICATION_TOAST\",\"READ_POWER_STATE\",\"READ_COUNTRY_INFO\"],\"signatures\":[{\"signatureVersion\":1,\"signature\":\"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw==\"}]}}}"); + sendRequest(QJsonDocument::fromJson(requestData).toVariant().toMap()); +} + +void WebosConnection::connectTv() +{ + QUrl url; + url.setScheme("ws"); + url.setHost(m_hostAddress.toString()); + url.setPort(3000); + + qCDebug(dcLgSmartTv()) << "Connecting to WebOS" << url.toString(); + + m_websocket->open(url); +} diff --git a/lgsmarttv/webosconnection.h b/lgsmarttv/webosconnection.h new file mode 100644 index 00000000..b61522cd --- /dev/null +++ b/lgsmarttv/webosconnection.h @@ -0,0 +1,47 @@ +#ifndef WEBOSCONNECTION_H +#define WEBOSCONNECTION_H + +#include +#include + +class WebosConnection : public QObject +{ + Q_OBJECT +public: + explicit WebosConnection(QObject *parent = nullptr); + + QHostAddress hostAddress() const; + void setHostAddress(const QHostAddress &hostAddress); + + QString apiKey() const; + void setApiKey(const QString &apiKey); + + bool connected() const; + +private: + QHostAddress m_hostAddress; + QWebSocket *m_websocket = nullptr; + + QString m_apiKey; + int m_id = 0; + + void sendRequest(const QVariantMap &request); + void getVolume(); + +signals: + void connectedChanged(bool connected); + +private slots: + void onConnected(); + void onDisconnected(); + void onStateChanged(const QAbstractSocket::SocketState &state); + void onTextMessageReceived(const QString &message); + +public slots: + void registerClient(); + void connectTv(); + + +}; + +#endif // WEBOSCONNECTION_H