enabled NOTIFY for UPnP plugins

added reconnect support for LG Smart Tv (pairing)
fixed missing uuid from UDAP2.0 device
This commit is contained in:
Simon Stürz 2014-11-05 13:10:08 +01:00 committed by Michael Zanetti
parent 30f5c44e08
commit 3129d6a15c
15 changed files with 253 additions and 673 deletions

View File

@ -184,6 +184,7 @@ DeviceManager::DeviceManager(QObject *parent) :
m_upnpDiscovery = new UpnpDiscovery(this);
connect(m_upnpDiscovery, &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished);
connect(m_upnpDiscovery, &UpnpDiscovery::upnpNotify, this, &DeviceManager::upnpNotifyReceived);
}
/*! Destructor of the DeviceManager. Each loaded \l{DevicePlugin} will be deleted. */
@ -941,6 +942,15 @@ void DeviceManager::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &dev
}
}
void DeviceManager::upnpNotifyReceived(const QByteArray &notifyData)
{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResourceUpnpDisovery)) {
devicePlugin->upnpNotifyReceived(notifyData);
}
}
}
void DeviceManager::timerEvent()
{
foreach (Device *device, m_configuredDevices) {

View File

@ -132,6 +132,7 @@ private slots:
void radio433SignalReceived(QList<int> rawData);
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId);
void upnpNotifyReceived(const QByteArray &notifyData);
void timerEvent();
private:

View File

@ -28,13 +28,13 @@ UpnpDiscovery::UpnpDiscovery(QObject *parent) :
setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1));
setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1));
if(!bind(QHostAddress::AnyIPv4,m_port,QUdpSocket::ShareAddress)){
qWarning() << "ERROR: UPnP discovery could not bind to port " << m_port;
if(!bind(QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress)){
qWarning() << "ERROR: UPnP discovery could not bind to port" << m_port;
return;
}
if(!joinMulticastGroup(m_host)){
qWarning() << "ERROR: UPnP discovery could not join multicast group " << m_host;
qWarning() << "ERROR: UPnP discovery could not join multicast group" << m_host;
return;
}
@ -53,7 +53,7 @@ UpnpDiscovery::UpnpDiscovery(QObject *parent) :
connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError)));
connect(this, &UpnpDiscovery::readyRead, this, &UpnpDiscovery::readData);
qDebug() << "--> Successfully created UPnPDiscovery.";
qDebug() << "--> UPnP discovery created successfully.";
}
bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &userAgent, const PluginId &pluginId)
@ -65,6 +65,11 @@ bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &
reply->deleteLater();
}
if(state() != BoundState){
qDebug() << "ERROR: UPnP not bound to port 1900";
return false;
}
m_searchTarget = searchTarget;
m_userAgent = userAgent;
m_pluginId = pluginId;
@ -76,7 +81,8 @@ bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &
"ST: " + m_searchTarget.toUtf8() + "\r\n"
"USR-AGENT: " + m_userAgent.toUtf8() + "\r\n\r\n");
writeDatagram(ssdpSearchMessage,m_host,m_port);
qDebug() << "--> UPnP discovery called.";
writeDatagram(ssdpSearchMessage, m_host, m_port);
m_timer->start(3000);
return true;
@ -110,19 +116,25 @@ void UpnpDiscovery::readData()
data.resize(pendingDatagramSize());
readDatagram(data.data(), data.size(), &hostAddress);
}
// qDebug() << "-----------------------";
// qDebug() << "======================";
// qDebug() << data;
if (data.contains("NOTIFY")) {
emit upnpNotify(data);
return;
}
// if the data contains the HTTP OK header...
if(data.contains("HTTP/1.1 200 OK")){
if (data.contains("HTTP/1.1 200 OK")) {
const QStringList lines = QString(data).split("\r\n");
foreach( const QString& line, lines){
foreach (const QString& line, lines) {
int separatorIndex = line.indexOf(':');
QString key = line.left(separatorIndex).toUpper();
QString value = line.mid(separatorIndex+1).trimmed();
// get location
if(key.contains("LOCATION")){
if (key.contains("LOCATION")) {
location = QUrl(value);
}
}
@ -147,45 +159,48 @@ void UpnpDiscovery::replyFinished(QNetworkReply *reply)
// parse XML data
QXmlStreamReader xml(data);
while(!xml.atEnd() && !xml.hasError()){
while (!xml.atEnd() && !xml.hasError()) {
xml.readNext();
if(xml.isStartDocument()){
if (xml.isStartDocument()) {
continue;
}
if(xml.isStartElement()){
if(xml.name().toString() == "device"){
while(!xml.atEnd()){
if(xml.name() == "deviceType" && xml.isStartElement()){
if (xml.isStartElement()) {
if (xml.name().toString() == "device") {
while (!xml.atEnd()) {
if (xml.name() == "deviceType" && xml.isStartElement()) {
upnpDeviceDescriptor.setDeviceType(xml.readElementText());
}
if(xml.name() == "friendlyName" && xml.isStartElement()){
if (xml.name() == "friendlyName" && xml.isStartElement()) {
upnpDeviceDescriptor.setFriendlyName(xml.readElementText());
}
if(xml.name() == "manufacturer" && xml.isStartElement()){
if (xml.name() == "manufacturer" && xml.isStartElement()) {
upnpDeviceDescriptor.setManufacturer(xml.readElementText());
}
if(xml.name() == "manufacturerURL" && xml.isStartElement()){
if (xml.name() == "manufacturerURL" && xml.isStartElement()) {
upnpDeviceDescriptor.setManufacturerURL(QUrl(xml.readElementText()));
}
if(xml.name() == "modelDescription" && xml.isStartElement()){
if (xml.name() == "modelDescription" && xml.isStartElement()) {
upnpDeviceDescriptor.setModelDescription(xml.readElementText());
}
if(xml.name() == "modelName" && xml.isStartElement()){
if (xml.name() == "modelName" && xml.isStartElement()) {
upnpDeviceDescriptor.setModelName(xml.readElementText());
}
if(xml.name() == "modelNumber" && xml.isStartElement()){
if (xml.name() == "modelNumber" && xml.isStartElement()) {
upnpDeviceDescriptor.setModelNumber(xml.readElementText());
}
if(xml.name() == "modelURL" && xml.isStartElement()){
if (xml.name() == "modelURL" && xml.isStartElement()) {
upnpDeviceDescriptor.setModelURL(QUrl(xml.readElementText()));
}
if(xml.name() == "serialNumber" && xml.isStartElement()){
if (xml.name() == "serialNumber" && xml.isStartElement()) {
upnpDeviceDescriptor.setSerialNumber(xml.readElementText());
}
if(xml.name() == "UDN" && xml.isStartElement()){
if (xml.name() == "UDN" && xml.isStartElement()) {
upnpDeviceDescriptor.setUuid(xml.readElementText());
}
if(xml.name() == "UPC" && xml.isStartElement()){
if (xml.name() == "uuid" && xml.isStartElement()) {
upnpDeviceDescriptor.setUuid(xml.readElementText());
}
if (xml.name() == "UPC" && xml.isStartElement()) {
upnpDeviceDescriptor.setUpc(xml.readElementText());
}
xml.readNext();
@ -198,11 +213,11 @@ void UpnpDiscovery::replyFinished(QNetworkReply *reply)
// check if we allready have the device in the list
bool isAlreadyInList = false;
foreach (UpnpDeviceDescriptor deviceDescriptor, m_deviceList) {
if(deviceDescriptor.uuid() == upnpDeviceDescriptor.uuid()){
if (deviceDescriptor.uuid() == upnpDeviceDescriptor.uuid()) {
isAlreadyInList = true;
}
}
if(!isAlreadyInList){
if (!isAlreadyInList) {
m_deviceList.append(upnpDeviceDescriptor);
}
break;

View File

@ -58,6 +58,7 @@ private:
signals:
void discoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId & pluginId);
void upnpNotify(const QByteArray &notifyMessage);
private slots:
void error(QAbstractSocket::SocketError error);

View File

@ -525,7 +525,7 @@ bool DevicePlugin::transmitData(int delay, QList<int> rawData, int repetitions)
void DevicePlugin::upnpDiscover(QString searchTarget, QString userAgent)
{
if(requiredHardware() == DeviceManager::HardwareResourceUpnpDisovery){
if(requiredHardware().testFlag(DeviceManager::HardwareResourceUpnpDisovery)){
deviceManager()->m_upnpDiscovery->discoverDevices(searchTarget, userAgent, pluginId());
}
}

View File

@ -62,6 +62,7 @@ public:
virtual void radioData(const QList<int> &rawData) {Q_UNUSED(rawData)}
virtual void guhTimer() {}
virtual void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) {Q_UNUSED(upnpDeviceDescriptorList)}
virtual void upnpNotifyReceived(const QByteArray &notifyData) {Q_UNUSED(notifyData)}
// Configuration
virtual QList<ParamType> configurationDescription() const;

View File

@ -16,28 +16,6 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page lgsmarttv.html
\title LG Smart Tv
\ingroup plugins
\ingroup network
This plugin allows to interact with \l{http://www.lg.com/us/experience-tvs/smart-tv}{LG Smart Tv's}
with the \l{http://developer.lgappstv.com/TV_HELP/index.jsp?topic=%2Flge.tvsdk.references.book%2Fhtml%2FUDAP%2FUDAP%2FLG+UDAP+2+0+Protocol+Specifications.htm}{LG UDAP 2.0 Protocol Specifications}.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
Each \l{DeviceClass} has a list of \l{ParamType}{paramTypes}, \l{ActionType}{actionTypes}, \l{StateType}{stateTypes}
and \l{EventType}{eventTypes}. The \l{DeviceClass::CreateMethod}{createMethods} parameter describes how the \l{Device}
will be created in the system. A device can have more than one \l{DeviceClass::CreateMethod}{CreateMethod}.
The \l{DeviceClass::SetupMethod}{setupMethod} describes the setup method of the \l{Device}.
The detailed implementation of each \l{DeviceClass} can be found in the source code.
\quotefile plugins/deviceplugins/lgsmarttv/devicepluginlgsmarttv.json
*/
#include "devicepluginlgsmarttv.h"
@ -47,42 +25,71 @@
#include <QDebug>
DeviceClassId lgSmartTvDeviceClassId = DeviceClassId("1d41b5a8-74ff-4a12-b365-c7bbe610848f");
StateTypeId tvReachableStateTypeId = StateTypeId("b056c36b-df87-4177-8d5d-1e7c1e8cdc7a");
StateTypeId tv3DModeStateTypeId = StateTypeId("8ad3d77f-d340-495d-8c2a-5569a80e9d36");
StateTypeId tvVolumeLevelStateTypeId = StateTypeId("07d39a6e-7eab-42d0-851d-9f3bcd3bbb57");
StateTypeId tvMuteStateTypeId = StateTypeId("a6ac9061-3de7-403a-a646-790ca5d73764");
StateTypeId tvChannelTypeStateTypeId = StateTypeId("84c86670-77c7-4fc6-9e23-abca066e76aa");
StateTypeId tvChannelNameStateTypeId = StateTypeId("265dc5f7-3f4d-4002-a6fe-2a53986bcf1d");
StateTypeId tvChannelNumberStateTypeId = StateTypeId("881629a3-4ce2-42ba-8ce6-10d90c383799");
StateTypeId tvProgramNameStateTypeId = StateTypeId("3f53e52e-1ad7-40e7-8080-76908e720cac");
StateTypeId tvInputSourceIndexStateTypeId = StateTypeId("e895017a-139f-410c-bfb2-4d008104e164");
StateTypeId tvInputSourceLabelNameStateTypeId = StateTypeId("58b734ec-2269-4c57-99e1-e1eeee401053");
ActionTypeId commandVolumeUpActionTypeId = ActionTypeId("ac5d7dcd-dfe8-4a94-9ab9-21b3f804b39e");
ActionTypeId commandVolumeDownActionTypeId = ActionTypeId("62b17bec-f461-4ffa-93d1-67a9430d55e1");
ActionTypeId commandMuteActionTypeId = ActionTypeId("1aa9d7f0-0f66-4b90-bb72-f6b7b2118221");
ActionTypeId commandUnmuteActionTypeId = ActionTypeId("b7e31999-ba67-443d-8e5c-ec104af987bd");
ActionTypeId commandChannelUpActionTypeId = ActionTypeId("acd1f6a0-2cfa-4665-9607-cf94245ec5a3");
ActionTypeId commandChannelDownActionTypeId = ActionTypeId("6ea66772-0e6d-40b1-978c-a01fb53871dd");
ActionTypeId commandPowerOffActionTypeId = ActionTypeId("cbe41134-ff11-4916-815b-3ac289c64090");
ActionTypeId commandArrowUpActionTypeId = ActionTypeId("57c483b4-4ddf-4470-828c-8d8767e7a923");
ActionTypeId commandArrowDownActionTypeId = ActionTypeId("614cf1af-5cf7-4bb2-885c-4414078d8899");
ActionTypeId commandArrowLeftActionTypeId = ActionTypeId("916394dd-7833-4875-8d7a-49d7d24ceeb2");
ActionTypeId commandArrowRightActionTypeId = ActionTypeId("01e3df1e-638b-4e14-ba85-660267766062");
ActionTypeId commandOkActionTypeId = ActionTypeId("257dfa59-0d38-4e18-a3fc-213809fdb12f");
ActionTypeId commandBackActionTypeId = ActionTypeId("ce4184b3-6b8e-4fc3-a4cb-7b8ec72f2ce9");
ActionTypeId commandHomeActionTypeId = ActionTypeId("33f941c1-f5fc-4449-b6e3-93eafca493e0");
ActionTypeId commandInputSourceActionTypeId = ActionTypeId("9a6e5111-95d3-49ac-8056-249e704b1509");
ActionTypeId commandExitActionTypeId = ActionTypeId("d76efdb8-056e-4b39-a839-2ef6d6001b00");
ActionTypeId commandInfoActionTypeId = ActionTypeId("9c1290d5-3135-4124-a576-fc7522cffdcf");
ActionTypeId commandMyAppsActionTypeId = ActionTypeId("47d65cac-fe75-4c36-9dee-9862c1c1130e");
ActionTypeId commandProgramListActionTypeId = ActionTypeId("9aa3a97e-505d-4906-9764-14b6dc4e31e8");
DevicePluginLgSmartTv::DevicePluginLgSmartTv()
{
m_discovery = new TvDiscovery(this);
connect(m_discovery,SIGNAL(discoveryDone(QList<TvDevice*>)),this,SLOT(discoveryDone(QList<TvDevice*>)));
}
DeviceManager::DeviceError DevicePluginLgSmartTv::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
qDebug() << "should discover devices with params:" << params;
Q_UNUSED(params);
if(deviceClassId != lgSmartTvDeviceClassId){
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
m_discovery->discover(3000);
upnpDiscover("udap:rootservice","UDAP/2.0");
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::setupDevice(Device *device)
{
device->setName("LG Smart Tv (" + device->paramValue("model").toString() + ")");
TvDevice *tvDevice = new TvDevice(this);
tvDevice->setName(device->paramValue("name").toString());
tvDevice->setUuid(device->paramValue("uuid").toString());
tvDevice->setModelName(device->paramValue("model").toString());
tvDevice->setHostAddress(QHostAddress(device->paramValue("host address").toString()));
tvDevice->setPort(device->paramValue("port").toInt());
tvDevice->setLocation(QUrl(device->paramValue("location").toString()));
tvDevice->setUuid(device->paramValue("manufacturer").toString());
UpnpDeviceDescriptor upnpDeviceDescriptor;
upnpDeviceDescriptor.setFriendlyName(device->paramValue("name").toString());
upnpDeviceDescriptor.setUuid(device->paramValue("uuid").toString());
upnpDeviceDescriptor.setModelName(device->paramValue("model").toString());
upnpDeviceDescriptor.setHostAddress(QHostAddress(device->paramValue("host address").toString()));
upnpDeviceDescriptor.setPort(device->paramValue("port").toInt());
upnpDeviceDescriptor.setLocation(QUrl(device->paramValue("location").toString()));
upnpDeviceDescriptor.setManufacturer(device->paramValue("manufacturer").toString());
// key if there is one...
TvDevice *tvDevice = new TvDevice(this, upnpDeviceDescriptor);
// TODO: make dynamic...displayPin setup!!!
tvDevice->setKey("539887");
tvDevice->setupEventHandler();
connect(tvDevice, &TvDevice::pairingFinished, this, &DevicePluginLgSmartTv::pairingFinished);
@ -90,55 +97,55 @@ DeviceManager::DeviceSetupStatus DevicePluginLgSmartTv::setupDevice(Device *devi
connect(tvDevice, &TvDevice::statusChanged, this, &DevicePluginLgSmartTv::statusChanged);
tvDevice->requestPairing();
m_tvList.insert(tvDevice,device);
m_tvList.insert(tvDevice, device);
return DeviceManager::DeviceSetupStatusAsync;
}
DeviceManager::HardwareResources DevicePluginLgSmartTv::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer;
return DeviceManager::HardwareResourceTimer | DeviceManager::HardwareResourceUpnpDisovery;
}
DeviceManager::DeviceError DevicePluginLgSmartTv::executeAction(Device *device, const Action &action)
{
TvDevice * tvDevice = m_tvList.key(device);
if(action.actionTypeId() == commandVolumeUpActionTypeId){
if (action.actionTypeId() == commandVolumeUpActionTypeId) {
tvDevice->sendCommand(TvDevice::VolUp, action.id());
} else if(action.actionTypeId() == commandVolumeDownActionTypeId){
} else if(action.actionTypeId() == commandVolumeDownActionTypeId) {
tvDevice->sendCommand(TvDevice::VolDown, action.id());
} else if(action.actionTypeId() == commandMuteActionTypeId){
} else if(action.actionTypeId() == commandMuteActionTypeId) {
tvDevice->sendCommand(TvDevice::Mute, action.id());
} else if(action.actionTypeId() == commandChannelUpActionTypeId){
} else if(action.actionTypeId() == commandChannelUpActionTypeId) {
tvDevice->sendCommand(TvDevice::ChannelUp, action.id());
} else if(action.actionTypeId() == commandChannelDownActionTypeId){
} else if(action.actionTypeId() == commandChannelDownActionTypeId) {
tvDevice->sendCommand(TvDevice::ChannelDown, action.id());
} else if(action.actionTypeId() == commandPowerOffActionTypeId){
} else if(action.actionTypeId() == commandPowerOffActionTypeId) {
tvDevice->sendCommand(TvDevice::Power, action.id());
} else if(action.actionTypeId() == commandArrowUpActionTypeId){
} else if(action.actionTypeId() == commandArrowUpActionTypeId) {
tvDevice->sendCommand(TvDevice::Up, action.id());
} else if(action.actionTypeId() == commandArrowDownActionTypeId){
} else if(action.actionTypeId() == commandArrowDownActionTypeId) {
tvDevice->sendCommand(TvDevice::Down, action.id());
} else if(action.actionTypeId() == commandArrowLeftActionTypeId){
} else if(action.actionTypeId() == commandArrowLeftActionTypeId) {
tvDevice->sendCommand(TvDevice::Left, action.id());
} else if(action.actionTypeId() == commandArrowRightActionTypeId){
} else if(action.actionTypeId() == commandArrowRightActionTypeId) {
tvDevice->sendCommand(TvDevice::Right, action.id());
} else if(action.actionTypeId() == commandOkActionTypeId){
} else if(action.actionTypeId() == commandOkActionTypeId) {
tvDevice->sendCommand(TvDevice::Ok, action.id());
} else if(action.actionTypeId() == commandBackActionTypeId){
} else if(action.actionTypeId() == commandBackActionTypeId) {
tvDevice->sendCommand(TvDevice::Back, action.id());
} else if(action.actionTypeId() == commandHomeActionTypeId){
} else if(action.actionTypeId() == commandHomeActionTypeId) {
tvDevice->sendCommand(TvDevice::Home, action.id());
} else if(action.actionTypeId() == commandInputSourceActionTypeId){
} else if(action.actionTypeId() == commandInputSourceActionTypeId) {
tvDevice->sendCommand(TvDevice::ExternalInput, action.id());
} else if(action.actionTypeId() == commandExitActionTypeId){
} else if(action.actionTypeId() == commandExitActionTypeId) {
tvDevice->sendCommand(TvDevice::Exit, action.id());
} else if(action.actionTypeId() == commandInfoActionTypeId){
} else if(action.actionTypeId() == commandInfoActionTypeId) {
tvDevice->sendCommand(TvDevice::Info, action.id());
} else if(action.actionTypeId() == commandMyAppsActionTypeId){
} else if(action.actionTypeId() == commandMyAppsActionTypeId) {
tvDevice->sendCommand(TvDevice::MyApps, action.id());
} else if(action.actionTypeId() == commandProgramListActionTypeId){
} else if(action.actionTypeId() == commandProgramListActionTypeId) {
tvDevice->sendCommand(TvDevice::ProgramList, action.id());
} else {
return DeviceManager::DeviceErrorActionTypeNotFound;
@ -146,6 +153,33 @@ DeviceManager::DeviceError DevicePluginLgSmartTv::executeAction(Device *device,
return DeviceManager::DeviceErrorAsync;
}
void DevicePluginLgSmartTv::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList)
{
QList<DeviceDescriptor> deviceDescriptors;
foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, upnpDeviceDescriptorList) {
DeviceDescriptor descriptor(lgSmartTvDeviceClassId, "Lg Smart Tv", upnpDeviceDescriptor.modelName());
ParamList params;
params.append(Param("name", upnpDeviceDescriptor.friendlyName()));
params.append(Param("uuid", upnpDeviceDescriptor.uuid()));
params.append(Param("model", upnpDeviceDescriptor.modelName()));
params.append(Param("host address", upnpDeviceDescriptor.hostAddress().toString()));
params.append(Param("location", upnpDeviceDescriptor.hostAddress().toString()));
params.append(Param("port", upnpDeviceDescriptor.port()));
params.append(Param("manufacturer", upnpDeviceDescriptor.manufacturer()));
params.append(Param("key", "539887"));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(lgSmartTvDeviceClassId, deviceDescriptors);
}
void DevicePluginLgSmartTv::upnpNotifyReceived(const QByteArray &notifyData)
{
Q_UNUSED(notifyData);
// qDebug() << "######################################";
// qDebug() << notifyData;
}
void DevicePluginLgSmartTv::deviceRemoved(Device *device)
{
if (!m_tvList.values().contains(device)) {
@ -153,7 +187,7 @@ void DevicePluginLgSmartTv::deviceRemoved(Device *device)
}
TvDevice *tvDevice= m_tvList.key(device);
qDebug() << "remove LG Smart Tv " << tvDevice->modelName();
qDebug() << "remove LG SmartTv " << tvDevice->modelName();
m_tvList.remove(tvDevice);
tvDevice->deleteLater();
}
@ -165,45 +199,35 @@ void DevicePluginLgSmartTv::guhTimer()
}
}
void DevicePluginLgSmartTv::discoveryDone(QList<TvDevice*> tvList)
{
QList<DeviceDescriptor> deviceDescriptors;
foreach (TvDevice *device, tvList) {
DeviceDescriptor descriptor(lgSmartTvDeviceClassId, "Lg Smart Tv", device->modelName());
ParamList params;
params.append(Param("name", device->name()));
params.append(Param("uuid", device->uuid()));
params.append(Param("model", device->modelName()));
params.append(Param("host address", device->hostAddress().toString()));
params.append(Param("location", device->location().toString()));
params.append(Param("port", device->port()));
params.append(Param("manufacturer", device->manufacturer()));
params.append(Param("key", device->key()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
emit devicesDiscovered(lgSmartTvDeviceClassId, deviceDescriptors);
}
void DevicePluginLgSmartTv::pairingFinished(const bool &success)
{
TvDevice *tvDevice = static_cast<TvDevice*>(sender());
Device *device = m_tvList.value(tvDevice);
if(success){
emit deviceSetupFinished(device,DeviceManager::DeviceSetupStatusSuccess);
// check if we allready set up this device...
foreach (Device *configuredDevice, deviceManager()->findConfiguredDevices(lgSmartTvDeviceClassId)) {
if (configuredDevice->paramValue("uuid").toString() == device->paramValue("uuid").toString()) {
tvDevice->refresh();
return;
}
}
// ...otherwise emit deviceSetupFinished with appropriate DeviceError
if (success) {
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess);
tvDevice->refresh();
}else{
emit deviceSetupFinished(device,DeviceManager::DeviceSetupStatusFailure);
} else {
emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure);
}
}
void DevicePluginLgSmartTv::sendingCommandFinished(const bool &success, const ActionId &actionId)
{
if(success){
emit actionExecutionFinished(actionId,DeviceManager::DeviceErrorNoError);
}else{
emit actionExecutionFinished(actionId,DeviceManager::DeviceErrorHardwareFailure);
if (success) {
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorNoError);
} else {
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorActionTypeNotFound);
}
}
@ -212,7 +236,7 @@ void DevicePluginLgSmartTv::statusChanged()
TvDevice *tvDevice = static_cast<TvDevice*>(sender());
Device *device = m_tvList.value(tvDevice);
device->setStateValue(tvReachableStateTypeId, tvDevice->reachable());
device->setStateValue(tvReachableStateTypeId, tvDevice->isReachable());
device->setStateValue(tv3DModeStateTypeId, tvDevice->is3DMode());
device->setStateValue(tvVolumeLevelStateTypeId, tvDevice->volumeLevel());
device->setStateValue(tvMuteStateTypeId, tvDevice->mute());
@ -223,5 +247,3 @@ void DevicePluginLgSmartTv::statusChanged()
device->setStateValue(tvInputSourceIndexStateTypeId, tvDevice->inputSourceIndex());
device->setStateValue(tvInputSourceLabelNameStateTypeId, tvDevice->inputSourceLabelName());
}

View File

@ -19,8 +19,9 @@
#ifndef DEVICEPLUGINLGSMARTTV_H
#define DEVICEPLUGINLGSMARTTV_H
#include "hardware/upnpdiscovery/upnpdevicedescriptor.h"
#include "plugin/deviceplugin.h"
#include "tvdiscovery.h"
#include "tvdevice.h"
class DevicePluginLgSmartTv : public DevicePlugin
{
@ -32,12 +33,13 @@ class DevicePluginLgSmartTv : public DevicePlugin
public:
explicit DevicePluginLgSmartTv();
TvDiscovery *m_discovery;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
DeviceManager::HardwareResources requiredHardware() const override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
void upnpNotifyReceived(const QByteArray &notifyData);
void deviceRemoved(Device *device) override;
@ -46,14 +48,10 @@ public:
QHash<TvDevice*, Device*> m_tvList;
private slots:
void discoveryDone(QList<TvDevice *> tvList);
void pairingFinished(const bool &success);
void sendingCommandFinished(const bool &success, const ActionId &actionId);
void statusChanged();
public slots:
};
#endif // DEVICEPLUGINLGSMARTTV_H

View File

@ -6,13 +6,11 @@ QT+= network xml
SOURCES += \
devicepluginlgsmarttv.cpp \
tvdiscovery.cpp \
tvdevice.cpp \
tveventhandler.cpp
HEADERS += \
devicepluginlgsmarttv.h \
tvdiscovery.h \
tvdevice.h \
tveventhandler.h

View File

@ -18,100 +18,18 @@
#include "tvdevice.h"
TvDevice::TvDevice(QObject *parent) :
QObject(parent)
TvDevice::TvDevice(QObject *parent, UpnpDeviceDescriptor upnpDeviceDescriptor) :
UpnpDevice(parent, upnpDeviceDescriptor)
{
m_manager = new QNetworkAccessManager(this);
// TODO: make dynamic...displayPin setup
m_key = "539887";
m_key = "0";
m_pairingStatus = false;
m_reachable = false;
connect(m_manager, &QNetworkAccessManager::finished, this, &TvDevice::replyFinished);
}
void TvDevice::setLocation(const QUrl &location)
{
m_location = location;
}
QUrl TvDevice::location() const
{
return m_location;
}
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
{
return m_port;
}
void TvDevice::setName(const QString &name)
{
m_name = name;
}
QString TvDevice::name() const
{
return m_name;
}
void TvDevice::setModelName(const QString &modelName)
{
m_modelName = modelName;
}
QString TvDevice::modelName() const
{
return m_modelName;
}
void TvDevice::setManufacturer(const QString &manufacturer)
{
m_manufacturer = manufacturer;
}
QString TvDevice::manufacturer() const
{
return m_manufacturer;
}
void TvDevice::setDeviceType(const QString &deviceType)
{
m_deviceType = deviceType;
}
QString TvDevice::deviceType() const
{
return m_deviceType;
}
void TvDevice::setUuid(const QString &uuid)
{
m_uuid = uuid;
}
QString TvDevice::uuid() const
{
return m_uuid;
}
void TvDevice::setKey(const QString &key)
{
m_key = key;
@ -122,7 +40,7 @@ QString TvDevice::key() const
return m_key;
}
bool TvDevice::reachable() const
bool TvDevice::isReachable() const
{
return m_reachable;
}
@ -179,12 +97,12 @@ QString TvDevice::inputSourceLabelName() const
void TvDevice::showPairingKey()
{
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/pairing";
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/pairing";
QNetworkRequest request;
request.setUrl(QUrl(urlString));
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=utf-8"));
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0 guh"));
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
QByteArray data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"pairing\"> <name>showKey</name></api></envelope>";
@ -197,7 +115,7 @@ void TvDevice::requestPairing()
emit pairingFinished(false);
}
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/pairing";
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/pairing";
QNetworkRequest request;
request.setUrl(QUrl(urlString));
@ -211,7 +129,7 @@ void TvDevice::requestPairing()
void TvDevice::endPairing()
{
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/pairing";
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/pairing";
QNetworkRequest request;
request.setUrl(QUrl(urlString));
@ -229,12 +147,12 @@ void TvDevice::sendCommand(TvDevice::RemoteKey key, ActionId actionId)
{
m_actionId = actionId;
if(!m_pairingStatus){
if(!m_pairingStatus) {
requestPairing();
return;
}
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/command";
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/command";
QByteArray data;
data.append("<?xml version=\"1.0\" encoding=\"utf-8\"?><envelope><api type=\"command\"><name>HandleKeyInput</name><value>");
@ -252,21 +170,23 @@ void TvDevice::sendCommand(TvDevice::RemoteKey key, ActionId actionId)
void TvDevice::setupEventHandler()
{
//qDebug() << "set up event handler " << m_hostAddress.toString() << m_port;
m_eventHandler = new TvEventHandler(this,m_hostAddress,m_port);
m_eventHandler = new TvEventHandler(this,hostAddress(),port());
connect(m_eventHandler, &TvEventHandler::eventOccured, this, &TvDevice::eventOccured);
}
void TvDevice::refresh()
{
if(paired()){
if(paired()) {
queryChannelInformation();
queryVolumeInformation();
}else{
requestPairing();
}
}
void TvDevice::queryVolumeInformation()
{
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/data?target=volume_info";
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/data?target=volume_info";
QNetworkRequest request;
request.setUrl(QUrl(urlString));
@ -279,7 +199,7 @@ void TvDevice::queryVolumeInformation()
void TvDevice::queryChannelInformation()
{
QString urlString = "http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/udap/api/data?target=cur_channel";
QString urlString = "http://" + hostAddress().toString() + ":" + QString::number(port()) + "/udap/api/data?target=cur_channel";
QNetworkRequest deviceRequest;
deviceRequest.setUrl(QUrl(urlString));
@ -295,13 +215,13 @@ void TvDevice::parseVolumeInformation(const QByteArray &data)
//qDebug() << 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();
}
}
@ -313,25 +233,25 @@ void TvDevice::parseChannelInformation(const QByteArray &data)
//qDebug() << 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();
}
}
@ -347,11 +267,11 @@ QString TvDevice::printXmlData(QByteArray data)
while (!reader.atEnd()) {
reader.readNext();
if (!reader.isWhitespace()) {
if(!reader.isWhitespace()) {
writer.writeCurrentToken(reader);
}
}
if(reader.hasError()){
if(reader.hasError()) {
qDebug() << "ERROR reading XML device information: " << reader.errorString();
qDebug() << "--------------------------------------------";
}
@ -362,56 +282,56 @@ void TvDevice::replyFinished(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(status != 200){
if(status != 200) {
m_reachable = false;
}else{
} else {
m_reachable = true;
}
if(reply == m_showKeyReplay){
if(status != 200){
qWarning() << "ERROR: could not request to show pairing key on screen " << status;
if(reply == m_showKeyReplay) {
if(status != 200) {
//qWarning() << "ERROR: could not request to show pairing key on screen " << status;
}
m_showKeyReplay->deleteLater();
}
if(reply == m_requestPairingReplay){
if(status != 200){
if(reply == m_requestPairingReplay) {
if(status != 200) {
m_pairingStatus = false;
emit pairingFinished(false);
qWarning() << "ERROR: could not pair with device" << status;
}else{
//qWarning() << "ERROR: could not pair with device" << status;
} else {
m_pairingStatus = true;
qDebug() << "successfully paired with tv " << m_modelName;
//qDebug() << "successfully paired with tv " << modelName();
emit pairingFinished(true);
}
m_requestPairingReplay->deleteLater();
}
if(reply == m_finishingPairingReplay){
if(status == 200){
if(reply == m_finishingPairingReplay) {
if(status == 200) {
m_pairingStatus = false;
qDebug() << "successfully unpaired from tv " << m_modelName;
//qDebug() << "successfully unpaired from tv " << modelName();
}
m_finishingPairingReplay->deleteLater();
}
if(reply == m_sendCommandReplay){
if(status != 200){
if(reply == m_sendCommandReplay) {
if (status != 200) {
emit sendCommandFinished(false,m_actionId);
qWarning() << "ERROR: could not send comand" << status;
}else{
} else {
m_pairingStatus = true;
qDebug() << "successfully sent command to tv " << m_modelName;
//qDebug() << "successfully sent command to tv " << modelName();
emit sendCommandFinished(true,m_actionId);
refresh();
}
m_sendCommandReplay->deleteLater();
}
if(reply == m_queryVolumeInformationReplay){
if(reply == m_queryVolumeInformationReplay) {
parseVolumeInformation(reply->readAll());
m_queryVolumeInformationReplay->deleteLater();
}
if(reply == m_queryChannelInformationReplay){
if(reply == m_queryChannelInformationReplay) {
parseChannelInformation(reply->readAll());
m_queryChannelInformationReplay->deleteLater();
}
@ -422,17 +342,14 @@ void TvDevice::replyFinished(QNetworkReply *reply)
void TvDevice::eventOccured(const QByteArray &data)
{
// if we got a channel changed event...
if(data.contains("ChannelChanged")){
if(data.contains("ChannelChanged")) {
parseChannelInformation(data);
return;
}
// qDebug() << "---------------------------------";
// qDebug() << printXmlData(data);
// if the tv suspends, it will send a byebye message, which means
// the pairing will be closed.
if(data.contains("api type=\"pairing\"") && data.contains("byebye")){
if(data.contains("api type=\"pairing\"") && data.contains("byebye")) {
qDebug() << "--> tv ended pairing";
m_pairingStatus = false;
m_reachable = false;
@ -443,13 +360,13 @@ 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();
}
}
@ -458,4 +375,3 @@ void TvDevice::eventOccured(const QByteArray &data)
emit statusChanged();
}

View File

@ -33,12 +33,13 @@
#include "plugin/deviceplugin.h"
#include "tveventhandler.h"
#include "hardware/upnpdiscovery/upnpdevice.h"
class TvDevice : public QObject
class TvDevice : public UpnpDevice
{
Q_OBJECT
public:
explicit TvDevice(QObject *parent = 0);
explicit TvDevice(QObject *parent = 0, UpnpDeviceDescriptor upnpDeviceDescriptor = UpnpDeviceDescriptor());
enum RemoteKey{
Power = 1,
@ -110,37 +111,13 @@ public:
};
// propertys
void setLocation(const QUrl &location);
QUrl location() const;
void setHostAddress(const QHostAddress &hostAddress);
QHostAddress hostAddress() const;
void setPort(const int &port);
int port() const;
void setName(const QString &name);
QString name() const;
void setModelName(const QString &modelName);
QString modelName() const;
void setManufacturer(const QString &manufacturer);
QString manufacturer() const;
void setDeviceType(const QString &deviceType);
QString deviceType() const;
void setUuid(const QString &uuid);
QString uuid() const;
void setKey(const QString &key);
QString key() const;
bool paired() const;
// States
bool reachable() const;
bool isReachable() const;
bool is3DMode() const;
int volumeLevel() const;
bool mute() const;
@ -160,14 +137,6 @@ public:
void refresh();
private:
QUrl m_location;
QHostAddress m_hostAddress;
int m_port;
QString m_name;
QString m_modelName;
QString m_manufacturer;
QString m_deviceType;
QString m_uuid;
QString m_key;
bool m_pairingStatus;
@ -210,8 +179,6 @@ private slots:
void replyFinished(QNetworkReply *reply);
void eventOccured(const QByteArray &data);
public slots:
};
#endif // TVDEVICE_H

View File

@ -1,292 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "tvdiscovery.h"
TvDiscovery::TvDiscovery(QObject *parent) :
QUdpSocket(parent)
{
m_timeout = new QTimer(this);
m_timeout->setSingleShot(true);
connect(m_timeout,SIGNAL(timeout()),this,SLOT(discoverTimeout()));
m_manager = new QNetworkAccessManager(this);
connect(m_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
m_port = 1900;
m_host = QHostAddress("239.255.255.250");
setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1));
setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1));
bind(QHostAddress::AnyIPv4,m_port,QUdpSocket::ShareAddress);
joinMulticastGroup(m_host);
connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError)));
connect(this,SIGNAL(readyRead()),this,SLOT(readData()));
}
bool TvDiscovery::checkXmlData(QByteArray data)
{
QByteArray xmlOut;
QXmlStreamReader reader(data);
QXmlStreamWriter writer(&xmlOut);
writer.setAutoFormatting(true);
while (!reader.atEnd()) {
reader.readNext();
if (!reader.isWhitespace()) {
writer.writeCurrentToken(reader);
}
}
if(reader.hasError()){
qDebug() << "ERROR reading XML device information: " << reader.errorString();
qDebug() << "--------------------------------------------";
return false;
}
m_deviceInformationData = xmlOut;
return true;
}
QString TvDiscovery::printXmlData(QByteArray data)
{
QString xmlOut;
QXmlStreamReader reader(data);
QXmlStreamWriter writer(&xmlOut);
writer.setAutoFormatting(true);
while (!reader.atEnd()) {
reader.readNext();
if (!reader.isWhitespace()) {
writer.writeCurrentToken(reader);
}
}
if(reader.hasError()){
qDebug() << "ERROR reading XML device information: " << reader.errorString();
qDebug() << "--------------------------------------------";
}
return xmlOut;
}
void TvDiscovery::error(QAbstractSocket::SocketError error)
{
qWarning() << errorString() << error;
}
void TvDiscovery::readData()
{
QByteArray data;
QHostAddress sender;
quint16 udpPort;
// read the answere from the multicast
while (hasPendingDatagrams()) {
data.resize(pendingDatagramSize());
readDatagram(data.data(), data.size(), &sender, &udpPort);
}
if(data.size() > 0){
if(data.contains("HTTP/1.1 200 OK")){
const QStringList lines = QString(data).split("\r\n");
QUrl location;
QString uuid;
QString server;
foreach( const QString& line, lines){
int separatorIndex = line.indexOf(':');
QString key = line.left(separatorIndex).toUpper();
QString value = line.mid(separatorIndex+1).trimmed();
// get location
if(key.contains("LOCATION")){
location = QUrl(value);
}
// get server info
if(key.contains("SERVER")){
// check if it is a LG Smart Tv with UDAP/2.0 protocoll
if(value.contains("UDAP/2.0")){
server = value;
}
}
// get uuid
if(key.contains("USN")){
int startIndex = value.indexOf(":");
int endIndex = value.indexOf("::");
uuid = value.mid(startIndex +1 ,(endIndex - startIndex)-1);
}
if(!location.isEmpty() && !uuid.isEmpty() && !server.isEmpty()){
foreach (TvDevice *device, m_tvList) {
if(device->uuid() == uuid){
return;
}
}
TvDevice *device = new TvDevice(this);
device->setLocation(location);
device->setHostAddress(sender);
device->setUuid(uuid);
m_tvList.append(device);
requestDeviceInformation(device);
}
}
}
}
}
void TvDiscovery::discoverTimeout()
{
emit discoveryDone(m_tvList);
}
void TvDiscovery::requestDeviceInformation(TvDevice *device)
{
QNetworkRequest deviceRequest;
deviceRequest.setUrl(device->location());
deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml"));
deviceRequest.setHeader(QNetworkRequest::UserAgentHeader,QVariant("UDAP/2.0"));
m_deviceInformationReplay = m_manager->get(deviceRequest);
}
void TvDiscovery::replyFinished(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QByteArray data;
switch (status) {
case(200):
data = reply->readAll();
if(checkXmlData(data)){
parseDeviceInformation(data);
}
break;
case(400):
qDebug() << "ERROR: 400 Bad request. The event format is not valid or it has an incorrect value.";
qDebug() << "--------------------------------------------";
return;
case(401):
qDebug() << "ERROR: 401 Unauthorized. An event is sent when a Host and a Controller are not paired.";
qDebug() << "--------------------------------------------";
return;
case(404):
qDebug() << "ERROR: 404 Not Found. The POST path of an event is incorrect.";
qDebug() << "--------------------------------------------";
return;
case(500):
qDebug() << "ERROR: 500 Internal Server Error. Event Execution Failure.";
qDebug() << "--------------------------------------------";
return;
default:
return;
}
}
void TvDiscovery::parseDeviceInformation(QByteArray data)
{
QXmlStreamReader xml(data);
QString name;
QString uuid;
QString modelName;
QString deviceType;
QString manufacturer;
int port;
qDebug() << printXmlData(data);
while(!xml.atEnd() && !xml.hasError()){
xml.readNext();
if(xml.isStartDocument()){
continue;
}
if(xml.isStartElement()){
if(xml.name() == "envelope"){
continue;
}
//check if we have device part of message
if(xml.name() == "device"){
// seems to be device information
while(!xml.atEnd()){
if(xml.name() == "deviceType" && xml.isStartElement()){
deviceType = xml.readElementText();
}
if(xml.name() == "modelName" && xml.isStartElement()){
modelName = xml.readElementText();
}
if(xml.name() == "friendlyName" && xml.isStartElement()){
name = xml.readElementText();
}
if(xml.name() == "manufacturer" && xml.isStartElement()){
manufacturer = xml.readElementText();
}
if(xml.name() == "uuid" && xml.isStartElement()){
uuid = xml.readElementText();
}
//check if we have port part of message
if(xml.name() == "port"){
port = xml.readElementText().toInt();
}
xml.readNext();
}
}
}
}
foreach (TvDevice *device, m_tvList) {
// find our device with this uuid
if(device->uuid() == uuid){
device->setName(name);
device->setModelName(modelName);
device->setDeviceType(deviceType);
device->setManufacturer(manufacturer);
device->setPort(port);
qDebug() << "--> fetched TV information...";
qDebug() << "name: " << device->name();
qDebug() << "model name: " << device->modelName();
qDebug() << "device type: " << device->deviceType();
qDebug() << "manufacturer: " << device->manufacturer();
qDebug() << "address: " << device->hostAddress().toString();
qDebug() << "port: " << device->port();
qDebug() << "location: " << device->location().toString();
qDebug() << "uuid: " << device->uuid();
qDebug() << "--------------------------------------------";
}
}
}
void TvDiscovery::discover(int timeout)
{
QString searchMessage("M-SEARCH * HTTP/1.1\r\n"
"HOST:239.255.255.250:1900\r\n"
"MAN:\"ssdp:discover\"\r\n"
"MX:2\r\n"
"ST:udap:rootservice\r\n"
"USER-AGENT: UDAP/2.0 \r\n\r\n");
m_tvList.clear();
writeDatagram(searchMessage.toUtf8(),m_host,m_port);
m_timeout->start(timeout);
}

View File

@ -1,72 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TVDISCOVERY_H
#define TVDISCOVERY_H
#include <QUdpSocket>
#include <QHostAddress>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QXmlStreamAttributes>
#include "tvdevice.h"
class TvDiscovery : public QUdpSocket
{
Q_OBJECT
public:
explicit TvDiscovery(QObject *parent = 0);
private:
QHostAddress m_host;
qint16 m_port;
QTimer *m_timeout;
QList<TvDevice*> m_tvList;
QNetworkAccessManager *m_manager;
QNetworkReply *m_deviceInformationReplay;
QByteArray m_deviceInformationData;
bool checkXmlData(QByteArray data);
QString printXmlData(QByteArray data);
signals:
void discoveryDone(const QList<TvDevice*> deviceList);
private slots:
void error(QAbstractSocket::SocketError error);
void readData();
void discoverTimeout();
void requestDeviceInformation(TvDevice *device);
void replyFinished(QNetworkReply *reply);
void parseDeviceInformation(QByteArray data);
public slots:
void discover(int timeout);
};
#endif // TVDISCOVERY_H

View File

@ -51,14 +51,29 @@
#include <QStringList>
#include <QColor>
DevicePluginPhilipsHue::DevicePluginPhilipsHue():
m_discovery(new Discovery(this))
{
connect(m_discovery, &Discovery::discoveryDone, this, &DevicePluginPhilipsHue::discoveryDone);
VendorId hueVendorId = VendorId("");
m_bridge = new HueBridgeConnection(this);
connect(m_bridge, &HueBridgeConnection::createUserFinished, this, &DevicePluginPhilipsHue::createUserFinished);
connect(m_bridge, &HueBridgeConnection::getFinished, this, &DevicePluginPhilipsHue::getFinished);
DeviceClassId hueDeviceClassId = DeviceClassId("d8f4c397-e05e-47c1-8917-8e72d4d0d47c");
StateTypeId hueColorStateTypeId = StateTypeId("d25423e7-b924-4b20-80b6-77eecc65d089");
ActionTypeId hueSetColorActionTypeId = ActionTypeId("29cc299a-818b-47b2-817f-c5a6361545e4");
StateTypeId huePowerStateTypeId = StateTypeId("6ac64eee-f356-4ae4-bc85-8c1244d12b02");
ActionTypeId hueSetPowerActionTypeId = ActionTypeId("7782d91e-d73a-4321-8828-da768e2f6827");
StateTypeId hueBrightnessStateTypeId = StateTypeId("411f489c-4bc9-42f7-b47d-b0581dc0c29e");
ActionTypeId hueSetBrightnessActionTypeId = ActionTypeId("3bc95552-cba0-4222-abd5-9b668132e442");
StateTypeId hueReachableStateTypeId = StateTypeId("15794d26-fde8-4a61-8f83-d7830534975f");
DevicePluginPhilipsHue::DevicePluginPhilipsHue()
//:m_discovery(new Discovery(this))
{
// connect(m_discovery, &Discovery::discoveryDone, this, &DevicePluginPhilipsHue::discoveryDone);
// m_bridge = new HueBridgeConnection(this);
// connect(m_bridge, &HueBridgeConnection::createUserFinished, this, &DevicePluginPhilipsHue::createUserFinished);
// connect(m_bridge, &HueBridgeConnection::getFinished, this, &DevicePluginPhilipsHue::getFinished);
}
DeviceManager::HardwareResources DevicePluginPhilipsHue::requiredHardware() const

View File

@ -53,9 +53,9 @@
DevicePluginWemo::DevicePluginWemo()
{
m_discovery = new WemoDiscovery(this);
// m_discovery = new WemoDiscovery(this);
connect(m_discovery,SIGNAL(discoveryDone(QList<WemoSwitch*>)),this,SLOT(discoveryDone(QList<WemoSwitch*>)));
// connect(m_discovery,SIGNAL(discoveryDone(QList<WemoSwitch*>)),this,SLOT(discoveryDone(QList<WemoSwitch*>)));
}
DeviceManager::DeviceError DevicePluginWemo::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)