fixed wemo to use UpnpDiscovery and added rediscovery action

This commit is contained in:
Simon Stürz 2014-12-11 11:32:44 +01:00 committed by Michael Zanetti
parent 608ef8641d
commit 9df94474bd
10 changed files with 246 additions and 611 deletions

View File

@ -42,67 +42,137 @@ QUrl UpnpDevice::location()
return m_location;
}
void UpnpDevice::setLocation(const QUrl &location)
{
m_location = location;
}
QHostAddress UpnpDevice::hostAddress() const
{
return m_hostAddress;
}
void UpnpDevice::setHostAddress(const QHostAddress &hostAddress)
{
m_hostAddress = hostAddress;
}
int UpnpDevice::port() const
{
return m_port;
}
void UpnpDevice::setPort(const int &port)
{
m_port = port;
}
QString UpnpDevice::deviceType() const
{
return m_deviceType;
}
void UpnpDevice::setDeviceType(const QString &deviceType)
{
m_deviceType = deviceType;
}
QString UpnpDevice::friendlyName() const
{
return m_friendlyName;
}
void UpnpDevice::setFriendlyName(const QString &friendlyName)
{
m_friendlyName = friendlyName;
}
QString UpnpDevice::manufacturer() const
{
return m_manufacturer;
}
void UpnpDevice::setManufacturer(const QString &manufacturer)
{
m_manufacturer = manufacturer;
}
QUrl UpnpDevice::manufacturerURL() const
{
return m_manufacturerURL;
}
void UpnpDevice::setManufacturerURL(const QUrl &manufacturerURL)
{
m_manufacturerURL = manufacturerURL;
}
QString UpnpDevice::modelDescription() const
{
return m_modelDescription;
}
void UpnpDevice::setModelDescription(const QString &modelDescription)
{
m_modelDescription = modelDescription;
}
QString UpnpDevice::modelName() const
{
return m_modelName;
}
void UpnpDevice::setModelName(const QString &modelName)
{
m_modelName = modelName;
}
QString UpnpDevice::modelNumber() const
{
return m_modelNumber;
}
void UpnpDevice::setModelNumber(const QString &modelNumber)
{
m_modelNumber = modelNumber;
}
QUrl UpnpDevice::modelURL() const
{
return m_modelURL;
}
void UpnpDevice::setModelURL(const QUrl &modelURL)
{
m_modelURL = modelURL;
}
QString UpnpDevice::serialNumber() const
{
return m_serialNumber;
}
void UpnpDevice::setSerialNumber(const QString &serialNumber)
{
m_serialNumber = serialNumber;
}
QString UpnpDevice::uuid() const
{
return m_uuid;
}
void UpnpDevice::setUuid(const QString &uuid)
{
m_uuid = uuid;
}
QString UpnpDevice::upc() const
{
return m_upc;
}
void UpnpDevice::setUpc(const QString &upc)
{
m_upc = upc;
}

View File

@ -30,20 +30,46 @@ public:
explicit UpnpDevice(QObject *parent = 0, UpnpDeviceDescriptor upnpDeviceDescriptor = UpnpDeviceDescriptor());
QUrl location();
QHostAddress hostAddress() const;
int port() const;
QString deviceType() const;
QString friendlyName() const;
QString manufacturer() const;
QUrl manufacturerURL() const;
QString modelDescription() const;
QString modelName() const;
QString modelNumber() const;
QUrl modelURL() const;
QString serialNumber() const;
QString uuid() const;
QString upc() const;
void setLocation(const QUrl &location);
QHostAddress hostAddress() const;
void setHostAddress(const QHostAddress &hostAddress);
int port() const;
void setPort(const int &port);
QString deviceType() const;
void setDeviceType(const QString & deviceType);
QString friendlyName() const;
void setFriendlyName(const QString &friendlyName);
QString manufacturer() const;
void setManufacturer(const QString &manufacturer);
QUrl manufacturerURL() const;
void setManufacturerURL(const QUrl & manufacturerURL);
QString modelDescription() const;
void setModelDescription(const QString & modelDescription);
QString modelName() const;
void setModelName(const QString & modelName);
QString modelNumber() const;
void setModelNumber(const QString &modelNumber);
QUrl modelURL() const;
void setModelURL(const QUrl &modelURL);
QString serialNumber() const;
void setSerialNumber(const QString &serialNumber);
QString uuid() const;
void setUuid(const QString &uuid);
QString upc() const;
void setUpc(const QString &upc);
private:
QUrl m_location;

