mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-10-17 13:43:26 +02:00
Fix UDAP Lg smart tv and start implementing browsable
This commit is contained in:
parent
6d02d18df0
commit
40a435ee9c
@ -55,16 +55,10 @@ void IntegrationPluginLgSmartTv::init()
|
||||
void IntegrationPluginLgSmartTv::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
if (info->thingClassId() == lgSmartTvThingClassId) {
|
||||
|
||||
qCDebug(dcLgSmartTv()) << "Start discovering";
|
||||
qCDebug(dcLgSmartTv()) << "Start discovering LG UDAP 2.0 smart TVs...";
|
||||
UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("udap:rootservice","UDAP/2.0");
|
||||
|
||||
// Clean up in any case when the reply finishes
|
||||
connect(reply, &UpnpDiscoveryReply::finished, reply, &UpnpDiscoveryReply::deleteLater);
|
||||
|
||||
// Connect reply to discovery info for rsults.
|
||||
connect(reply, &UpnpDiscoveryReply::finished, info, [this, info, reply](){
|
||||
|
||||
if (reply->error() != UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError) {
|
||||
qCWarning(dcLgSmartTv()) << "Upnp discovery error" << reply->error();
|
||||
return info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error discovering devices. Please check your network connection."));
|
||||
@ -75,13 +69,14 @@ void IntegrationPluginLgSmartTv::discoverThings(ThingDiscoveryInfo *info)
|
||||
continue;
|
||||
|
||||
qCDebug(dcLgSmartTv) << upnpDeviceDescriptor;
|
||||
ThingDescriptor descriptor(lgSmartTvThingClassId, "Lg Smart Tv", upnpDeviceDescriptor.modelName());
|
||||
ThingDescriptor descriptor(lgSmartTvThingClassId, "LG Smart Tv", upnpDeviceDescriptor.modelName());
|
||||
ParamList params;
|
||||
params << Param(lgSmartTvThingNameParamTypeId, upnpDeviceDescriptor.friendlyName());
|
||||
params << Param(lgSmartTvThingUuidParamTypeId, upnpDeviceDescriptor.uuid());
|
||||
params << Param(lgSmartTvThingModelParamTypeId, upnpDeviceDescriptor.modelName());
|
||||
params << Param(lgSmartTvThingHostAddressParamTypeId, upnpDeviceDescriptor.hostAddress().toString());
|
||||
params << Param(lgSmartTvThingPortParamTypeId, upnpDeviceDescriptor.port());
|
||||
params << Param(lgSmartTvThingEventHandlerPortParamTypeId, TvEventHandler::getFreePort());
|
||||
descriptor.setParams(params);
|
||||
|
||||
foreach (Thing *existingThing, myThings()) {
|
||||
@ -96,7 +91,7 @@ void IntegrationPluginLgSmartTv::discoverThings(ThingDiscoveryInfo *info)
|
||||
});
|
||||
|
||||
} else if (info->thingClassId() == webosTvThingClassId) {
|
||||
qCDebug(dcLgSmartTv()) << "Start discovering Webos tv";
|
||||
qCDebug(dcLgSmartTv()) << "Start discovering WebOs smart TVs...";
|
||||
UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("");
|
||||
connect(reply, &UpnpDiscoveryReply::finished, reply, &UpnpDiscoveryReply::deleteLater);
|
||||
connect(reply, &UpnpDiscoveryReply::finished, info, [this, info, reply](){
|
||||
@ -116,68 +111,69 @@ void IntegrationPluginLgSmartTv::discoverThings(ThingDiscoveryInfo *info)
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::startPairing(ThingPairingInfo *info)
|
||||
{
|
||||
QHostAddress host = QHostAddress(info->params().paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
int port = info->params().paramValue(lgSmartTvThingPortParamTypeId).toInt();
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createDisplayKeyRequest(host, port);
|
||||
if (info->thingClassId() == lgSmartTvThingClassId) {
|
||||
QHostAddress host = QHostAddress(info->params().paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
quint16 port = info->params().paramValue(lgSmartTvThingPortParamTypeId).toUInt();
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createDisplayKeyRequest(host, port);
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [info, reply](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "display pin on TV request error:" << status << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error connecting to the TV."));
|
||||
return;
|
||||
}
|
||||
|
||||
connect(reply, &QNetworkReply::finished, info, [info, reply](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "display pin on TV request error:" << status << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Error connecting to the TV."));
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter the key displayed on the TV."));
|
||||
});
|
||||
info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter the key displayed on the TV."));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::confirmPairing(ThingPairingInfo *info, const QString &username, const QString &secret)
|
||||
{
|
||||
Q_UNUSED(username)
|
||||
|
||||
QHostAddress host = QHostAddress(info->params().paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
int port = info->params().paramValue(lgSmartTvThingPortParamTypeId).toInt();
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, secret);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
|
||||
connect(reply, &QNetworkReply::finished, info, [this, info, reply, secret](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "pair TV request error:" << status << reply->errorString();
|
||||
return info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Error pairing TV. Please try again."));
|
||||
}
|
||||
|
||||
// End pairing before calling setupDevice, which will always try to pair
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(reply->request().url());
|
||||
if (info->thingClassId() == lgSmartTvThingClassId) {
|
||||
QHostAddress host = QHostAddress(info->params().paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
quint16 port = info->params().paramValue(lgSmartTvThingPortParamTypeId).toUInt();
|
||||
quint16 eventHandlerPort = info->params().paramValue(lgSmartTvThingEventHandlerPortParamTypeId).toUInt();
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, eventHandlerPort, secret);
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
|
||||
connect(reply, &QNetworkReply::finished, info, [this, info, reply, secret](){
|
||||
connect(reply, &QNetworkReply::finished, info, [=](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "end pairing TV request error:" << status << reply->errorString();
|
||||
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Error pairing TV. Please try again."));
|
||||
return;
|
||||
qCWarning(dcLgSmartTv) << "Pair TV request error:" << status << reply->errorString();
|
||||
return info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Error pairing TV. Please try again."));
|
||||
}
|
||||
|
||||
pluginStorage()->beginGroup(info->thingId().toString());
|
||||
pluginStorage()->setValue("key", secret);
|
||||
pluginStorage()->endGroup();
|
||||
// End pairing before calling setupDevice, which will always try to pair
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(host, port, eventHandlerPort);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, info, [this, info, reply, secret](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "End pairing TV request error:" << status << reply->errorString();
|
||||
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Error pairing TV. Please try again."));
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
pluginStorage()->beginGroup(info->thingId().toString());
|
||||
pluginStorage()->setValue("key", secret);
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::setupThing(ThingSetupInfo *info)
|
||||
@ -187,7 +183,9 @@ void IntegrationPluginLgSmartTv::setupThing(ThingSetupInfo *info)
|
||||
if (thing->thingClassId() == lgSmartTvThingClassId) {
|
||||
qCDebug(dcLgSmartTv()) << "Setup LG smart TV" << thing->name() << thing->params();
|
||||
QHostAddress address = QHostAddress(thing->paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
TvDevice *tvDevice = new TvDevice(address, thing->paramValue(lgSmartTvThingPortParamTypeId).toInt(), this);
|
||||
quint16 port = thing->paramValue(lgSmartTvThingPortParamTypeId).toUInt();
|
||||
quint16 eventHandlerPort = thing->paramValue(lgSmartTvThingEventHandlerPortParamTypeId).toUInt();
|
||||
TvDevice *tvDevice = new TvDevice(address, port, eventHandlerPort, this);
|
||||
tvDevice->setUuid(thing->paramValue(lgSmartTvThingUuidParamTypeId).toString());
|
||||
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
@ -199,7 +197,6 @@ void IntegrationPluginLgSmartTv::setupThing(ThingSetupInfo *info)
|
||||
connect(tvDevice, &TvDevice::stateChanged, this, &IntegrationPluginLgSmartTv::stateChanged);
|
||||
m_tvList.insert(tvDevice, thing);
|
||||
|
||||
|
||||
if (!m_pluginTimer) {
|
||||
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(5);
|
||||
connect(m_pluginTimer, &PluginTimer::timeout, this, &IntegrationPluginLgSmartTv::onPluginTimer);
|
||||
@ -207,9 +204,7 @@ void IntegrationPluginLgSmartTv::setupThing(ThingSetupInfo *info)
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == webosTvThingClassId) {
|
||||
} else if (thing->thingClassId() == webosTvThingClassId) {
|
||||
QHostAddress hostAddress = QHostAddress(thing->paramValue(webosTvThingHostAddressParamTypeId).toString());
|
||||
WebosConnection *webosConnection = new WebosConnection(this);
|
||||
webosConnection->setHostAddress(hostAddress);
|
||||
@ -262,7 +257,6 @@ void IntegrationPluginLgSmartTv::executeAction(ThingActionInfo *info)
|
||||
Action action = info->action();
|
||||
|
||||
if (thing->thingClassId() == lgSmartTvThingClassId) {
|
||||
|
||||
TvDevice * tvDevice = m_tvList.key(thing);
|
||||
if (!tvDevice->reachable()) {
|
||||
qCWarning(dcLgSmartTv) << "Device not reachable";
|
||||
@ -270,59 +264,79 @@ void IntegrationPluginLgSmartTv::executeAction(ThingActionInfo *info)
|
||||
}
|
||||
|
||||
QNetworkReply *reply = nullptr;
|
||||
|
||||
if (action.actionTypeId() == lgSmartTvCommandVolumeUpActionTypeId) {
|
||||
if (action.actionTypeId() == lgSmartTvIncreaseVolumeActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::VolUp);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandVolumeDownActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvDecreaseVolumeActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::VolDown);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandMuteActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvMuteActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Mute);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandChannelUpActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvCommandChannelUpActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ChannelUp);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandChannelDownActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvCommandChannelDownActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ChannelDown);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandPowerOffActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvCommandPowerOffActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Power);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandArrowUpActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Up);
|
||||
} else if (action.actionTypeId() == lgSmartTvNavigateActionTypeId) {
|
||||
TvDevice::RemoteKey key;
|
||||
QString navigateTo = action.paramValue(lgSmartTvNavigateActionToParamTypeId).toString();
|
||||
if (navigateTo == "up") {
|
||||
key = TvDevice::Up;
|
||||
} else if (navigateTo == "down") {
|
||||
key = TvDevice::Down;
|
||||
} else if (navigateTo == "left") {
|
||||
key = TvDevice::Left;
|
||||
} else if (navigateTo == "right") {
|
||||
key = TvDevice::Right;
|
||||
} else if (navigateTo == "enter") {
|
||||
key = TvDevice::Ok;
|
||||
} else if (navigateTo == "back") {
|
||||
key = TvDevice::Back;
|
||||
} else if (navigateTo == "menu") {
|
||||
key = TvDevice::Menu;
|
||||
} else if (navigateTo == "info") {
|
||||
key = TvDevice::Info;
|
||||
} else if (navigateTo == "home") {
|
||||
key = TvDevice::Home;
|
||||
}
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(key);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandArrowDownActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Down);
|
||||
} else if (action.actionTypeId() == lgSmartTvPlayActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Play);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandArrowLeftActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Left);
|
||||
} else if (action.actionTypeId() == lgSmartTvPauseActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Pause);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandArrowRightActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Right);
|
||||
} else if (action.actionTypeId() == lgSmartTvStopActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Stop);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandOkActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Ok);
|
||||
} else if (action.actionTypeId() == lgSmartTvSkipNextActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::SkipForward);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandBackActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Back);
|
||||
} else if (action.actionTypeId() == lgSmartTvSkipBackActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::SkipBackward);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandHomeActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Home);
|
||||
} else if (action.actionTypeId() == lgSmartTvFastForwardActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::FastForward);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandInputSourceActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvFastRewindActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Rewind);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if (action.actionTypeId() == lgSmartTvCommandInputSourceActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ExternalInput);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandExitActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvCommandExitActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Exit);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandInfoActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::Info);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandMyAppsActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvCommandMyAppsActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::MyApps);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
} else if(action.actionTypeId() == lgSmartTvCommandProgramListActionTypeId) {
|
||||
} else if (action.actionTypeId() == lgSmartTvCommandProgramListActionTypeId) {
|
||||
QPair<QNetworkRequest, QByteArray> request = tvDevice->createPressButtonRequest(TvDevice::ProgramList);
|
||||
reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
}
|
||||
@ -347,61 +361,268 @@ void IntegrationPluginLgSmartTv::executeAction(ThingActionInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::browseThing(BrowseResult *result)
|
||||
{
|
||||
if (result->thing()->thingClassId() == lgSmartTvThingClassId) {
|
||||
TvDevice *tv = m_tvList.key(result->thing());
|
||||
if (!tv) {
|
||||
result->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
tv->browse(result);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::browserItem(BrowserItemResult *result)
|
||||
{
|
||||
if (result->thing()->thingClassId() == lgSmartTvThingClassId) {
|
||||
TvDevice *tv = m_tvList.key(result->thing());
|
||||
if (!tv) {
|
||||
result->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
tv->browserItem(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IntegrationPluginLgSmartTv::pairTvDevice(Thing *thing)
|
||||
{
|
||||
qCDebug(dcLgSmartTv()) << "Send pair request TV" << thing->name();
|
||||
QHostAddress host = QHostAddress(thing->paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
int port = thing->paramValue(lgSmartTvThingPortParamTypeId).toInt();
|
||||
if (thing->thingClassId() == lgSmartTvThingClassId) {
|
||||
qCDebug(dcLgSmartTv()) << "Send pair request TV" << thing->name();
|
||||
QHostAddress host = QHostAddress(thing->paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
quint16 port = thing->paramValue(lgSmartTvThingPortParamTypeId).toUInt();
|
||||
quint16 eventHandlerPort = thing->paramValue(lgSmartTvThingEventHandlerPortParamTypeId).toUInt();
|
||||
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
QString key = pluginStorage()->value("key").toString();
|
||||
pluginStorage()->endGroup();
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
QString key = pluginStorage()->value("key").toString();
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, key);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, thing, [this, thing, reply]() {
|
||||
TvDevice *tv = m_tvList.key(thing);
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "Pair TV request error:" << status << reply->errorString();
|
||||
tv->setPaired(false);
|
||||
} else {
|
||||
qCDebug(dcLgSmartTv) << "Paired TV successfully.";
|
||||
tv->setPaired(true);
|
||||
refreshTv(thing);
|
||||
}
|
||||
});
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createPairingRequest(host, port, eventHandlerPort, key);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, thing, [this, thing, reply]() {
|
||||
TvDevice *tv = m_tvList.key(thing);
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "Pair TV request error:" << status << reply->errorString();
|
||||
tv->setPaired(false);
|
||||
} else {
|
||||
qCDebug(dcLgSmartTv) << "Paired TV successfully.";
|
||||
tv->setPaired(true);
|
||||
loadAppList(thing);
|
||||
|
||||
refreshTv(thing);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::unpairTvDevice(Thing *thing)
|
||||
{
|
||||
QHostAddress host = QHostAddress(thing->paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
int port = thing->paramValue(lgSmartTvThingPortParamTypeId).toInt();
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(host, port);
|
||||
if (thing->thingClassId() == lgSmartTvThingClassId) {
|
||||
QHostAddress host = QHostAddress(thing->paramValue(lgSmartTvThingHostAddressParamTypeId).toString());
|
||||
quint16 port = thing->paramValue(lgSmartTvThingPortParamTypeId).toUInt();
|
||||
quint16 eventHandlerPort = thing->paramValue(lgSmartTvThingEventHandlerPortParamTypeId).toUInt();
|
||||
QPair<QNetworkRequest, QByteArray> request = TvDevice::createEndPairingRequest(host, port, eventHandlerPort);
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
|
||||
connect(reply, &QNetworkReply::finished, this, [reply](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "End pairing TV (thing deleted) request error:" << status << reply->errorString();
|
||||
} else {
|
||||
qCDebug(dcLgSmartTv) << "End pairing TV (thing deleted) successfully.";
|
||||
}
|
||||
});
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(status != 200) {
|
||||
qCWarning(dcLgSmartTv) << "End pairing TV (thing deleted) request error:" << status << reply->errorString();
|
||||
} else {
|
||||
qCDebug(dcLgSmartTv) << "End pairing TV (thing deleted) successfully.";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::refreshTv(Thing *thing)
|
||||
{
|
||||
TvDevice *tv = m_tvList.key(thing);
|
||||
// check volume information
|
||||
QNetworkReply *volumeReply = hardwareManager()->networkManager()->get(tv->createVolumeInformationRequest());
|
||||
connect(volumeReply, &QNetworkReply::finished, this, &IntegrationPluginLgSmartTv::onNetworkManagerReplyFinished);
|
||||
m_volumeInfoRequests.insert(volumeReply, thing);
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(tv->createVolumeInformationRequest());
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [=](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (status != 200) {
|
||||
tv->setReachable(false);
|
||||
qCWarning(dcLgSmartTv) << "Refresh tv information request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tv->reachable()) {
|
||||
loadAppList(thing);
|
||||
}
|
||||
tv->setReachable(true);
|
||||
tv->onVolumeInformationUpdate(reply->readAll());
|
||||
|
||||
// QByteArray data = reply->readAll();
|
||||
// qCDebug(dcLgSmartTv()) << "Refresh info received:" << data << qUtf8Printable(TvDevice::printXmlData(data));
|
||||
|
||||
|
||||
// QNetworkReply *reply = hardwareManager()->networkManager()->get(tv->createAppListRequest());
|
||||
// connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
// connect(reply, &QNetworkReply::finished, this, [reply, tv](){
|
||||
// int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
// if (status != 200) {
|
||||
// tv->setReachable(false);
|
||||
// qCWarning(dcLgSmartTv) << "Refresh tv information request error:" << status << reply->errorString();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// tv->setReachable(true);
|
||||
// QByteArray data = reply->readAll();
|
||||
// qCDebug(dcLgSmartTv()) << "Refresh info received:" << data << qUtf8Printable(TvDevice::printXmlData(data));
|
||||
|
||||
|
||||
// tv->setReachable(true);
|
||||
// tv->onVolumeInformationUpdate(reply->readAll());
|
||||
|
||||
// // Check channel information
|
||||
// QNetworkReply *channelReply = hardwareManager()->networkManager()->get(tv->createChannelInformationRequest());
|
||||
// connect(channelReply, &QNetworkReply::finished, this, &IntegrationPluginLgSmartTv::onNetworkManagerReplyFinished);
|
||||
// m_channelInfoRequests.insert(channelReply, thing);
|
||||
// });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::loadAppList(Thing *thing)
|
||||
{
|
||||
TvDevice *tv = m_tvList.key(thing);
|
||||
tv->clearAppList();
|
||||
|
||||
// Note:: loading all apps (type 1) does not work, so load type 2 (premium) and typ 3 (myApps) sequentially
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(tv->createAppListCountRequest(2));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [=](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (status != 200) {
|
||||
tv->setReachable(false);
|
||||
qCWarning(dcLgSmartTv) << "Get app count request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
tv->setReachable(true);
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
int appCount = 0;
|
||||
QXmlStreamReader xml(data);
|
||||
while (!xml.atEnd() && !xml.hasError()) {
|
||||
xml.readNext();
|
||||
if (xml.name() == "number") {
|
||||
appCount = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(tv->createAppListRequest(2, appCount));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [=](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (status != 200) {
|
||||
tv->setReachable(false);
|
||||
qCWarning(dcLgSmartTv) << "Get app list request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
// Parse app list
|
||||
QVariantList appList;
|
||||
QXmlStreamReader xml(qUtf8Printable(QString::fromLatin1(data)));
|
||||
while (xml.readNextStartElement() && !xml.atEnd()) {
|
||||
if (xml.name() == "dataList") {
|
||||
while (xml.readNextStartElement()) {
|
||||
QVariantMap appMap;
|
||||
if (xml.name() == "data") {
|
||||
qCDebug(dcLgSmartTv()) << "--------------------";
|
||||
while (xml.readNextStartElement()) {
|
||||
qCDebug(dcLgSmartTv()) << "-->" << xml.name() << xml.readElementText();
|
||||
if (xml.name() == "name") {
|
||||
appMap.insert("name", xml.readElementText());
|
||||
} else if (xml.name() == "icon") {
|
||||
appMap.insert("icon", xml.readElementText());
|
||||
} if (xml.name() == "cpid") {
|
||||
appMap.insert("cpid", xml.readElementText());
|
||||
}
|
||||
}
|
||||
}
|
||||
appList.append(appMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(dcLgSmartTv()) << "Adding app list" << appList;
|
||||
tv->addAppList(appList);
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(tv->createAppListCountRequest(3));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [=](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (status != 200) {
|
||||
tv->setReachable(false);
|
||||
qCWarning(dcLgSmartTv) << "Get app count request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
int appCount = 0;
|
||||
QXmlStreamReader xml(data);
|
||||
while (!xml.atEnd() && !xml.hasError()) {
|
||||
xml.readNext();
|
||||
if (xml.name() == "number") {
|
||||
appCount = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
QNetworkReply *reply = hardwareManager()->networkManager()->get(tv->createAppListRequest(3, appCount));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, tv](){
|
||||
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (status != 200) {
|
||||
tv->setReachable(false);
|
||||
qCWarning(dcLgSmartTv) << "Refresh tv information request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
// Parse app list
|
||||
QVariantList appList;
|
||||
QXmlStreamReader xml(QString::fromLatin1(data));
|
||||
while (xml.readNextStartElement() && !xml.atEnd()) {
|
||||
if (xml.name() == "dataList") {
|
||||
while (xml.readNextStartElement()) {
|
||||
if (xml.name() == "data") {
|
||||
QVariantMap appMap;
|
||||
while (xml.readNextStartElement()) {
|
||||
if (xml.name() == "name") {
|
||||
appMap.insert("name", xml.readElementText());
|
||||
} else if (xml.name() == "icon") {
|
||||
appMap.insert("icon", xml.readElementText());
|
||||
} if (xml.name() == "auid") {
|
||||
appMap.insert("auid", xml.readElementText());
|
||||
}
|
||||
}
|
||||
qCDebug(dcLgSmartTv()) << appMap;
|
||||
appList.append(appMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(dcLgSmartTv()) << "Adding app list" << appList;
|
||||
tv->addAppList(appList);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginLgSmartTv::onPluginTimer()
|
||||
@ -426,7 +647,7 @@ void IntegrationPluginLgSmartTv::onNetworkManagerReplyFinished()
|
||||
if (m_volumeInfoRequests.keys().contains(reply)) {
|
||||
Thing *thing = m_volumeInfoRequests.take(reply);
|
||||
TvDevice *tv = m_tvList.key(thing);
|
||||
if(status != 200) {
|
||||
if (status != 200) {
|
||||
tv->setReachable(false);
|
||||
qCWarning(dcLgSmartTv) << "Volume information request error:" << status << reply->errorString();
|
||||
if (status == 401) {
|
||||
@ -445,7 +666,7 @@ void IntegrationPluginLgSmartTv::onNetworkManagerReplyFinished()
|
||||
} else if (m_channelInfoRequests.keys().contains(reply)) {
|
||||
Thing *thing = m_channelInfoRequests.take(reply);
|
||||
TvDevice *tv = m_tvList.key(thing);
|
||||
if(status != 200) {
|
||||
if (status != 200) {
|
||||
tv->setReachable(false);
|
||||
qCWarning(dcLgSmartTv) << "Channel information request error:" << status << reply->errorString();
|
||||
if (status == 401) {
|
||||
@ -466,8 +687,8 @@ void IntegrationPluginLgSmartTv::stateChanged()
|
||||
|
||||
thing->setStateValue(lgSmartTvConnectedStateTypeId, tvDevice->reachable());
|
||||
thing->setStateValue(lgSmartTvTv3DModeStateTypeId, tvDevice->is3DMode());
|
||||
thing->setStateValue(lgSmartTvTvVolumeLevelStateTypeId, tvDevice->volumeLevel());
|
||||
thing->setStateValue(lgSmartTvTvMuteStateTypeId, tvDevice->mute());
|
||||
thing->setStateValue(lgSmartTvVolumeLevelStateTypeId, tvDevice->volumeLevel());
|
||||
thing->setStateValue(lgSmartTvMuteStateTypeId, tvDevice->mute());
|
||||
thing->setStateValue(lgSmartTvTvChannelTypeStateTypeId, tvDevice->channelType());
|
||||
thing->setStateValue(lgSmartTvTvChannelNameStateTypeId, tvDevice->channelName());
|
||||
thing->setStateValue(lgSmartTvTvChannelNumberStateTypeId, tvDevice->channelNumber());
|
||||
|
||||
@ -61,6 +61,9 @@ public:
|
||||
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
void browseThing(BrowseResult *result) override;
|
||||
void browserItem(BrowserItemResult *result) override;
|
||||
|
||||
private:
|
||||
PluginTimer *m_pluginTimer = nullptr;
|
||||
QHash<TvDevice *, Thing *> m_tvList;
|
||||
@ -76,6 +79,8 @@ private:
|
||||
void unpairTvDevice(Thing *thing);
|
||||
void refreshTv(Thing *thing);
|
||||
|
||||
void loadAppList(Thing *thing);
|
||||
|
||||
private slots:
|
||||
void onPluginTimer();
|
||||
void onNetworkManagerReplyFinished();
|
||||
|
||||
@ -14,41 +14,51 @@
|
||||
"displayName": "LG Smart Tv",
|
||||
"createMethods": [ "discovery" ],
|
||||
"setupMethod": "displayPin",
|
||||
"interfaces": ["connectable"],
|
||||
"browsable": true,
|
||||
"interfaces": ["mediacontroller", "navigationpad", "volumecontroller", "connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "797a1915-cb85-400a-9c1a-db09c73b54d5",
|
||||
"name": "name",
|
||||
"displayName": "name",
|
||||
"displayName": "Name",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine"
|
||||
},
|
||||
{
|
||||
"id": "0deec372-b955-49d2-9906-fc1a603dd637",
|
||||
"name": "model",
|
||||
"displayName": "model",
|
||||
"displayName": "Model",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine"
|
||||
},
|
||||
{
|
||||
"id": "0af152bb-8844-44d8-afee-d08bb0e28558",
|
||||
"name": "uuid",
|
||||
"displayName": "uuid",
|
||||
"displayName": "UUID",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine"
|
||||
},
|
||||
{
|
||||
"id": "9710c07c-0725-4099-bf73-2513efbc0872",
|
||||
"name": "hostAddress",
|
||||
"displayName": "host address",
|
||||
"displayName": "Host address",
|
||||
"type": "QString",
|
||||
"inputType": "IPv4Address"
|
||||
"inputType": "IPv4Address",
|
||||
"defaultValue": "127.0.0.1"
|
||||
},
|
||||
{
|
||||
"id": "442abce0-16f9-4628-9534-e98e7f1c0a51",
|
||||
"name": "port",
|
||||
"displayName": "port",
|
||||
"type": "int"
|
||||
"displayName": "Port",
|
||||
"type": "uint",
|
||||
"defaultValue": 8080
|
||||
},
|
||||
{
|
||||
"id": "2904dc2d-d734-4893-ab69-222cd7a5d147",
|
||||
"name": "eventHandlerPort",
|
||||
"displayName": "Event handler port",
|
||||
"type": "uint",
|
||||
"defaultValue": 9000
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
@ -69,21 +79,24 @@
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "07d39a6e-7eab-42d0-851d-9f3bcd3bbb57",
|
||||
"name": "tvVolumeLevel",
|
||||
"displayName": "volume",
|
||||
"displayNameEvent": "Volume changed",
|
||||
"type": "int",
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 0
|
||||
"id": "e1ead9b0-2db5-41bd-aedb-b78a99235dde",
|
||||
"name": "mute",
|
||||
"displayName": "Mute",
|
||||
"displayNameEvent": "Mute changed",
|
||||
"displayNameAction": "Set mute",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "a6ac9061-3de7-403a-a646-790ca5d73764",
|
||||
"name": "tvMute",
|
||||
"displayNameEvent": "mute changed",
|
||||
"displayName": "mute",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
"id": "597f9e07-108e-4345-80ab-1842bcb40666",
|
||||
"displayName": "Volume",
|
||||
"displayNameEvent": "Volume changed",
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"name": "volumeLevel",
|
||||
"type": "int",
|
||||
"defaultValue": 10
|
||||
},
|
||||
{
|
||||
"id": "84c86670-77c7-4fc6-9e23-abca066e76aa",
|
||||
@ -137,73 +150,87 @@
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "ac5d7dcd-dfe8-4a94-9ab9-21b3f804b39e",
|
||||
"name": "commandVolumeUp",
|
||||
"displayName": "volume up"
|
||||
"name": "increaseVolume",
|
||||
"displayName": "Volume +"
|
||||
},
|
||||
{
|
||||
"id": "62b17bec-f461-4ffa-93d1-67a9430d55e1",
|
||||
"name": "commandVolumeDown",
|
||||
"displayName": "volume down"
|
||||
},
|
||||
{
|
||||
"id": "1aa9d7f0-0f66-4b90-bb72-f6b7b2118221",
|
||||
"name": "commandMute",
|
||||
"displayName": "mute"
|
||||
},
|
||||
{
|
||||
"id": "b7e31999-ba67-443d-8e5c-ec104af987bd",
|
||||
"name": "commandUnmute",
|
||||
"displayName": "unmute"
|
||||
"name": "decreaseVolume",
|
||||
"displayName": "Volume -"
|
||||
},
|
||||
{
|
||||
"id": "acd1f6a0-2cfa-4665-9607-cf94245ec5a3",
|
||||
"name": "commandChannelUp",
|
||||
"displayName": "channel up"
|
||||
"displayName": "Channel up"
|
||||
},
|
||||
{
|
||||
"id": "6ea66772-0e6d-40b1-978c-a01fb53871dd",
|
||||
"name": "commandChannelDown",
|
||||
"displayName": "channel down"
|
||||
"displayName": "Channel down"
|
||||
},
|
||||
{
|
||||
"id": "cbe41134-ff11-4916-815b-3ac289c64090",
|
||||
"name": "commandPowerOff",
|
||||
"displayName": "power off"
|
||||
"displayName": "Power off"
|
||||
},
|
||||
{
|
||||
"id": "57c483b4-4ddf-4470-828c-8d8767e7a923",
|
||||
"name": "commandArrowUp",
|
||||
"displayName": "arrow up"
|
||||
"id": "193f80bf-3c9a-47a4-b54e-7cecf0bf0f45",
|
||||
"name": "navigate",
|
||||
"displayName": "Navigate",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "93861dac-0c24-4a3b-903d-d1be44eae611",
|
||||
"name": "to",
|
||||
"displayName": "to",
|
||||
"type": "QString",
|
||||
"allowedValues": [
|
||||
"up",
|
||||
"down",
|
||||
"left",
|
||||
"right",
|
||||
"enter",
|
||||
"back",
|
||||
"menu",
|
||||
"info",
|
||||
"home"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "614cf1af-5cf7-4bb2-885c-4414078d8899",
|
||||
"name": "commandArrowDown",
|
||||
"displayName": "arrow down"
|
||||
"id": "2c1e07e1-198a-45f4-9c58-2c5e31290262",
|
||||
"name": "skipBack",
|
||||
"displayName": "skip back"
|
||||
},
|
||||
{
|
||||
"id": "916394dd-7833-4875-8d7a-49d7d24ceeb2",
|
||||
"name": "commandArrowLeft",
|
||||
"displayName": "arrow left"
|
||||
"id": "db984804-acad-4905-bc89-9ebcdf64478e",
|
||||
"name": "fastRewind",
|
||||
"displayName": "rewind"
|
||||
},
|
||||
{
|
||||
"id": "01e3df1e-638b-4e14-ba85-660267766062",
|
||||
"name": "commandArrowRight",
|
||||
"displayName": "arrow right"
|
||||
"id": "590c0f43-be86-4692-9b89-13730e71bed4",
|
||||
"name": "stop",
|
||||
"displayName": "stop"
|
||||
},
|
||||
{
|
||||
"id": "257dfa59-0d38-4e18-a3fc-213809fdb12f",
|
||||
"name": "commandOk",
|
||||
"displayName": "OK"
|
||||
"id": "17f5c9d4-e060-4daa-a039-3cd7eb6ef8bf",
|
||||
"name": "play",
|
||||
"displayName": "play"
|
||||
},
|
||||
{
|
||||
"id": "ce4184b3-6b8e-4fc3-a4cb-7b8ec72f2ce9",
|
||||
"name": "commandBack",
|
||||
"displayName": "back"
|
||||
"id": "6360fe9e-00c6-4d32-bcfc-69b5b5d85f8b",
|
||||
"name": "pause",
|
||||
"displayName": "pause"
|
||||
},
|
||||
{
|
||||
"id": "33f941c1-f5fc-4449-b6e3-93eafca493e0",
|
||||
"name": "commandHome",
|
||||
"displayName": "home"
|
||||
"id": "48c7afb6-8252-4c11-aff9-e4e4954b2d30",
|
||||
"name": "fastForward",
|
||||
"displayName": "fastForward"
|
||||
},
|
||||
{
|
||||
"id": "353ad30a-25b7-4ae9-b47b-057bf101f8d1",
|
||||
"name": "skipNext",
|
||||
"displayName": "skipNext"
|
||||
},
|
||||
{
|
||||
"id": "9a6e5111-95d3-49ac-8056-249e704b1509",
|
||||
@ -215,11 +242,6 @@
|
||||
"name": "commandExit",
|
||||
"displayName": "exit"
|
||||
},
|
||||
{
|
||||
"id": "9c1290d5-3135-4124-a576-fc7522cffdcf",
|
||||
"name": "commandInfo",
|
||||
"displayName": "info"
|
||||
},
|
||||
{
|
||||
"id": "47d65cac-fe75-4c36-9dee-9862c1c1130e",
|
||||
"name": "commandMyApps",
|
||||
@ -238,7 +260,7 @@
|
||||
"displayName": "LG WebOS Smart Tv",
|
||||
"createMethods": [ "Discovery" ],
|
||||
"setupMethod": "PushButton",
|
||||
"interfaces": [ "extendedvolumecontroller", "mediacontroller", "connectable" ],
|
||||
"interfaces": [ "volumecontroller", "mediacontroller", "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "adebba0c-ac7b-4b6a-8668-307f44dbe5bf",
|
||||
@ -288,6 +310,16 @@
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "ff814f79-5c79-4346-94fa-4da1a6f95c82",
|
||||
"displayName": "Volume +",
|
||||
"name": "increaseVolume"
|
||||
},
|
||||
{
|
||||
"id": "360326c4-c6c3-4304-b539-aca08f711c8a",
|
||||
"displayName": "Volume -",
|
||||
"name": "decreaseVolume"
|
||||
},
|
||||
{
|
||||
"id": "35cdb587-956a-4310-8e4c-85fdc240943e",
|
||||
"displayName": "Skip back",
|
||||
|
||||
@ -31,20 +31,32 @@
|
||||
#include "tvdevice.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
TvDevice::TvDevice(const QHostAddress &hostAddress, const int &port, QObject *parent) :
|
||||
TvDevice::TvDevice(const QHostAddress &hostAddress, quint16 port, quint16 eventHandlerPort, 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_eventHandlerPort(eventHandlerPort)
|
||||
{
|
||||
m_eventHandler = new TvEventHandler(hostAddress, port, this);
|
||||
m_eventHandler = new TvEventHandler(hostAddress, eventHandlerPort, this);
|
||||
connect(m_eventHandler, &TvEventHandler::eventOccured, this, &TvDevice::eventOccured);
|
||||
|
||||
// Init FS
|
||||
m_virtualFs = new VirtualFsNode(BrowserItem());
|
||||
|
||||
// Apps
|
||||
BrowserItem item = BrowserItem("apps", tr("Apps"), true);
|
||||
item.setDescription(tr(""));
|
||||
item.setIcon(BrowserItem::BrowserIconApplication);
|
||||
VirtualFsNode *apps = new VirtualFsNode(item);
|
||||
m_virtualFs->addChild(apps);
|
||||
|
||||
// Channels
|
||||
item = BrowserItem("channels", tr("Channels"), true);
|
||||
item.setDescription(tr(""));
|
||||
item.setIcon(BrowserItem::BrowserIconVideo);
|
||||
VirtualFsNode *channels = new VirtualFsNode(item);
|
||||
m_virtualFs->addChild(channels);
|
||||
|
||||
}
|
||||
|
||||
void TvDevice::setKey(const QString &key)
|
||||
@ -57,26 +69,21 @@ QString TvDevice::key() const
|
||||
return m_key;
|
||||
}
|
||||
|
||||
void TvDevice::setHostAddress(const QHostAddress &hostAddress)
|
||||
{
|
||||
m_hostAddress = hostAddress;
|
||||
}
|
||||
|
||||
QHostAddress TvDevice::hostAddress() const
|
||||
{
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
void TvDevice::setPort(const int &port)
|
||||
{
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
int TvDevice::port() const
|
||||
quint16 TvDevice::port() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
quint16 TvDevice::eventHandlerPort() const
|
||||
{
|
||||
return m_eventHandlerPort;
|
||||
}
|
||||
|
||||
void TvDevice::setUuid(const QString &uuid)
|
||||
{
|
||||
m_uuid = uuid;
|
||||
@ -91,7 +98,7 @@ void TvDevice::setPaired(const bool &paired)
|
||||
{
|
||||
if (m_paired != paired) {
|
||||
m_paired = paired;
|
||||
stateChanged();
|
||||
emit stateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,7 +166,7 @@ QString TvDevice::inputSourceLabelName() const
|
||||
return m_inputSourceLabel;
|
||||
}
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createDisplayKeyRequest(const QHostAddress &host, const int &port)
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createDisplayKeyRequest(const QHostAddress &host, quint16 port)
|
||||
{
|
||||
QString urlString = "http://" + host.toString() + ":" + QString::number(port) + "/udap/api/pairing";
|
||||
QNetworkRequest request;
|
||||
@ -171,7 +178,7 @@ QPair<QNetworkRequest, QByteArray> TvDevice::createDisplayKeyRequest(const QHost
|
||||
return QPair<QNetworkRequest, QByteArray>(request, data);
|
||||
}
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createPairingRequest(const QHostAddress &host, const int &port, const QString &key)
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createPairingRequest(const QHostAddress &host, quint16 port, quint16 eventHandlerPort, const QString &key)
|
||||
{
|
||||
QString urlString = "http://" + host.toString() + ":" + QString::number(port) + "/udap/api/pairing";
|
||||
QNetworkRequest request;
|
||||
@ -179,23 +186,12 @@ QPair<QNetworkRequest, QByteArray> TvDevice::createPairingRequest(const QHostAdd
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0 nymea"));
|
||||
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>hello</name><value>" + key.toUtf8() + "</value><port>8080</port></api></envelope>";
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>hello</name><value>" +
|
||||
key.toUtf8() + "</value><port>" + QByteArray::number(eventHandlerPort) + "</port></api></envelope>";
|
||||
return QPair<QNetworkRequest, QByteArray>(request, data);
|
||||
}
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createEndPairingRequest(const QUrl &url)
|
||||
{
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0 nymea"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>byebye</name><port>8080</port></api></envelope>";
|
||||
return QPair<QNetworkRequest, QByteArray>(request, data);
|
||||
}
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createEndPairingRequest(const QHostAddress &host, const int &port)
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createEndPairingRequest(const QHostAddress &host, quint16 port, quint16 eventHandlerPort)
|
||||
{
|
||||
QString urlString = "http://" + host.toString() + ":" + QString::number(port) + "/udap/api/pairing";
|
||||
QNetworkRequest request;
|
||||
@ -204,11 +200,11 @@ QPair<QNetworkRequest, QByteArray> TvDevice::createEndPairingRequest(const QHost
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0 nymea"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>byebye</name><port>8080</port></api></envelope>";
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"><name>byebye</name><port>" + QByteArray::number(eventHandlerPort) + "</port></api></envelope>";
|
||||
return QPair<QNetworkRequest, QByteArray>(request, data);
|
||||
}
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createEventRequest(const QHostAddress &host, const int &port)
|
||||
QPair<QNetworkRequest, QByteArray> TvDevice::createEventRequest(const QHostAddress &host, quint16 port, quint16 eventHandlerPort)
|
||||
{
|
||||
QString urlString = "http://" + host.toString() + ":" + QString::number(port) + "/udap/api/event";
|
||||
QNetworkRequest request;
|
||||
@ -217,16 +213,54 @@ QPair<QNetworkRequest, QByteArray> TvDevice::createEventRequest(const QHostAddre
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0 nymea"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"event\"><name>byebye</name><port>8080</port></api></envelope>";
|
||||
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"event\"><name>byebye</name><port>" + QByteArray::number(eventHandlerPort) + "</port></api></envelope>";
|
||||
return QPair<QNetworkRequest, QByteArray>(request, data);
|
||||
}
|
||||
|
||||
QUrl TvDevice::buildDisplayImageUrl() const
|
||||
{
|
||||
return QUrl("http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/data?target=screen_image");
|
||||
}
|
||||
|
||||
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::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
return request;
|
||||
}
|
||||
|
||||
QNetworkRequest TvDevice::createChannelListRequest()
|
||||
{
|
||||
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/data?target=channel_list";
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
return request;
|
||||
}
|
||||
|
||||
QNetworkRequest TvDevice::createAppListCountRequest(int type)
|
||||
{
|
||||
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/data?target=appnum_get&type=" + QString::number(type);
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
return request;
|
||||
}
|
||||
|
||||
QNetworkRequest TvDevice::createAppListRequest(int type, int appCount)
|
||||
{
|
||||
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/data?target=applist_get&type=" + QString::number(type) + "&index=1&number=" + QString::number(appCount);
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
return request;
|
||||
@ -237,7 +271,7 @@ QNetworkRequest TvDevice::createChannelInformationRequest()
|
||||
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/data?target=cur_channel";
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(urlString));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
|
||||
request.setRawHeader("Connection", "Close");
|
||||
return request;
|
||||
@ -262,13 +296,13 @@ void TvDevice::onVolumeInformationUpdate(const QByteArray &data)
|
||||
{
|
||||
//qCDebug(dcLgSmartTv()) << printXmlData(data);
|
||||
QXmlStreamReader xml(data);
|
||||
while(!xml.atEnd() && !xml.hasError()) {
|
||||
while (!xml.atEnd() && !xml.hasError()) {
|
||||
xml.readNext();
|
||||
|
||||
if(xml.name() == "mute") {
|
||||
if (xml.name() == "mute") {
|
||||
m_mute = QVariant(xml.readElementText()).toBool();
|
||||
}
|
||||
if(xml.name() == "level") {
|
||||
if (xml.name() == "level") {
|
||||
m_volumeLevel = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
}
|
||||
@ -280,56 +314,121 @@ void TvDevice::onChannelInformationUpdate(const QByteArray &data)
|
||||
//qCDebug(dcLgSmartTv()) << printXmlData(data);
|
||||
QXmlStreamReader xml(data);
|
||||
|
||||
while(!xml.atEnd() && !xml.hasError()) {
|
||||
while (!xml.atEnd() && !xml.hasError()) {
|
||||
xml.readNext();
|
||||
|
||||
if(xml.name() == "chtype") {
|
||||
if (xml.name() == "chtype") {
|
||||
m_channelType = xml.readElementText();
|
||||
}
|
||||
if(xml.name() == "major") {
|
||||
if (xml.name() == "major") {
|
||||
m_channelNumber = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
if(xml.name() == "chname") {
|
||||
if (xml.name() == "chname") {
|
||||
m_channelName = xml.readElementText();
|
||||
}
|
||||
if(xml.name() == "progName") {
|
||||
if (xml.name() == "progName") {
|
||||
m_programName = xml.readElementText();
|
||||
}
|
||||
if(xml.name() == "inputSourceIdx") {
|
||||
if (xml.name() == "inputSourceIdx") {
|
||||
m_inputSourceIndex = QVariant(xml.readElementText()).toInt();
|
||||
}
|
||||
if(xml.name() == "labelName") {
|
||||
if (xml.name() == "labelName") {
|
||||
m_inputSourceLabel = xml.readElementText();
|
||||
}
|
||||
}
|
||||
emit stateChanged();
|
||||
}
|
||||
|
||||
void TvDevice::onAppListUpdated(const QByteArray &appList)
|
||||
{
|
||||
Q_UNUSED(appList)
|
||||
}
|
||||
|
||||
QString TvDevice::printXmlData(const 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()) {
|
||||
qCWarning(dcLgSmartTv()) << "error reading XML thing information:" << reader.errorString();
|
||||
if (reader.hasError()) {
|
||||
qCWarning(dcLgSmartTv()) << "Error reading XML thing information:" << reader.errorString();
|
||||
}
|
||||
return xmlOut;
|
||||
}
|
||||
|
||||
void TvDevice::browse(BrowseResult *result)
|
||||
{
|
||||
qCDebug(dcLgSmartTv()) << "Browse" << result->itemId();
|
||||
VirtualFsNode *node = m_virtualFs->findNode(result->itemId());
|
||||
if (node) {
|
||||
if (result->itemId().isEmpty()) {
|
||||
foreach (VirtualFsNode *child, node->childs) {
|
||||
result->addItem(child->item);
|
||||
}
|
||||
result->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result->itemId().startsWith("apps")) {
|
||||
qCDebug(dcLgSmartTv()) << m_appList;
|
||||
// Build the app list
|
||||
foreach (const QVariant &appVariant, m_appList) {
|
||||
QVariantMap appMap = appVariant.toMap();
|
||||
qCDebug(dcLgSmartTv()) << "Entry:" << appMap;
|
||||
BrowserItem item("apps:" + appMap.value("name").toString(), appMap.value("name").toString());
|
||||
item.setExecutable(true);
|
||||
item.setIcon(BrowserItem::BrowserIconApplication);
|
||||
result->addItem(item);
|
||||
}
|
||||
result->finish(Thing::ThingErrorNoError);
|
||||
|
||||
} else if (result->itemId().startsWith("channels")) {
|
||||
// Build the channel list
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TvDevice::browserItem(BrowserItemResult *result)
|
||||
{
|
||||
qCDebug(dcLgSmartTv()) << "Browse item" << result->itemId();
|
||||
|
||||
}
|
||||
|
||||
int TvDevice::launchBrowserItem(const QString &itemId)
|
||||
{
|
||||
qCDebug(dcLgSmartTv()) << "Launch browse item" << itemId;
|
||||
|
||||
// TODO: switch channel or launch app
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TvDevice::clearAppList()
|
||||
{
|
||||
m_appList.clear();
|
||||
}
|
||||
|
||||
void TvDevice::addAppList(const QVariantList &appList)
|
||||
{
|
||||
foreach (const QVariant &appVariant, appList) {
|
||||
m_appList.append(appVariant);
|
||||
}
|
||||
}
|
||||
|
||||
void TvDevice::eventOccured(const QByteArray &data)
|
||||
{
|
||||
qCDebug(dcLgSmartTv()) << "Event handler data received" << printXmlData(data);
|
||||
qCDebug(dcLgSmartTv()) << "Event handler data received" << qUtf8Printable(printXmlData(data));
|
||||
|
||||
// if we got a channel changed event...
|
||||
if(data.contains("ChannelChanged")) {
|
||||
if (data.contains("ChannelChanged")) {
|
||||
onChannelInformationUpdate(data);
|
||||
return;
|
||||
}
|
||||
@ -338,7 +437,7 @@ void TvDevice::eventOccured(const QByteArray &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")) {
|
||||
if (data.contains("api type=\"pairing\"") && data.contains("byebye")) {
|
||||
qCDebug(dcLgSmartTv()) << "Ended pairing (host)";
|
||||
setPaired(false);
|
||||
setReachable(false);
|
||||
@ -347,14 +446,12 @@ void TvDevice::eventOccured(const QByteArray &data)
|
||||
|
||||
// check if this is a 3DMode changed event
|
||||
QXmlStreamReader xml(data);
|
||||
|
||||
while(!xml.atEnd() && !xml.hasError()) {
|
||||
while (!xml.atEnd() && !xml.hasError()) {
|
||||
xml.readNext();
|
||||
|
||||
if(xml.name() == "name") {
|
||||
if(xml.readElementText() == "3DMode") {
|
||||
if (xml.name() == "name") {
|
||||
if (xml.readElementText() == "3DMode") {
|
||||
xml.readNext();
|
||||
if(xml.name() == "value") {
|
||||
if (xml.name() == "value") {
|
||||
m_is3DMode = QVariant(xml.readElementText()).toBool();
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ class TvDevice : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TvDevice(const QHostAddress &hostAddress, const int &port, QObject *parent = 0);
|
||||
explicit TvDevice(const QHostAddress &hostAddress, quint16 port, quint16 eventHandlerPort, QObject *parent = 0);
|
||||
|
||||
enum RemoteKey{
|
||||
Power = 1,
|
||||
@ -125,11 +125,9 @@ public:
|
||||
void setKey(const QString &key);
|
||||
QString key() const;
|
||||
|
||||
void setHostAddress(const QHostAddress &hostAddress);
|
||||
QHostAddress hostAddress() const;
|
||||
|
||||
void setPort(const int &port);
|
||||
int port() const;
|
||||
quint16 port() const;
|
||||
quint16 eventHandlerPort() const;
|
||||
|
||||
void setUuid(const QString &uuid);
|
||||
QString uuid() const;
|
||||
@ -152,41 +150,78 @@ public:
|
||||
QString inputSourceLabelName() const;
|
||||
|
||||
// other methods
|
||||
static QPair<QNetworkRequest, QByteArray> createDisplayKeyRequest(const QHostAddress &host, const int &port);
|
||||
static QPair<QNetworkRequest, QByteArray> createPairingRequest(const QHostAddress &host, const int &port, const QString &key);
|
||||
static QPair<QNetworkRequest, QByteArray> createEndPairingRequest(const QUrl &url);
|
||||
static QPair<QNetworkRequest, QByteArray> createEndPairingRequest(const QHostAddress &host, const int &port);
|
||||
static QPair<QNetworkRequest, QByteArray> createEventRequest(const QHostAddress &host, const int &port);
|
||||
static QPair<QNetworkRequest, QByteArray> createDisplayKeyRequest(const QHostAddress &host, quint16 port);
|
||||
static QPair<QNetworkRequest, QByteArray> createPairingRequest(const QHostAddress &host, quint16 port, quint16 eventHandlerPort, const QString &key);
|
||||
static QPair<QNetworkRequest, QByteArray> createEndPairingRequest(const QHostAddress &host, quint16 port, quint16 eventHandlerPort);
|
||||
static QPair<QNetworkRequest, QByteArray> createEventRequest(const QHostAddress &host, quint16 port, quint16 eventHandlerPort);
|
||||
|
||||
QPair<QNetworkRequest, QByteArray> createPressButtonRequest(const TvDevice::RemoteKey &key);
|
||||
|
||||
QUrl buildDisplayImageUrl() const;
|
||||
|
||||
QNetworkRequest createVolumeInformationRequest();
|
||||
QNetworkRequest createChannelInformationRequest();
|
||||
QNetworkRequest createChannelListRequest();
|
||||
QNetworkRequest createAppListCountRequest(int type);
|
||||
QNetworkRequest createAppListRequest(int type, int appCount);
|
||||
|
||||
void onVolumeInformationUpdate(const QByteArray &data);
|
||||
void onChannelInformationUpdate(const QByteArray &data);
|
||||
void onAppListUpdated(const QByteArray &appList);
|
||||
|
||||
static QString printXmlData(const QByteArray &data);
|
||||
|
||||
void browse(BrowseResult *result);
|
||||
void browserItem(BrowserItemResult *result);
|
||||
int launchBrowserItem(const QString &itemId);
|
||||
|
||||
void clearAppList();
|
||||
void addAppList(const QVariantList &appList);
|
||||
|
||||
private:
|
||||
TvEventHandler *m_eventHandler;
|
||||
|
||||
QHostAddress m_hostAddress;
|
||||
int m_port;
|
||||
quint16 m_port = 0;
|
||||
quint16 m_eventHandlerPort = 0;
|
||||
QString m_uuid;
|
||||
QString m_key;
|
||||
|
||||
QVariantList m_appList;
|
||||
|
||||
// States
|
||||
bool m_paired;
|
||||
bool m_reachable;
|
||||
bool m_is3DMode;
|
||||
bool m_mute;
|
||||
int m_volumeLevel;
|
||||
int m_inputSourceIndex;
|
||||
int m_channelNumber;
|
||||
bool m_paired = false;
|
||||
bool m_reachable = false;
|
||||
bool m_is3DMode = false;
|
||||
bool m_mute = false;
|
||||
int m_volumeLevel = 20;
|
||||
int m_inputSourceIndex = -1;
|
||||
int m_channelNumber = -1;
|
||||
QString m_channelType;
|
||||
QString m_channelName;
|
||||
QString m_programName;
|
||||
QString m_inputSourceLabel;
|
||||
|
||||
QString printXmlData(const QByteArray &data);
|
||||
class VirtualFsNode {
|
||||
public:
|
||||
VirtualFsNode(const BrowserItem &item):item(item) {}
|
||||
~VirtualFsNode() { qDeleteAll(childs); }
|
||||
BrowserItem item;
|
||||
QList<VirtualFsNode*> childs;
|
||||
QString getMethod;
|
||||
QVariantMap getParams;
|
||||
void addChild(VirtualFsNode* child) {childs.append(child); }
|
||||
VirtualFsNode *findNode(const QString &id) {
|
||||
if (item.id() == id) return this;
|
||||
foreach (VirtualFsNode *child, childs) {
|
||||
VirtualFsNode *node = child->findNode(id);
|
||||
if (node) return node;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
VirtualFsNode* m_virtualFs = nullptr;
|
||||
|
||||
|
||||
signals:
|
||||
void stateChanged();
|
||||
|
||||
@ -31,20 +31,41 @@
|
||||
#include "tveventhandler.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
TvEventHandler::TvEventHandler(const QHostAddress &host, const int &port, QObject *parent) :
|
||||
TvEventHandler::TvEventHandler(const QHostAddress &host, quint16 eventHandlerPort, QObject *parent) :
|
||||
QTcpServer(parent),
|
||||
m_host(host),
|
||||
m_port(port),
|
||||
m_port(eventHandlerPort),
|
||||
m_expectingData(false)
|
||||
{
|
||||
listen(QHostAddress::AnyIPv4, m_port);
|
||||
if (!listen(QHostAddress::AnyIPv4, m_port)) {
|
||||
qCWarning(dcLgSmartTv()) << "EventHandler: Could not listen for events on" << m_port;
|
||||
} else {
|
||||
qCDebug(dcLgSmartTv()) << "EventHandler: listening on port" << m_port;
|
||||
}
|
||||
}
|
||||
|
||||
uint TvEventHandler::getFreePort()
|
||||
{
|
||||
uint port = 9000;
|
||||
QTcpServer testServer;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (testServer.listen(QHostAddress::AnyIPv4, port)) {
|
||||
qCDebug(dcLgSmartTv()) << "EventHandler: found free port" << port;
|
||||
testServer.close();
|
||||
return port;
|
||||
} else {
|
||||
qCDebug(dcLgSmartTv()) << "EventHandler: port not free" << port << "picking next one...";
|
||||
}
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void TvEventHandler::incomingConnection(qintptr socket)
|
||||
{
|
||||
QTcpSocket* tcpSocket = new QTcpSocket(this);
|
||||
tcpSocket->setSocketDescriptor(socket);
|
||||
qCDebug(dcLgSmartTv()) << "Event handler -> incoming connection" << tcpSocket->peerAddress().toString() << tcpSocket->peerName();
|
||||
qCDebug(dcLgSmartTv()) << "EventHandler: incoming connection" << tcpSocket->peerAddress().toString() << tcpSocket->peerName();
|
||||
connect(tcpSocket, &QTcpSocket::readyRead, this, &TvEventHandler::readClient);
|
||||
connect(tcpSocket, &QTcpSocket::disconnected, this, &TvEventHandler::onDisconnected);
|
||||
}
|
||||
@ -53,22 +74,22 @@ void TvEventHandler::readClient()
|
||||
{
|
||||
QTcpSocket* socket = (QTcpSocket*)sender();
|
||||
|
||||
// reject everything, except the tv
|
||||
// Reject everything, except data from the TV
|
||||
if(socket->peerAddress() != m_host){
|
||||
socket->close();
|
||||
socket->deleteLater();
|
||||
qCWarning(dcLgSmartTv()) << "Event handler -> rejecting connection from " << socket->peerAddress().toString();
|
||||
qCWarning(dcLgSmartTv()) << "EventHandler: rejecting connection from " << socket->peerAddress().toString();
|
||||
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()){
|
||||
while (!socket->atEnd()){
|
||||
QByteArray data = socket->readAll();
|
||||
|
||||
// check if we got information
|
||||
if(data.startsWith("<?xml") && m_expectingData){
|
||||
if (data.startsWith("<?xml") && m_expectingData){
|
||||
m_expectingData = false;
|
||||
|
||||
// Answere with OK
|
||||
@ -86,7 +107,7 @@ 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 handler -> event occured" << "http://" << m_host.toString() << ":" << m_port << tokens[1];
|
||||
qCDebug(dcLgSmartTv()) << "EventHandler: event occured" << "http://" << m_host.toString() << ":" << m_port << tokens[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,7 +115,7 @@ void TvEventHandler::readClient()
|
||||
void TvEventHandler::onDisconnected()
|
||||
{
|
||||
QTcpSocket* socket = (QTcpSocket*)sender();
|
||||
qCDebug(dcLgSmartTv()) << "event handler -> client disconnected" << socket->peerAddress();
|
||||
qCDebug(dcLgSmartTv()) << "EventHandler: client disconnected" << socket->peerAddress();
|
||||
socket->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
@ -45,14 +45,16 @@ class TvEventHandler : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TvEventHandler(const QHostAddress &host, const int &port = 8080, QObject *parent = 0);
|
||||
explicit TvEventHandler(const QHostAddress &host, quint16 eventHandlerPort = 9000, QObject *parent = 0);
|
||||
|
||||
static uint getFreePort();
|
||||
|
||||
protected:
|
||||
void incomingConnection(qintptr socket) override;
|
||||
|
||||
private:
|
||||
QHostAddress m_host;
|
||||
int m_port;
|
||||
quint16 m_port;
|
||||
bool m_expectingData;
|
||||
|
||||
signals:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user