View File

@ -51,48 +51,46 @@
#include <QDebug>
DeviceClassId wemoSwitchDeviceClassId = DeviceClassId("69d97d3b-a8e6-42f3-afc0-ca8a53eb7cce");
StateTypeId powerStateTypeId = StateTypeId("7166c4f6-f68c-4188-8f7c-2205d72a5a6d");
StateTypeId reachableStateTypeId = StateTypeId("ec2f5b49-585c-4455-a233-b7aa4c608dbc");
ActionTypeId powerActionTypeId = ActionTypeId("269f25eb-d0b7-4144-b9ef-801f4ff3e90c");
ActionTypeId rediscoverActionTypeId = ActionTypeId("269cf3b8-d4dd-42e9-8309-6cb3ca8842df");
DevicePluginWemo::DevicePluginWemo()
{
// m_discovery = new WemoDiscovery(this);
// connect(m_discovery,SIGNAL(discoveryDone(QList<WemoSwitch*>)),this,SLOT(discoveryDone(QList<WemoSwitch*>)));
}
DeviceManager::DeviceError DevicePluginWemo::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
if(deviceClassId != wemoSwitchDeviceClassId){
Q_UNUSED(params);
if (deviceClassId != wemoSwitchDeviceClassId) {
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
m_discovery->discover(2000);
upnpDiscover("upnp:rootdevice");
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceSetupStatus DevicePluginWemo::setupDevice(Device *device)
{
if(device->deviceClassId() == wemoSwitchDeviceClassId){
if (device->deviceClassId() == wemoSwitchDeviceClassId) {
foreach (WemoSwitch *wemoSwitch, m_wemoSwitches.keys()) {
if(wemoSwitch->serialNumber() == device->paramValue("serial number").toString()){
qWarning() << wemoSwitch->serialNumber() << " already exists...";
if (wemoSwitch->serialNumber() == device->paramValue("serial number").toString()) {
qWarning() << "WeMo Switch " << wemoSwitch->serialNumber() << " allready added...";
return DeviceManager::DeviceSetupStatusFailure;
}
}
UpnpDeviceDescriptor upnpDeviceDescriptor;
upnpDeviceDescriptor.setFriendlyName(device->paramValue("name").toString());
upnpDeviceDescriptor.setHostAddress(QHostAddress(device->paramValue("host address").toString()));
upnpDeviceDescriptor.setPort(device->paramValue("port").toInt());
upnpDeviceDescriptor.setSerialNumber(device->paramValue("serial number").toString());
device->setName("WeMo Switch (" + device->paramValue("serial number").toString() + ")");
WemoSwitch *wemoSwitch = new WemoSwitch(this);
wemoSwitch->setName(device->paramValue("name").toString());
wemoSwitch->setUuid(device->paramValue("uuid").toString());
wemoSwitch->setPort(device->paramValue("port").toInt());
wemoSwitch->setModelName(device->paramValue("model").toString());
wemoSwitch->setHostAddress(QHostAddress(device->paramValue("host address").toString()));
wemoSwitch->setModelDescription(device->paramValue("model description").toString());
wemoSwitch->setSerialNumber(device->paramValue("serial number").toString());
wemoSwitch->setLocation(QUrl(device->paramValue("location").toString()));
wemoSwitch->setManufacturer(device->paramValue("manufacturer").toString());
wemoSwitch->setDeviceType(device->paramValue("device type").toString());
WemoSwitch *wemoSwitch = new WemoSwitch(this, upnpDeviceDescriptor);
connect(wemoSwitch,SIGNAL(stateChanged()),this,SLOT(wemoSwitchStateChanged()));
connect(wemoSwitch,SIGNAL(setPowerFinished(bool,ActionId)),this,SLOT(setPowerFinished(bool,ActionId)));
@ -101,27 +99,35 @@ DeviceManager::DeviceSetupStatus DevicePluginWemo::setupDevice(Device *device)
wemoSwitch->refresh();
return DeviceManager::DeviceSetupStatusSuccess;
}
return DeviceManager::DeviceSetupStatusSuccess;
return DeviceManager::DeviceSetupStatusFailure;
}
DeviceManager::HardwareResources DevicePluginWemo::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer;
return DeviceManager::HardwareResourceTimer | DeviceManager::HardwareResourceUpnpDisovery;
}
DeviceManager::DeviceError DevicePluginWemo::executeAction(Device *device, const Action &action)
{
if(device->deviceClassId() == wemoSwitchDeviceClassId){
if(action.actionTypeId() == powerActionTypeId){
if (device->deviceClassId() == wemoSwitchDeviceClassId) {
if (action.actionTypeId() == powerActionTypeId) {
WemoSwitch *wemoSwitch = m_wemoSwitches.key(device);
wemoSwitch->setPower(action.param("power").value().toBool(),action.id());
return DeviceManager::DeviceErrorAsync;
}else{
return DeviceManager::DeviceErrorActionTypeNotFound;
if (wemoSwitch->reachable()) {
// setPower returns false, if the curent powerState == new powerState
if (wemoSwitch->setPower(action.param("power").value().toBool(), action.id())) {
return DeviceManager::DeviceErrorAsync;
} else {
return DeviceManager::DeviceErrorNoError;
}
} else {
return DeviceManager::DeviceErrorHardwareNotAvailable;
}
} else if (action.actionTypeId() == rediscoverActionTypeId) {
upnpDiscover("upnp:rootdevice");
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
return DeviceManager::DeviceErrorDeviceClassNotFound;
}
@ -133,8 +139,8 @@ void DevicePluginWemo::deviceRemoved(Device *device)
WemoSwitch *wemoSwitch= m_wemoSwitches.key(device);
qDebug() << "remove wemo swich " << wemoSwitch->serialNumber();
wemoSwitch->deleteLater();
m_wemoSwitches.remove(wemoSwitch);
wemoSwitch->deleteLater();
}
void DevicePluginWemo::guhTimer()
@ -144,33 +150,64 @@ void DevicePluginWemo::guhTimer()
}
}
void DevicePluginWemo::discoveryDone(QList<WemoSwitch *> deviceList)
void DevicePluginWemo::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList)
{
QList<DeviceDescriptor> deviceDescriptors;
foreach (WemoSwitch *device, deviceList) {
DeviceDescriptor descriptor(wemoSwitchDeviceClassId, "WeMo Switch", device->serialNumber());
ParamList params;
params.append(Param("name", device->name()));
params.append(Param("uuid", device->uuid()));
params.append(Param("port", device->port()));
params.append(Param("model", device->modelName()));
params.append(Param("model description", device->modelDescription()));
params.append(Param("serial number", device->serialNumber()));
params.append(Param("host address", device->hostAddress().toString()));
params.append(Param("location", device->location().toString()));
params.append(Param("manufacturer", device->manufacturer()));
params.append(Param("device type", device->deviceType()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
foreach (UpnpDeviceDescriptor upnpDeviceDescriptor, upnpDeviceDescriptorList) {
if (upnpDeviceDescriptor.friendlyName() == "WeMo Switch") {
if (!verifyExistingDevices(upnpDeviceDescriptor)) {
DeviceDescriptor descriptor(wemoSwitchDeviceClassId, "WemoSwitch", upnpDeviceDescriptor.serialNumber());
ParamList params;
params.append(Param("name", upnpDeviceDescriptor.friendlyName()));
params.append(Param("host address", upnpDeviceDescriptor.hostAddress().toString()));
params.append(Param("port", upnpDeviceDescriptor.port()));
params.append(Param("serial number", upnpDeviceDescriptor.serialNumber()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
}
}
emit devicesDiscovered(wemoSwitchDeviceClassId, deviceDescriptors);
}
void DevicePluginWemo::upnpNotifyReceived(const QByteArray &notifyData)
{
Q_UNUSED(notifyData);
}
bool DevicePluginWemo::verifyExistingDevices(UpnpDeviceDescriptor deviceDescriptor)
{
foreach (WemoSwitch *wemoSwitch, m_wemoSwitches.keys()) {
// check if we allready have added this Wemo device and verify the params
if (wemoSwitch->serialNumber() == deviceDescriptor.serialNumber()) {
qDebug() << "verify wemo paramters... of" << wemoSwitch->serialNumber();
Device *device = m_wemoSwitches.value(wemoSwitch);
// now check if ip or port changed
bool somethingChanged = false;
if (wemoSwitch->hostAddress() != deviceDescriptor.hostAddress()) {
device->setParamValue("host address", deviceDescriptor.hostAddress().toString());
wemoSwitch->setHostAddress(deviceDescriptor.hostAddress());
somethingChanged = true;
}
if(wemoSwitch->port() != deviceDescriptor.port()){
device->setParamValue("port", deviceDescriptor.port());
wemoSwitch->setPort(deviceDescriptor.port());
somethingChanged = true;
}
if (somethingChanged) {
wemoSwitch->refresh();
}
return true;
}
}
return false;
}
void DevicePluginWemo::wemoSwitchStateChanged()
{
WemoSwitch *wemoSwitch = static_cast<WemoSwitch*>(sender());
if(m_wemoSwitches.contains(wemoSwitch)){
if (m_wemoSwitches.contains(wemoSwitch)) {
Device * device = m_wemoSwitches.value(wemoSwitch);
device->setStateValue(powerStateTypeId, wemoSwitch->powerState());
device->setStateValue(reachableStateTypeId, wemoSwitch->reachable());
@ -179,10 +216,10 @@ void DevicePluginWemo::wemoSwitchStateChanged()
void DevicePluginWemo::setPowerFinished(const bool &succeeded, const ActionId &actionId)
{
if(succeeded){
emit actionExecutionFinished(actionId,DeviceManager::DeviceErrorNoError);
}else{
emit actionExecutionFinished(actionId,DeviceManager::DeviceErrorHardwareFailure);
if (succeeded) {
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorNoError);
} else {
emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorHardwareNotAvailable);
}
}

View File

@ -20,7 +20,7 @@
#define DEVICEPLUGINWEMO_H
#include "plugin/deviceplugin.h"
#include "wemodiscovery.h"
#include "wemoswitch.h"
class DevicePluginWemo : public DevicePlugin
{
@ -40,12 +40,14 @@ public:
void deviceRemoved(Device *device) override;
void guhTimer() override;
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &upnpDeviceDescriptorList) override;
void upnpNotifyReceived(const QByteArray &notifyData);
WemoDiscovery *m_discovery;
private:
QHash<WemoSwitch*, Device*> m_wemoSwitches;
bool verifyExistingDevices(UpnpDeviceDescriptor deviceDescriptor);
private slots:
void discoveryDone(QList<WemoSwitch *> deviceList);
void wemoSwitchStateChanged();
void setPowerFinished(const bool &succeeded, const ActionId &actionId);

View File

@ -16,14 +16,6 @@
"name": "name",
"type": "QString"
},
{
"name": "uuid",
"type": "QString"
},
{
"name": "model",
"type": "QString"
},
{
"name": "host address",
"type": "QString"
@ -32,25 +24,9 @@
"name": "port",
"type": "int"
},
{
"name": "model description",
"type": "QString"
},
{
"name": "serial number",
"type": "QString"
},
{
"name": "location",
"type": "QString"
},
{
"name": "manufacturer",
"type": "QString"
},
{
"name": "device type",
"type": "QString"
}
],
"stateTypes": [
@ -74,8 +50,16 @@
"id": "269f25eb-d0b7-4144-b9ef-801f4ff3e90c",
"idName": "power",
"name": "set power",
"type": "bool",
"defaultValue": true
"paramTypes": [
{
"name": "power",
"type": "bool"
}
]
},
{
"id": "269cf3b8-d4dd-42e9-8309-6cb3ca8842df",
"name": "rediscover"
}
]
}

View File

@ -6,13 +6,11 @@ QT+= network
SOURCES += \
devicepluginwemo.cpp \
wemodiscovery.cpp \
wemoswitch.cpp
HEADERS += \
devicepluginwemo.h \
wemodiscovery.h \
wemoswitch.h

View File

@ -1,281 +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 "wemodiscovery.h"
WemoDiscovery::WemoDiscovery(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);
if(!joinMulticastGroup(m_host)){
qWarning() << "ERROR: could not join multicast group";
}
connect(this,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error(QAbstractSocket::SocketError)));
connect(this,SIGNAL(readyRead()),this,SLOT(readData()));
}
bool WemoDiscovery::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 WemoDiscovery::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 WemoDiscovery::error(QAbstractSocket::SocketError error)
{
qWarning() << errorString() << error;
}
void WemoDiscovery::sendDiscoverMessage()
{
QByteArray ssdpSearchMessage("M-SEARCH * HTTP/1.1\r\n"
"HOST:239.255.255.250:1900\r\n"
"ST:upnp:rootdevice\r\n"
"MX:2\r\n"
"MAN:\"ssdp:discover\"\r\n\r\n");
writeDatagram(ssdpSearchMessage,m_host,m_port);
}
void WemoDiscovery::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.contains("HTTP/1.1 200 OK")){
const QStringList lines = QString(data).split("\r\n");
QUrl location;
QString uuid;
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 uuid
if(key.contains("USN")){
int startIndex = value.indexOf(":");
int endIndex = value.indexOf("::");
uuid = value.mid(startIndex +1 ,(endIndex - startIndex)-1);
// check if we found a socket...else return
if(!uuid.startsWith("Socket-1_0")){
return;
}
}
if(!location.isEmpty() && !uuid.isEmpty()){
// check if we already discovered this device
foreach (WemoSwitch *device, m_deviceList) {
if(device->uuid() == uuid){
return;
}
}
// get port from location (it changes between 49152-5 so fare...)
QByteArray locationData = location.toString().toUtf8();
locationData = locationData.left(locationData.length() - 10);
qDebug() << "locationData" << locationData;
int port = locationData.right(5).toInt();
WemoSwitch *device = new WemoSwitch(this);
device->setHostAddress(sender);
device->setUuid(uuid);
device->setLocation(location);
device->setPort(port);
qDebug() << "--> UPnP searcher discovered wemo...";
qDebug() << "location: " << device->location().toString();
qDebug() << "ip: " << device->hostAddress().toString();
qDebug() << "uuid: " << device->uuid();
qDebug() << "port: " << device->port();
qDebug() << "--------------------------------------------";
m_deviceList.append(device);
requestDeviceInformation(location);
}
}
}
}
void WemoDiscovery::discoverTimeout()
{
emit discoveryDone(m_deviceList);
}
void WemoDiscovery::requestDeviceInformation(QUrl location)
{
m_manager->get(QNetworkRequest(location));
}
void WemoDiscovery::replyFinished(QNetworkReply *reply)
{
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
switch (status) {
case(200):
parseDeviceInformation(reply->readAll());
break;
default:
qWarning() << "HTTP request error " << status;
return;
}
}
void WemoDiscovery::parseDeviceInformation(QByteArray data)
{
QXmlStreamReader xml(data);
QString name;
QString uuid;
QString modelName;
QString modelDescription;
QString serialNumber;
QString deviceType;
QString manufacturer;
while(!xml.atEnd() && !xml.hasError()){
xml.readNext();
if(xml.isStartDocument()){
continue;
}
if(xml.isStartElement()){
if(xml.name().toString() == "device"){
while(!xml.atEnd()){
if(xml.name() == "friendlyName" && xml.isStartElement()){
name = xml.readElementText();
}
if(xml.name() == "manufacturer" && xml.isStartElement()){
manufacturer = xml.readElementText();
}
if(xml.name() == "modelDescription" && xml.isStartElement()){
modelDescription = xml.readElementText();
}
if(xml.name() == "modelName" && xml.isStartElement()){
modelName = xml.readElementText();
}
if(xml.name() == "serialNumber" && xml.isStartElement()){
serialNumber = xml.readElementText();
}
if(xml.name() == "deviceType" && xml.isStartElement()){
deviceType = xml.readElementText();
}
if(xml.name() == "UDN" && xml.isStartElement()){
uuid = xml.readElementText();
if(uuid.startsWith("uuid:")){
uuid = uuid.right(uuid.length()-5);
}
}
xml.readNext();
}
xml.readNext();
}
}
}
foreach (WemoSwitch *device, m_deviceList) {
// find our device with this uuid
if(device->uuid() == uuid){
device->setName(name);
device->setModelName(modelName);
device->setDeviceType(deviceType);
device->setManufacturer(manufacturer);
device->setModelDescription(modelDescription);
device->setSerialNumber(serialNumber);
qDebug() << "--> fetched Wemo 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() << "location: " << device->location().toString();
qDebug() << "uuid: " << device->uuid();
qDebug() << "model description " << device->modelDescription();
qDebug() << "serial number " << device->serialNumber();
qDebug() << "--------------------------------------------";
}
}
}
void WemoDiscovery::discover(int timeout)
{
m_deviceList.clear();
m_timeout->stop();
sendDiscoverMessage();
m_timeout->start(timeout);
}

View File

@ -1,74 +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 WEMODISCOVERY_H
#define WEMODISCOVERY_H
#include <QUdpSocket>
#include <QHostAddress>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QXmlStreamAttributes>
#include "wemoswitch.h"
class WemoDiscovery : public QUdpSocket
{
Q_OBJECT
public:
explicit WemoDiscovery(QObject *parent = 0);
private:
QHostAddress m_host;
qint16 m_port;
QTimer *m_timeout;
QNetworkAccessManager *m_manager;
QByteArray m_deviceInformationData;
bool checkXmlData(QByteArray data);
QString printXmlData(QByteArray data);
QList<WemoSwitch*> m_deviceList;
signals:
void discoveryDone(QList<WemoSwitch*> deviceList);
private slots:
void error(QAbstractSocket::SocketError error);
void sendDiscoverMessage();
void readData();
void discoverTimeout();
void requestDeviceInformation(QUrl location);
void replyFinished(QNetworkReply *reply);
void parseDeviceInformation(QByteArray data);
public slots:
void discover(int timeout);
};
#endif // WEMODISCOVERY_H

View File

@ -18,112 +18,16 @@
#include "wemoswitch.h"
WemoSwitch::WemoSwitch(QObject *parent) :
QObject(parent)
WemoSwitch::WemoSwitch(QObject *parent, UpnpDeviceDescriptor upnpDeviceDescriptor):
UpnpDevice(parent, upnpDeviceDescriptor)
{
m_manager = new QNetworkAccessManager(this);
connect(m_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
}
void WemoSwitch::setLocation(const QUrl &location)
WemoSwitch::~WemoSwitch()
{
m_location = location;
}
QUrl WemoSwitch::location() const
{
return m_location;
}
void WemoSwitch::setHostAddress(const QHostAddress &hostAddress)
{
m_hostAddress = hostAddress;
}
QHostAddress WemoSwitch::hostAddress() const
{
return m_hostAddress;
}
void WemoSwitch::setPort(const int &port)
{
m_port = port;
}
int WemoSwitch::port() const
{
return m_port;
}
void WemoSwitch::setManufacturer(const QString &manufacturer)
{
m_manufacturer = manufacturer;
}
QString WemoSwitch::manufacturer() const
{
return m_manufacturer;
}
void WemoSwitch::setName(const QString &name)
{
m_name = name;
}
QString WemoSwitch::name() const
{
return m_name;
}
void WemoSwitch::setDeviceType(const QString &deviceType)
{
m_deviceType = deviceType;
}
QString WemoSwitch::deviceType() const
{
return m_deviceType;
}
void WemoSwitch::setModelDescription(const QString &modelDescription)
{
m_modelDescription = modelDescription;
}
QString WemoSwitch::modelDescription() const
{
return m_modelDescription;
}
void WemoSwitch::setModelName(const QString &modelName)
{
m_modelName = modelName;
}
QString WemoSwitch::modelName() const
{
return m_modelName;
}
void WemoSwitch::setSerialNumber(const QString &serialNumber)
{
m_serialNumber = serialNumber;
}
QString WemoSwitch::serialNumber() const
{
return m_serialNumber;
}
void WemoSwitch::setUuid(const QString &uuid)
{
m_uuid = uuid;
}
QString WemoSwitch::uuid() const
{
return m_uuid;
}
bool WemoSwitch::powerState()
@ -138,32 +42,39 @@ bool WemoSwitch::reachable()
void WemoSwitch::replyFinished(QNetworkReply *reply)
{
if(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200){
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
// clean up
if (reply == m_setPowerReplay) {
emit setPowerFinished(false,m_actionId);
m_setPowerReplay->deleteLater();
}
if (reply == m_refrashReplay) {
m_refrashReplay->deleteLater();
}
m_reachable = false;
emit stateChanged();
m_setPowerReplay->deleteLater();
return;
}else{
} else {
m_reachable = true;
}
// if this is the answerer to a refresh request
if(reply == m_refrashReplay){
if (reply == m_refrashReplay) {
QByteArray data = reply->readAll();
if(data.contains("<BinaryState>0</BinaryState>")){
if (data.contains("<BinaryState>0</BinaryState>")) {
m_powerState = false;
}
if(data.contains("<BinaryState>1</BinaryState>")){
if (data.contains("<BinaryState>1</BinaryState>")) {
m_powerState = true;
}
m_refrashReplay->deleteLater();
}
// if this is the answerer to a "set power" request
if(reply == m_setPowerReplay){
if (reply == m_setPowerReplay) {
QByteArray data = reply->readAll();
if(data.contains("<BinaryState>1</BinaryState>") || data.contains("<BinaryState>0</BinaryState>")){
if (data.contains("<BinaryState>1</BinaryState>") || data.contains("<BinaryState>0</BinaryState>")) {
emit setPowerFinished(true,m_actionId);
}else{
} else {
emit setPowerFinished(false,m_actionId);
}
refresh();
@ -178,7 +89,7 @@ void WemoSwitch::refresh()
QByteArray getBinarayStateMessage("<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:GetBinaryState xmlns:u=\"urn:Belkin:service:basicevent:1\"><BinaryState>1</BinaryState></u:GetBinaryState></s:Body></s:Envelope>");
QNetworkRequest request;
request.setUrl(QUrl("http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/upnp/control/basicevent1"));
request.setUrl(QUrl("http://" + hostAddress().toString() + ":" + QString::number(port()) + "/upnp/control/basicevent1"));
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=\"utf-8\""));
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("guh"));
request.setRawHeader("SOAPACTION", "\"urn:Belkin:service:basicevent:1#GetBinaryState\"");
@ -186,22 +97,23 @@ void WemoSwitch::refresh()
m_refrashReplay = m_manager->post(request,getBinarayStateMessage);
}
void WemoSwitch::setPower(const bool &power, const ActionId &actionId)
bool WemoSwitch::setPower(const bool &power, const ActionId &actionId)
{
m_actionId = actionId;
if(m_powerState == power){
emit setPowerFinished(true,actionId);
return;
// check if the power state changed...
if (m_powerState == power) {
return false;
}
QByteArray setPowerMessage("<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetBinaryState xmlns:u=\"urn:Belkin:service:basicevent:1\"><BinaryState>" + QByteArray::number((int)power) + "</BinaryState></u:SetBinaryState></s:Body></s:Envelope>");
QNetworkRequest request;
request.setUrl(QUrl("http://" + m_hostAddress.toString() + ":" + QString::number(m_port) + "/upnp/control/basicevent1"));
request.setUrl(QUrl("http://" + hostAddress().toString() + ":" + QString::number(port()) + "/upnp/control/basicevent1"));
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml; charset=\"utf-8\""));
request.setHeader(QNetworkRequest::UserAgentHeader,QVariant("guh"));
request.setRawHeader("SOAPACTION", "\"urn:Belkin:service:basicevent:1#SetBinaryState\"");
m_setPowerReplay = m_manager->post(request,setPowerMessage);
return true;
}

View File

@ -30,58 +30,19 @@
#include <QXmlStreamAttributes>
#include "plugin/deviceplugin.h"
#include "hardware/upnpdiscovery/upnpdevice.h"
class WemoSwitch : public QObject
class WemoSwitch : public UpnpDevice
{
Q_OBJECT
public:
explicit WemoSwitch(QObject *parent = 0);
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 setManufacturer(const QString &manufacturer);
QString manufacturer() const;
void setName(const QString &name);
QString name() const;
void setDeviceType(const QString &deviceType);
QString deviceType() const;
void setModelDescription(const QString &modelDescription);
QString modelDescription() const;
void setModelName(const QString &modelName);
QString modelName() const;
void setSerialNumber(const QString &serialNumber);
QString serialNumber() const;
void setUuid(const QString &uuid);
QString uuid() const;
explicit WemoSwitch(QObject *parent = 0, UpnpDeviceDescriptor upnpDeviceDescriptor = UpnpDeviceDescriptor());
~WemoSwitch();
bool powerState();
bool reachable();
private:
QUrl m_location;
QHostAddress m_hostAddress;
int m_port;
QString m_name;
QString m_deviceType;
QString m_modelName;
QString m_modelDescription;
QString m_manufacturer;
QString m_serialNumber;
QString m_uuid;
QNetworkAccessManager *m_manager;
QNetworkReply *m_refrashReplay;
QNetworkReply *m_setPowerReplay;
@ -99,7 +60,7 @@ private slots:
public slots:
void refresh();
void setPower(const bool &power, const ActionId &actionId);
bool setPower(const bool &power, const ActionId &actionId);
};
#endif // WEMOSWITCH_H