mirror of https://github.com/nymea/nymea.git
add initial support for pairing devices (Only CreateMethodDiscovery and SetupMethodPushButton so far)
implement an initial Philips Hue plugin to test it add a python script to test stuffpull/135/head
parent
3bb19915bf
commit
a6725ec4e9
|
|
@ -95,6 +95,9 @@ DeviceManager::DeviceManager(QObject *parent) :
|
|||
QObject(parent),
|
||||
m_radio433(0)
|
||||
{
|
||||
qRegisterMetaType<DeviceClassId>();
|
||||
qRegisterMetaType<DeviceDescriptor>();
|
||||
|
||||
m_pluginTimer.setInterval(15000);
|
||||
connect(&m_pluginTimer, &QTimer::timeout, this, &DeviceManager::timerEvent);
|
||||
|
||||
|
|
@ -228,7 +231,7 @@ QPair<DeviceManager::DeviceError, QString> DeviceManager::addConfiguredDevice(co
|
|||
return qMakePair<DeviceError, QString>(DeviceErrorCreationMethodNotSupported, "CreateMethodDiscovery");
|
||||
}
|
||||
|
||||
DeviceDescriptor descriptor = m_discoveredDevices.take(deviceClassId).take(deviceDescriptorId);
|
||||
DeviceDescriptor descriptor = m_discoveredDevices.take(deviceDescriptorId);
|
||||
if (!descriptor.isValid()) {
|
||||
return qMakePair<DeviceError>(DeviceErrorDeviceDescriptorNotFound, deviceDescriptorId.toString());
|
||||
}
|
||||
|
|
@ -236,6 +239,98 @@ QPair<DeviceManager::DeviceError, QString> DeviceManager::addConfiguredDevice(co
|
|||
return addConfiguredDeviceInternal(deviceClassId, descriptor.params(), deviceId);
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> DeviceManager::pairDevice(const DeviceClassId &deviceClassId, const QList<Param> ¶ms)
|
||||
{
|
||||
DeviceClass deviceClass = findDeviceClass(deviceClassId);
|
||||
if (deviceClass.id().isNull()) {
|
||||
qWarning() << "cannot find a device class with id" << deviceClassId;
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorDeviceClassNotFound, deviceClassId.toString());
|
||||
}
|
||||
|
||||
if (deviceClass.setupMethod() == DeviceClass::SetupMethodJustAdd) {
|
||||
qWarning() << "Cannot setup this device this way. No need to pair this device.";
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorCreationMethodNotSupported, "No need to pair this device.");
|
||||
}
|
||||
|
||||
QUuid pairingTransactionId = QUuid::createUuid();
|
||||
m_pairingsJustAdd.insert(pairingTransactionId, qMakePair<DeviceClassId, QList<Param> >(deviceClassId, params));
|
||||
|
||||
if (deviceClass.setupMethod() == DeviceClass::SetupMethodDisplayPin) {
|
||||
// TODO: fetch PIN from device plugin
|
||||
qWarning() << "SetupMethodDisplayPin not implemented yet";
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorSetupFailed, "SetupMethodDisplayPin Not implemented yet.");
|
||||
}
|
||||
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorNoError, pairingTransactionId.toString());
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> DeviceManager::pairDevice(const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId)
|
||||
{
|
||||
DeviceClass deviceClass = findDeviceClass(deviceClassId);
|
||||
if (deviceClass.id().isNull()) {
|
||||
qWarning() << "cannot find a device class with id" << deviceClassId;
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorDeviceClassNotFound, deviceClassId.toString());
|
||||
}
|
||||
|
||||
if (deviceClass.setupMethod() == DeviceClass::SetupMethodJustAdd) {
|
||||
qWarning() << "Cannot setup this device this way. No need to pair this device.";
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorCreationMethodNotSupported, "No need to pair this device.");
|
||||
}
|
||||
|
||||
if (!m_discoveredDevices.contains(deviceDescriptorId)) {
|
||||
qWarning() << "Cannot find a DeviceDescriptor with ID" << deviceClassId.toString();
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorDeviceDescriptorNotFound, deviceDescriptorId.toString());
|
||||
}
|
||||
|
||||
QUuid pairingTransactionId = QUuid::createUuid();
|
||||
m_pairingsDiscovery.insert(pairingTransactionId, qMakePair<DeviceClassId, DeviceDescriptorId>(deviceClassId, deviceDescriptorId));
|
||||
|
||||
if (deviceClass.setupMethod() == DeviceClass::SetupMethodDisplayPin) {
|
||||
// TODO: fetch PIN from device plugin
|
||||
qWarning() << "SetupMethodDisplayPin not implemented yet";
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorSetupFailed, "SetupMethodDisplayPin Not implemented yet.");
|
||||
}
|
||||
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorNoError, pairingTransactionId.toString());
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> DeviceManager::confirmPairing(const QUuid &pairingTransactionId, const QString &secret)
|
||||
{
|
||||
if (m_pairingsJustAdd.contains(pairingTransactionId)) {
|
||||
qWarning() << "this SetupMethod is not implemented yet";
|
||||
m_pairingsJustAdd.remove(pairingTransactionId);
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorSetupFailed, "Not implemented yet");
|
||||
}
|
||||
|
||||
if (m_pairingsDiscovery.contains(pairingTransactionId)) {
|
||||
DeviceDescriptorId deviceDescriptorId = m_pairingsDiscovery.value(pairingTransactionId).second;
|
||||
DeviceClassId deviceClassId = m_pairingsDiscovery.value(pairingTransactionId).first;
|
||||
|
||||
DeviceDescriptor deviceDescriptor = m_discoveredDevices.value(deviceDescriptorId);
|
||||
|
||||
DevicePlugin *plugin = m_devicePlugins.value(m_supportedDevices.value(deviceClassId).pluginId());
|
||||
|
||||
if (!plugin) {
|
||||
qWarning() << "Can't find a plugin for this device class";
|
||||
return report(DeviceErrorPluginNotFound, m_supportedDevices.value(deviceClassId).pluginId().toString());
|
||||
}
|
||||
|
||||
QPair<DeviceSetupStatus, QString> status = plugin->confirmPairing(pairingTransactionId, deviceClassId, deviceDescriptor.params());
|
||||
switch (status.first) {
|
||||
case DeviceSetupStatusSuccess:
|
||||
m_pairingsDiscovery.remove(pairingTransactionId);
|
||||
return report(DeviceErrorNoError);
|
||||
case DeviceSetupStatusFailure:
|
||||
m_pairingsDiscovery.remove(pairingTransactionId);
|
||||
return report(DeviceErrorSetupFailed, status.second);
|
||||
case DeviceSetupStatusAsync:
|
||||
return report(DeviceErrorAsync);
|
||||
}
|
||||
}
|
||||
|
||||
return report(DeviceErrorPairingTransactionIdNotFound, pairingTransactionId.toString());
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> DeviceManager::addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QList<Param> ¶ms, const DeviceId id)
|
||||
{
|
||||
DeviceClass deviceClass = findDeviceClass(deviceClassId);
|
||||
|
|
@ -244,6 +339,11 @@ QPair<DeviceManager::DeviceError, QString> DeviceManager::addConfiguredDeviceInt
|
|||
return qMakePair<DeviceError, QString>(DeviceErrorDeviceClassNotFound, deviceClassId.toString());
|
||||
}
|
||||
|
||||
if (deviceClass.setupMethod() != DeviceClass::SetupMethodJustAdd) {
|
||||
qWarning() << "Cannot setup this device this way. You need to pair this device.";
|
||||
return qMakePair<DeviceError, QString>(DeviceErrorCreationMethodNotSupported, "You need to pair this device.");
|
||||
}
|
||||
|
||||
QPair<DeviceError, QString> result = verifyParams(deviceClass.paramTypes(), params);
|
||||
if (result.first != DeviceErrorNoError) {
|
||||
return result;
|
||||
|
|
@ -437,6 +537,7 @@ void DeviceManager::loadPlugins()
|
|||
connect(pluginIface, &DevicePlugin::devicesDiscovered, this, &DeviceManager::slotDevicesDiscovered);
|
||||
connect(pluginIface, &DevicePlugin::deviceSetupFinished, this, &DeviceManager::slotDeviceSetupFinished);
|
||||
connect(pluginIface, &DevicePlugin::actionExecutionFinished, this, &DeviceManager::actionExecutionFinished);
|
||||
connect(pluginIface, &DevicePlugin::pairingFinished, this, &DeviceManager::slotPairingFinished);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -527,11 +628,9 @@ void DeviceManager::createNewAutoDevices()
|
|||
|
||||
void DeviceManager::slotDevicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors)
|
||||
{
|
||||
QHash<DeviceDescriptorId, DeviceDescriptor> descriptorHash;
|
||||
foreach (const DeviceDescriptor &descriptor, deviceDescriptors) {
|
||||
descriptorHash.insert(descriptor.id(), descriptor);
|
||||
m_discoveredDevices.insert(descriptor.id(), descriptor);
|
||||
}
|
||||
m_discoveredDevices[deviceClassId] = descriptorHash;
|
||||
emit devicesDiscovered(deviceClassId, deviceDescriptors);
|
||||
}
|
||||
|
||||
|
|
@ -589,6 +688,78 @@ void DeviceManager::slotDeviceSetupFinished(Device *device, DeviceManager::Devic
|
|||
emit deviceSetupFinished(device, DeviceManager::DeviceErrorNoError, QString());
|
||||
}
|
||||
|
||||
void DeviceManager::slotPairingFinished(const QUuid &pairingTransactionId, DeviceManager::DeviceSetupStatus status, const QString &errorMessage)
|
||||
{
|
||||
if (!m_pairingsJustAdd.contains(pairingTransactionId) && !m_pairingsDiscovery.contains(pairingTransactionId)) {
|
||||
DevicePlugin *plugin = dynamic_cast<DevicePlugin*>(sender());
|
||||
if (plugin) {
|
||||
qWarning() << "Received a pairing finished without waiting for it from plugin:" << plugin->metaObject()->className();
|
||||
} else {
|
||||
qWarning() << "Received a pairing finished without waiting for it.";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceClassId deviceClassId;
|
||||
QList<Param> params;
|
||||
|
||||
// Do this before checking status to make sure we clean up our hashes properly
|
||||
if (m_pairingsJustAdd.contains(pairingTransactionId)) {
|
||||
QPair<DeviceClassId, QList<Param> > pair = m_pairingsJustAdd.take(pairingTransactionId);
|
||||
deviceClassId = pair.first;
|
||||
params = pair.second;
|
||||
}
|
||||
|
||||
if (m_pairingsDiscovery.contains(pairingTransactionId)) {
|
||||
QPair<DeviceClassId, DeviceDescriptorId> pair = m_pairingsDiscovery.take(pairingTransactionId);
|
||||
|
||||
DeviceDescriptorId deviceDescriptorId = pair.second;
|
||||
DeviceDescriptor descriptor = m_discoveredDevices.take(deviceDescriptorId);
|
||||
|
||||
deviceClassId = pair.first;
|
||||
params = descriptor.params();
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "pairingfinsihed!" << errorMessage;
|
||||
if (status != DeviceSetupStatusSuccess) {
|
||||
qDebug() << "emitting shit";
|
||||
emit pairingFinished(pairingTransactionId, DeviceErrorSetupFailed, errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceClass deviceClass = findDeviceClass(deviceClassId);
|
||||
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
|
||||
if (!plugin) {
|
||||
qWarning() << "Cannot find a plugin for this device class!";
|
||||
emit pairingFinished(pairingTransactionId, DeviceErrorPluginNotFound, deviceClass.pluginId().toString());
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceId id = DeviceId::createDeviceId();
|
||||
Device *device = new Device(plugin->pluginId(), id, deviceClassId, this);
|
||||
device->setName(deviceClass.name());
|
||||
device->setParams(params);
|
||||
|
||||
QPair<DeviceSetupStatus, QString> setupStatus = setupDevice(device);
|
||||
switch (setupStatus.first) {
|
||||
case DeviceSetupStatusFailure:
|
||||
qWarning() << "Device setup failed. Not adding device to system.";
|
||||
delete device;
|
||||
emit pairingFinished(pairingTransactionId, DeviceErrorSetupFailed, QString("Device setup failed: %1").arg(setupStatus.second));
|
||||
return;
|
||||
case DeviceSetupStatusAsync:
|
||||
case DeviceSetupStatusSuccess:
|
||||
qDebug() << "Device setup complete.";
|
||||
break;
|
||||
}
|
||||
|
||||
m_configuredDevices.append(device);
|
||||
storeConfiguredDevices();
|
||||
|
||||
emit pairingFinished(pairingTransactionId, DeviceErrorNoError, QString(), id);
|
||||
}
|
||||
|
||||
void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value)
|
||||
{
|
||||
Device *device = qobject_cast<Device*>(sender());
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ public:
|
|||
DeviceErrorCreationMethodNotSupported,
|
||||
DeviceErrorActionParameterError,
|
||||
DeviceErrorDeviceDescriptorNotFound,
|
||||
DeviceErrorAsync
|
||||
DeviceErrorAsync,
|
||||
DeviceErrorPairingTransactionIdNotFound,
|
||||
};
|
||||
|
||||
enum DeviceSetupStatus {
|
||||
|
|
@ -82,6 +83,9 @@ public:
|
|||
QList<Device*> configuredDevices() const;
|
||||
QPair<DeviceError, QString> addConfiguredDevice(const DeviceClassId &deviceClassId, const QList<Param> ¶ms, const DeviceId id = DeviceId::createDeviceId());
|
||||
QPair<DeviceError, QString> addConfiguredDevice(const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId, const DeviceId &id = DeviceId::createDeviceId());
|
||||
QPair<DeviceError, QString> pairDevice(const DeviceClassId &deviceClassId, const QList<Param> ¶ms);
|
||||
QPair<DeviceError, QString> pairDevice(const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId);
|
||||
QPair<DeviceError, QString> confirmPairing(const QUuid &pairingTransactionId, const QString &secret = QString());
|
||||
QPair<DeviceError, QString> removeConfiguredDevice(const DeviceId &deviceId);
|
||||
|
||||
Device* findConfiguredDevice(const DeviceId &id) const;
|
||||
|
|
@ -94,6 +98,7 @@ signals:
|
|||
void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value);
|
||||
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &devices);
|
||||
void deviceSetupFinished(Device *device, DeviceError status, const QString &errorMessage);
|
||||
void pairingFinished(const QUuid &pairingTransactionId, DeviceError status, const QString &errorMessage, const DeviceId &deviceId = DeviceId());
|
||||
void actionExecutionFinished(const ActionId, DeviceError status, const QString &errorMessage);
|
||||
|
||||
public slots:
|
||||
|
|
@ -106,6 +111,7 @@ private slots:
|
|||
void createNewAutoDevices();
|
||||
void slotDevicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
|
||||
void slotDeviceSetupFinished(Device *device, DeviceManager::DeviceSetupStatus status, const QString &errorMessage);
|
||||
void slotPairingFinished(const QUuid &pairingTransactionId, DeviceManager::DeviceSetupStatus status, const QString &errorMessage);
|
||||
|
||||
// Only connect this to Devices. It will query the sender()
|
||||
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
|
||||
|
|
@ -128,7 +134,7 @@ private:
|
|||
QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap;
|
||||
QHash<DeviceClassId, DeviceClass> m_supportedDevices;
|
||||
QList<Device*> m_configuredDevices;
|
||||
QHash<DeviceClassId, QHash<DeviceDescriptorId, DeviceDescriptor> > m_discoveredDevices;
|
||||
QHash<DeviceDescriptorId, DeviceDescriptor> m_discoveredDevices;
|
||||
|
||||
QHash<PluginId, DevicePlugin*> m_devicePlugins;
|
||||
|
||||
|
|
@ -139,6 +145,9 @@ private:
|
|||
QTimer m_pluginTimer;
|
||||
QList<Device*> m_pluginTimerUsers;
|
||||
|
||||
QHash<QUuid, QPair<DeviceClassId, QList<Param> > > m_pairingsJustAdd;
|
||||
QHash<QUuid, QPair<DeviceClassId, DeviceDescriptorId> > m_pairingsDiscovery;
|
||||
|
||||
friend class DevicePlugin;
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(DeviceManager::HardwareResources)
|
||||
|
|
|
|||
|
|
@ -189,6 +189,16 @@ void DeviceClass::setSetupMethod(DeviceClass::SetupMethod setupMethod)
|
|||
m_setupMethod = setupMethod;
|
||||
}
|
||||
|
||||
QString DeviceClass::pairingInfo() const
|
||||
{
|
||||
return m_pairingInfo;
|
||||
}
|
||||
|
||||
void DeviceClass::setPairingInfo(const QString &pairingInfo)
|
||||
{
|
||||
m_pairingInfo = pairingInfo;
|
||||
}
|
||||
|
||||
/*! Compare this \a deviceClass to another. This is effectively the same as calling a.id() == b.id(). Returns true if the ids match.*/
|
||||
bool DeviceClass::operator==(const DeviceClass &deviceClass) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ public:
|
|||
SetupMethod setupMethod() const;
|
||||
void setSetupMethod(SetupMethod setupMethod);
|
||||
|
||||
QString pairingInfo() const;
|
||||
void setPairingInfo(const QString &pairingInfo);
|
||||
|
||||
bool operator==(const DeviceClass &device) const;
|
||||
|
||||
private:
|
||||
|
|
@ -89,6 +92,7 @@ private:
|
|||
QList<ParamType> m_discoveryParamTypes;
|
||||
CreateMethod m_createMethod;
|
||||
SetupMethod m_setupMethod;
|
||||
QString m_pairingInfo;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -53,4 +53,6 @@ private:
|
|||
QList<Param> m_params;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(DeviceDescriptor)
|
||||
|
||||
#endif // DEVICEDESCRIPTION_H
|
||||
|
|
|
|||
|
|
@ -147,6 +147,11 @@ bool DevicePlugin::configureAutoDevice(QList<Device*> loadedDevices, Device *dev
|
|||
return false;
|
||||
}
|
||||
|
||||
/*! Reimplement this if you support a DeviceClass with createMethod CreateMethodDiscovery.
|
||||
This will be called to discover Devices for the given DeviceClass. This will always
|
||||
be an async operation. Return DeviceErrorAsync or DeviceErrorNoError if the discovery
|
||||
has been started successfully. Return an appropriate error otherwise.
|
||||
Once devices are discovered, emit devicesDiscovered() once. */
|
||||
DeviceManager::DeviceError DevicePlugin::discoverDevices(const DeviceClassId &deviceClassId, const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(deviceClassId)
|
||||
|
|
@ -177,6 +182,15 @@ void DevicePlugin::deviceRemoved(Device *device)
|
|||
Q_UNUSED(device)
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> DevicePlugin::confirmPairing(const QUuid &pairingTransactionId, const DeviceClassId &deviceClassId, const QList<Param> ¶ms)
|
||||
{
|
||||
Q_UNUSED(pairingTransactionId)
|
||||
Q_UNUSED(deviceClassId)
|
||||
Q_UNUSED(params)
|
||||
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusFailure, "Plugin does not implement pairing.");
|
||||
}
|
||||
|
||||
QList<ParamType> DevicePlugin::configurationDescription() const
|
||||
{
|
||||
return QList<ParamType>();
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ public:
|
|||
virtual QPair<DeviceManager::DeviceSetupStatus, QString> setupDevice(Device *device);
|
||||
virtual void deviceRemoved(Device *device);
|
||||
|
||||
virtual QPair<DeviceManager::DeviceSetupStatus, QString> confirmPairing(const QUuid &pairingTransactionId, const DeviceClassId &deviceClassId, const QList<Param> ¶ms);
|
||||
|
||||
// Hardware input
|
||||
virtual void radioData(QList<int> rawData) {Q_UNUSED(rawData)}
|
||||
virtual void guhTimer() {}
|
||||
|
|
@ -76,6 +78,7 @@ signals:
|
|||
void emitEvent(const Event &event);
|
||||
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
|
||||
void deviceSetupFinished(Device *device, DeviceManager::DeviceSetupStatus status, const QString &errorMessage);
|
||||
void pairingFinished(const QUuid &pairingTransactionId, DeviceManager::DeviceSetupStatus status, const QString &errorMessage);
|
||||
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status, const QString &errorMessage);
|
||||
void configValueChanged(const QString ¶mName, const QVariant &value);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ SUBDIRS += elro \
|
|||
lircd \
|
||||
wakeonlan \
|
||||
mailnotification \
|
||||
philipshue \
|
||||
|
||||
boblight {
|
||||
SUBDIRS += boblight
|
||||
|
|
|
|||
|
|
@ -428,10 +428,10 @@ DeviceManager::DeviceError DevicePluginOpenweathermap::discoverDevices(const Dev
|
|||
qDebug() << "should discover divces for" << deviceClassId << params.value("location").toString();
|
||||
if(params.value("location").toString() == ""){
|
||||
m_openweaher->searchAutodetect();
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
return DeviceManager::DeviceErrorAsync;
|
||||
}
|
||||
m_openweaher->search(params.value("location").toString());
|
||||
return DeviceManager::DeviceErrorNoError;
|
||||
return DeviceManager::DeviceErrorAsync;
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> DevicePluginOpenweathermap::setupDevice(Device *device)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,242 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 "devicepluginphilipshue.h"
|
||||
|
||||
#include "plugin/device.h"
|
||||
#include "devicemanager.h"
|
||||
#include "types/param.h"
|
||||
#include "huebridgeconnection.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QJsonDocument>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QColor>
|
||||
|
||||
VendorId hueVendorId = VendorId("0ae1e001-2aa6-47ed-b8c0-334c3728a68f");
|
||||
|
||||
PluginId huePluginUuid = PluginId("5f2e634b-b7f3-48ee-976a-b5ae22aa5c55");
|
||||
DeviceClassId hueDeviceClassId = DeviceClassId("d8f4c397-e05e-47c1-8917-8e72d4d0d47c");
|
||||
|
||||
StateTypeId hueColorStateTypeId = StateTypeId("d25423e7-b924-4b20-80b6-77eecc65d089");
|
||||
ActionTypeId setHueColorActionTypeId = ActionTypeId("29cc299a-818b-47b2-817f-c5a6361545e4");
|
||||
|
||||
DevicePluginPhilipsHue::DevicePluginPhilipsHue():
|
||||
m_discovery(new Discovery(this))
|
||||
{
|
||||
connect(m_discovery, &Discovery::discoveryDone, this, &DevicePluginPhilipsHue::discoveryDone);
|
||||
|
||||
m_nam = new QNetworkAccessManager(this);
|
||||
}
|
||||
|
||||
QList<Vendor> DevicePluginPhilipsHue::supportedVendors() const
|
||||
{
|
||||
QList<Vendor> ret;
|
||||
Vendor philips(hueVendorId, "Philips");
|
||||
ret.append(philips);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<DeviceClass> DevicePluginPhilipsHue::supportedDevices() const
|
||||
{
|
||||
QList<DeviceClass> ret;
|
||||
|
||||
DeviceClass deviceClassHue(pluginId(), hueVendorId, hueDeviceClassId);
|
||||
deviceClassHue.setName("Hue");
|
||||
deviceClassHue.setCreateMethod(DeviceClass::CreateMethodDiscovery);
|
||||
|
||||
deviceClassHue.setSetupMethod(DeviceClass::SetupMethodPushButton);
|
||||
deviceClassHue.setPairingInfo("Please press the button on the Hue bridge and then press OK");
|
||||
|
||||
QList<ParamType> paramTypes;
|
||||
ParamType ipParam("ip", QVariant::String);
|
||||
paramTypes.append(ipParam);
|
||||
deviceClassHue.setParamTypes(paramTypes);
|
||||
|
||||
QList<StateType> hueStates;
|
||||
|
||||
StateType colorState(hueColorStateTypeId);
|
||||
colorState.setName("color");
|
||||
colorState.setType(QVariant::Color);
|
||||
colorState.setDefaultValue(QColor(Qt::black));
|
||||
hueStates.append(colorState);
|
||||
|
||||
deviceClassHue.setStateTypes(hueStates);
|
||||
|
||||
QList<ActionType> hueActons;
|
||||
|
||||
ActionType setColorAction(setHueColorActionTypeId);
|
||||
setColorAction.setName("Set color");
|
||||
|
||||
QList<ParamType> actionParamsSetColor;
|
||||
ParamType actionParamSetColor("color", QVariant::Color);
|
||||
actionParamsSetColor.append(actionParamSetColor);
|
||||
setColorAction.setParameters(actionParamsSetColor);
|
||||
|
||||
hueActons.append(setColorAction);
|
||||
|
||||
deviceClassHue.setActions(hueActons);
|
||||
|
||||
ret.append(deviceClassHue);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DeviceManager::HardwareResources DevicePluginPhilipsHue::requiredHardware() const
|
||||
{
|
||||
return DeviceManager::HardwareResourceNone;
|
||||
}
|
||||
|
||||
bool DevicePluginPhilipsHue::configureAutoDevice(QList<Device *> loadedDevices, Device *device) const
|
||||
{
|
||||
// if (!m_bobClient->connected()) {
|
||||
// return false;
|
||||
// }
|
||||
// if (loadedDevices.count() < m_bobClient->lightsCount()) {
|
||||
// int index = loadedDevices.count();
|
||||
// device->setName("Boblight Channel " + QString::number(index));
|
||||
// QList<Param> params;
|
||||
// Param param("channel");
|
||||
// param.setValue(index);
|
||||
// params.append(param);
|
||||
// device->setParams(params);
|
||||
// device->setStateValue(colorStateTypeId, m_bobClient->currentColor(index));
|
||||
// return true;
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
QString DevicePluginPhilipsHue::pluginName() const
|
||||
{
|
||||
return "Philips Hue";
|
||||
}
|
||||
|
||||
PluginId DevicePluginPhilipsHue::pluginId() const
|
||||
{
|
||||
return huePluginUuid;
|
||||
}
|
||||
|
||||
QList<ParamType> DevicePluginPhilipsHue::configurationDescription() const
|
||||
{
|
||||
QList<ParamType> params;
|
||||
return params;
|
||||
}
|
||||
|
||||
DeviceManager::DeviceError DevicePluginPhilipsHue::discoverDevices(const DeviceClassId &deviceClassId, const QVariantMap ¶ms) const
|
||||
{
|
||||
m_discovery->findBridges(4000);
|
||||
return DeviceManager::DeviceErrorAsync;
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> DevicePluginPhilipsHue::confirmPairing(const QUuid &pairingTransactionId, const DeviceClassId &deviceClassId, const QList<Param> ¶ms)
|
||||
{
|
||||
Param ipParam;
|
||||
foreach (const Param ¶m, params) {
|
||||
if (param.name() == "ip") {
|
||||
ipParam = param;
|
||||
}
|
||||
}
|
||||
if (!ipParam.isValid()) {
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusFailure, "Missing parameter: ip");
|
||||
}
|
||||
|
||||
QString username = "guh-" + QUuid::createUuid().toString().remove(QRegExp("[\\{\\}]*")).remove(QRegExp("\\-[0-9a-f\\-]*"));
|
||||
|
||||
QVariantMap createUserParams;
|
||||
createUserParams.insert("devicetype", "guh");
|
||||
createUserParams.insert("username", username);
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(createUserParams);
|
||||
QByteArray data = jsonDoc.toJson();
|
||||
|
||||
QNetworkRequest request(QUrl("http://" + ipParam.value().toString() + "/api"));
|
||||
QNetworkReply *reply = m_nam->post(request, data);
|
||||
connect(reply, &QNetworkReply::finished, this, &DevicePluginPhilipsHue::createUserFinished);
|
||||
|
||||
HueBridgeConnection *bridge = new HueBridgeConnection(QHostAddress(ipParam.value().toString()), username);
|
||||
m_pairings.insert(reply, qMakePair<QUuid, HueBridgeConnection*>(pairingTransactionId, bridge));
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusAsync);
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> DevicePluginPhilipsHue::executeAction(Device *device, const Action &action)
|
||||
{
|
||||
// if (!m_bobClient->connected()) {
|
||||
return report(DeviceManager::DeviceErrorSetupFailed, device->id().toString());
|
||||
// }
|
||||
// QColor newColor = action.param("color").value().value<QColor>();
|
||||
// if (!newColor.isValid()) {
|
||||
// return report(DeviceManager::DeviceErrorActionParameterError, "color");
|
||||
// }
|
||||
// qDebug() << "executing boblight action" << newColor;
|
||||
// m_bobClient->setColor(device->paramValue("channel").toInt(), newColor);
|
||||
// m_bobClient->sync();
|
||||
|
||||
// device->setStateValue(colorStateTypeId, newColor);
|
||||
// return report();
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::discoveryDone(const QList<QHostAddress> &bridges)
|
||||
{
|
||||
qDebug() << "discovered bridges" << bridges.count();
|
||||
QList<DeviceDescriptor> deviceDescriptors;
|
||||
foreach (const QHostAddress &bridge, bridges) {
|
||||
DeviceDescriptor descriptor(hueDeviceClassId, "Philips Hue bridge", bridge.toString());
|
||||
QList<Param> params;
|
||||
Param param("ip", bridge.toString());
|
||||
params.append(param);
|
||||
descriptor.setParams(params);
|
||||
deviceDescriptors.append(descriptor);
|
||||
}
|
||||
|
||||
emit devicesDiscovered(hueDeviceClassId, deviceDescriptors);
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::createUserFinished()
|
||||
{
|
||||
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
QPair<QUuid, HueBridgeConnection*> pair = m_pairings.take(reply);
|
||||
QUuid pairingTransactionId = pair.first;
|
||||
HueBridgeConnection *bridge = pair.second;
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
emit pairingFinished(pairingTransactionId, DeviceManager::DeviceSetupStatusFailure, "Pairing failed. Failed to parse response from Hue Bridge.");
|
||||
delete bridge;
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap response = jsonDoc.toVariant().toList().first().toMap();
|
||||
|
||||
if (response.contains("error")) {
|
||||
qDebug() << "Failed to pair Hue bridge:" << response.value("error").toMap().value("description");
|
||||
emit pairingFinished(pairingTransactionId, DeviceManager::DeviceSetupStatusFailure, "Pairing failed:" + response.value("error").toMap().value("description").toString());
|
||||
delete bridge;
|
||||
return;
|
||||
}
|
||||
|
||||
emit pairingFinished(pairingTransactionId, DeviceManager::DeviceSetupStatusSuccess, QString());
|
||||
|
||||
m_bridges.append(bridge);
|
||||
qDebug() << "response" << response << data;
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 DEVICEPLUGINPHILIPSHUE_H
|
||||
#define DEVICEPLUGINPHILIPSHUE_H
|
||||
|
||||
#include "plugin/deviceplugin.h"
|
||||
#include "discovery.h"
|
||||
#include "huebridgeconnection.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
|
||||
class DevicePluginPhilipsHue: public DevicePlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "devicepluginphilipshue.json")
|
||||
Q_INTERFACES(DevicePlugin)
|
||||
|
||||
public:
|
||||
explicit DevicePluginPhilipsHue();
|
||||
|
||||
QList<Vendor> supportedVendors() const override;
|
||||
QList<DeviceClass> supportedDevices() const override;
|
||||
DeviceManager::HardwareResources requiredHardware() const override;
|
||||
|
||||
bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const override;
|
||||
|
||||
QString pluginName() const override;
|
||||
PluginId pluginId() const override;
|
||||
|
||||
QList<ParamType> configurationDescription() const override;
|
||||
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const QVariantMap ¶ms) const override;
|
||||
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> confirmPairing(const QUuid &pairingTransactionId, const DeviceClassId &deviceClassId, const QList<Param> ¶ms) override;
|
||||
|
||||
public slots:
|
||||
QPair<DeviceManager::DeviceError, QString> executeAction(Device *device, const Action &action);
|
||||
|
||||
private slots:
|
||||
void discoveryDone(const QList<QHostAddress> &bridges);
|
||||
|
||||
void createUserFinished();
|
||||
|
||||
private:
|
||||
QList<Param> m_config;
|
||||
Discovery *m_discovery;
|
||||
QNetworkAccessManager *m_nam;
|
||||
|
||||
QHash<QNetworkReply*, QPair<QUuid, HueBridgeConnection*> > m_pairings;
|
||||
|
||||
QList<HueBridgeConnection*> m_bridges;
|
||||
};
|
||||
|
||||
#endif // DEVICEPLUGINBOBLIGHT_H
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright 2013 Christian Muehlhaeuser
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 2.
|
||||
*
|
||||
* This program 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Christian Muehlhaeuser <muesli@gmail.com>
|
||||
*/
|
||||
|
||||
#include "discovery.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
Discovery::Discovery(QObject *parent) :
|
||||
QUdpSocket(parent),
|
||||
m_timeout(new QTimer(this))
|
||||
{
|
||||
quint16 port = 1900;
|
||||
unsigned int tries = 0;
|
||||
const unsigned int maxtries = 10;
|
||||
|
||||
while (!bind(port++)) {
|
||||
if (++tries == maxtries) {
|
||||
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
|
||||
|
||||
m_timeout->setSingleShot(true);
|
||||
connect(m_timeout, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||
}
|
||||
|
||||
bool Discovery::findBridges(int timeout)
|
||||
{
|
||||
m_timeout->stop();
|
||||
m_reportedBridges.clear();
|
||||
|
||||
QString b("M-SEARCH * HTTP/1.1\r\n"
|
||||
"HOST: 239.255.255.250:1900\r\n"
|
||||
"MAN: \"ssdp:discover\"\r\n"
|
||||
"MX: %1\r\n"
|
||||
"ST: libhue:idl\r\n");
|
||||
b.arg(timeout / 1000);
|
||||
|
||||
// qDebug() << "writing datagram" << b;
|
||||
m_timeout->start(timeout);
|
||||
if (writeDatagram(b.toUtf8(), QHostAddress("239.255.255.250"), 1900) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Discovery::onTimeout()
|
||||
{
|
||||
emit discoveryDone(m_reportedBridges);
|
||||
}
|
||||
|
||||
void Discovery::onReadyRead()
|
||||
{
|
||||
while (hasPendingDatagrams()) {
|
||||
QByteArray datagram;
|
||||
datagram.resize(pendingDatagramSize());
|
||||
QHostAddress sender;
|
||||
quint16 senderPort;
|
||||
|
||||
readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
|
||||
|
||||
// qDebug() << "got datagram" << datagram;
|
||||
if (!m_reportedBridges.contains(sender)) {
|
||||
m_reportedBridges << sender;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2013 Christian Muehlhaeuser
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; version 2.
|
||||
*
|
||||
* This program 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Christian Muehlhaeuser <muesli@gmail.com>
|
||||
* Michael Zanetti <michael_zanetti@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef DISCOVERY_H
|
||||
#define DISCOVERY_H
|
||||
|
||||
#include <QUdpSocket>
|
||||
#include <QHostAddress>
|
||||
|
||||
class QTimer;
|
||||
|
||||
class Discovery: public QUdpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Discovery(QObject *parent);
|
||||
bool findBridges(int timeout);
|
||||
|
||||
signals:
|
||||
void error();
|
||||
void discoveryDone(QList<QHostAddress> bridges);
|
||||
|
||||
private slots:
|
||||
void onTimeout();
|
||||
void onReadyRead();
|
||||
|
||||
private:
|
||||
QList<QHostAddress> m_reportedBridges;
|
||||
QTimer *m_timeout;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 "huebridgeconnection.h"
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
HueBridgeConnection::HueBridgeConnection(const QHostAddress &address, const QString &username, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_address(address),
|
||||
m_username(username)
|
||||
{
|
||||
}
|
||||
|
||||
QString HueBridgeConnection::username() const
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
|
||||
QHostAddress HueBridgeConnection::address() const
|
||||
{
|
||||
return m_address;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* 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 HUEBRIDGECONNECTION_H
|
||||
#define HUEBRIDGECONNECTION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHostAddress>
|
||||
|
||||
class HueBridgeConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HueBridgeConnection(const QHostAddress &address, const QString &username = QString(), QObject *parent = 0);
|
||||
|
||||
QHostAddress address() const;
|
||||
QString username() const;
|
||||
|
||||
private:
|
||||
QHostAddress m_address;
|
||||
QString m_username;
|
||||
};
|
||||
|
||||
#endif // HUEBRIDGECONNECTION_H
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
include(../../plugins.pri)
|
||||
|
||||
TARGET = $$qtLibraryTarget(guh_devicepluginphilipshue)
|
||||
|
||||
QT += network
|
||||
|
||||
SOURCES += \
|
||||
devicepluginphilipshue.cpp \
|
||||
discovery.cpp \
|
||||
huebridgeconnection.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginphilipshue.h \
|
||||
discovery.h \
|
||||
huebridgeconnection.h
|
||||
|
||||
|
||||
|
||||
|
|
@ -77,7 +77,12 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setReturns("SetPluginConfiguration", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("AddConfiguredDevice", "Add a configured device. Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class.");
|
||||
setDescription("AddConfiguredDevice", "Add a configured device with a setupMethod of SetupMethodJustAdd. "
|
||||
"For devices with a setupMethod different than SetupMethodJustAdd, use PairDevice. "
|
||||
"Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. "
|
||||
"CreateMethodJustAdd takes the parameters you want to have with that device. "
|
||||
"CreateMethodDiscovery requires the use of a deviceDescriptorId."
|
||||
);
|
||||
params.insert("deviceClassId", "uuid");
|
||||
params.insert("o:deviceDescriptorId", "uuid");
|
||||
QVariantList deviceParams;
|
||||
|
|
@ -89,6 +94,34 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
returns.insert("o:deviceId", "uuid");
|
||||
setReturns("AddConfiguredDevice", returns);
|
||||
|
||||
returns.clear(); // Reused params from above!
|
||||
setDescription("PairDevice", "Pair a device. "
|
||||
"Use this for DeviceClasses with a setupMethod different than SetupMethodJustAdd."
|
||||
"Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. "
|
||||
"CreateMethodJustAdd takes the parameters you want to have with that device. "
|
||||
"CreateMethodDiscovery requires the use of a deviceDescriptorId. "
|
||||
"If success is true, the return values will contain a pairingTransactionId, a displayMessage and "
|
||||
"the setupMethod. Depending on the setupMethod you should either proceed with AddConfiguredDevice "
|
||||
" or PairDevice."
|
||||
);
|
||||
setParams("PairDevice", params);
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
returns.insert("o:pairingTransactionId", "uuid");
|
||||
returns.insert("o:displayMessage", "string");
|
||||
returns.insert("o:setupMethod", JsonTypes::setupMethodTypesRef());
|
||||
setReturns("PairDevice", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("ConfirmPairing", "Confirm an ongoing pairing. In case of SetupMethodEnterPin also provide the pin in the params.");
|
||||
params.insert("pairingTransactionId", "uuid");
|
||||
params.insert("o:secret", "string");
|
||||
setParams("ConfirmPairing", params);
|
||||
returns.insert("success", "bool");
|
||||
returns.insert("errorMessage", "string");
|
||||
returns.insert("o:deviceId", "uuid");
|
||||
setReturns("ConfirmPairing", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("GetConfiguredDevices", "Returns a list of configured devices.");
|
||||
setParams("GetConfiguredDevices", params);
|
||||
|
|
@ -165,8 +198,9 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
|||
setParams("StateChanged", params);
|
||||
|
||||
connect(GuhCore::instance()->deviceManager(), &DeviceManager::deviceStateChanged, this, &DeviceHandler::deviceStateChanged);
|
||||
connect(GuhCore::instance()->deviceManager(), &DeviceManager::devicesDiscovered, this, &DeviceHandler::devicesDiscovered);
|
||||
connect(GuhCore::instance()->deviceManager(), &DeviceManager::devicesDiscovered, this, &DeviceHandler::devicesDiscovered, Qt::QueuedConnection);
|
||||
connect(GuhCore::instance()->deviceManager(), &DeviceManager::deviceSetupFinished, this, &DeviceHandler::deviceSetupFinished);
|
||||
connect(GuhCore::instance()->deviceManager(), &DeviceManager::pairingFinished, this, &DeviceHandler::pairingFinished);
|
||||
}
|
||||
|
||||
QString DeviceHandler::name() const
|
||||
|
|
@ -211,6 +245,7 @@ JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap ¶ms) const
|
|||
|
||||
DeviceManager::DeviceError status = GuhCore::instance()->deviceManager()->discoverDevices(deviceClassId, params.value("discoveryParams").toMap());
|
||||
switch (status) {
|
||||
case DeviceManager::DeviceErrorAsync:
|
||||
case DeviceManager::DeviceErrorNoError: {
|
||||
JsonReply *reply = createAsyncReply("GetDiscoveredDevices");
|
||||
m_discoverRequests.insert(deviceClassId, reply);
|
||||
|
|
@ -352,6 +387,79 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms)
|
|||
return createReply(returns);
|
||||
}
|
||||
|
||||
JsonReply *DeviceHandler::PairDevice(const QVariantMap ¶ms)
|
||||
{
|
||||
DeviceClassId deviceClassId(params.value("deviceClassId").toString());
|
||||
DeviceClass deviceClass = GuhCore::instance()->deviceManager()->findDeviceClass(deviceClassId);
|
||||
|
||||
QPair<DeviceManager::DeviceError, QString> status;
|
||||
if (params.contains("deviceDescriptorId")) {
|
||||
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
|
||||
status = GuhCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceDescriptorId);
|
||||
} else {
|
||||
QList<Param> deviceParams;
|
||||
foreach (const QString ¶mName, params.value("deviceParams").toMap().keys()) {
|
||||
Param param(paramName);
|
||||
param.setValue(params.value("deviceParams").toMap().value(paramName));
|
||||
deviceParams.append(param);
|
||||
}
|
||||
status = GuhCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceParams);
|
||||
}
|
||||
|
||||
QVariantMap returns;
|
||||
switch (status.first) {
|
||||
case DeviceManager::DeviceErrorNoError:
|
||||
returns.insert("success", true);
|
||||
returns.insert("errorMessage", "");
|
||||
returns.insert("displayMessage", deviceClass.pairingInfo());
|
||||
returns.insert("pairingTransactionId", status.second);
|
||||
returns.insert("setupMethod", JsonTypes::setupMethodTypes().at(deviceClass.setupMethod()));
|
||||
break;
|
||||
case DeviceManager::DeviceErrorDeviceClassNotFound:
|
||||
returns.insert("errorMessage", QString("Error pairing device. Device class not found: %1").arg(status.second));
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorDeviceDescriptorNotFound:
|
||||
returns.insert("errorMessage", QString("Error pairing device. Device descriptor not found: %1").arg(status.second));
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorCreationMethodNotSupported:
|
||||
returns.insert("errorMessage", QString("Error pairing device. This device can't be created this way: %1").arg(status.second));
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
case DeviceManager::DeviceErrorPairingTransactionIdNotFound:
|
||||
returns.insert("errorMessage", QString("Error pairing device. PairingTransactionId not found: %1").arg(status.second));
|
||||
returns.insert("success", false);
|
||||
break;
|
||||
}
|
||||
return createReply(returns);
|
||||
}
|
||||
|
||||
JsonReply *DeviceHandler::ConfirmPairing(const QVariantMap ¶ms)
|
||||
{
|
||||
QUuid pairingTransactionId = params.value("pairingTransactionId").toUuid();
|
||||
QString secret = params.value("secret").toString();
|
||||
QPair<DeviceManager::DeviceError, QString> status = GuhCore::instance()->deviceManager()->confirmPairing(pairingTransactionId, secret);
|
||||
|
||||
JsonReply *reply = 0;
|
||||
QVariantMap returns;
|
||||
switch (status.first) {
|
||||
case DeviceManager::DeviceErrorAsync:
|
||||
reply = createAsyncReply("ConfirmPairing");
|
||||
m_asyncPairingRequests.insert(pairingTransactionId, reply);
|
||||
return reply;
|
||||
case DeviceManager::DeviceErrorNoError:
|
||||
returns.insert("success", true);
|
||||
returns.insert("errorMessage", QString());
|
||||
case DeviceManager::DeviceErrorSetupFailed:
|
||||
default:
|
||||
returns.insert("success", false);
|
||||
returns.insert("errorMessage", status.second);
|
||||
}
|
||||
reply = createReply(returns);
|
||||
return reply;
|
||||
}
|
||||
|
||||
JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const
|
||||
{
|
||||
Q_UNUSED(params)
|
||||
|
|
@ -503,3 +611,24 @@ void DeviceHandler::deviceSetupFinished(Device *device, DeviceManager::DeviceErr
|
|||
reply->setData(returns);
|
||||
reply->finished();
|
||||
}
|
||||
|
||||
void DeviceHandler::pairingFinished(const QUuid &pairingTransactionId, DeviceManager::DeviceError status, const QString &errorMessage, const DeviceId &deviceId)
|
||||
{
|
||||
qDebug() << "handler: pairing finished";
|
||||
JsonReply *reply = m_asyncPairingRequests.take(pairingTransactionId);
|
||||
if (!reply) {
|
||||
qDebug() << "not for me";
|
||||
return;
|
||||
}
|
||||
QVariantMap returns;
|
||||
if (status == DeviceManager::DeviceErrorNoError) {
|
||||
returns.insert("success", true);
|
||||
returns.insert("errorMessage", QString());
|
||||
returns.insert("deviceId", deviceId.toString());
|
||||
} else {
|
||||
returns.insert("success", false);
|
||||
returns.insert("errorMessage", errorMessage);
|
||||
}
|
||||
reply->setData(returns);
|
||||
reply->finished();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ public:
|
|||
|
||||
Q_INVOKABLE JsonReply* AddConfiguredDevice(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE JsonReply* PairDevice(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE JsonReply* ConfirmPairing(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE JsonReply* GetConfiguredDevices(const QVariantMap ¶ms) const;
|
||||
|
||||
Q_INVOKABLE JsonReply* RemoveConfiguredDevice(const QVariantMap ¶ms);
|
||||
|
|
@ -66,10 +70,13 @@ private slots:
|
|||
|
||||
void deviceSetupFinished(Device *device, DeviceManager::DeviceError status);
|
||||
|
||||
void pairingFinished(const QUuid &pairingTransactionId, DeviceManager::DeviceError status, const QString &errorMessage, const DeviceId &deviceId);
|
||||
|
||||
private:
|
||||
// A cache for async replies
|
||||
mutable QHash<DeviceClassId, JsonReply*> m_discoverRequests;
|
||||
mutable QHash<DeviceId, JsonReply*> m_asynDeviceAdditions;
|
||||
mutable QHash<QUuid, JsonReply*> m_asyncPairingRequests;
|
||||
};
|
||||
|
||||
#endif // DEVICEHANDLER_H
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#include <QJsonDocument>
|
||||
#include <QStringList>
|
||||
|
||||
#define JSON_PROTOCOL_VERSION 1
|
||||
#define JSON_PROTOCOL_VERSION 2
|
||||
|
||||
JsonRPCServer::JsonRPCServer(QObject *parent):
|
||||
JsonHandler(parent),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ Q_IMPORT_PLUGIN(DevicePluginOpenweathermap)
|
|||
Q_IMPORT_PLUGIN(DevicePluginLircd)
|
||||
Q_IMPORT_PLUGIN(DevicePluginWakeOnLan)
|
||||
Q_IMPORT_PLUGIN(DevicePluginMailNotification)
|
||||
Q_IMPORT_PLUGIN(DevicePluginPhilipsHue)
|
||||
|
||||
#if USE_BOBLIGHT
|
||||
Q_IMPORT_PLUGIN(DevicePluginBoblight)
|
||||
|
|
|
|||
|
|
@ -144,7 +144,10 @@ RuleEngine::RuleEngine(QObject *parent) :
|
|||
list of all \l{Action}{Actions} that should be executed. */
|
||||
QList<Action> RuleEngine::evaluateEvent(const Event &event)
|
||||
{
|
||||
qDebug() << "got event:" << event;
|
||||
Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(event.deviceId());
|
||||
|
||||
qDebug() << "got event:" << event << device->name();
|
||||
|
||||
QList<Action> actions;
|
||||
for (int i = 0; i < m_rules.count(); ++i) {
|
||||
qDebug() << "evaluating rule" << i << m_rules.at(i).eventDescriptors();
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ LIBS += -L../plugins/deviceplugins/openweathermap -lguh_devicepluginopenweatherm
|
|||
LIBS += -L../plugins/deviceplugins/lircd -lguh_devicepluginlircd
|
||||
LIBS += -L../plugins/deviceplugins/mailnotification -lguh_devicepluginmailnotification
|
||||
LIBS += -L../plugins/deviceplugins/wakeonlan -lguh_devicepluginwakeonlan
|
||||
LIBS += -L../plugins/deviceplugins/philipshue -lguh_devicepluginphilipshue
|
||||
|
||||
boblight {
|
||||
xcompile {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
1
|
||||
2
|
||||
{
|
||||
"methods": {
|
||||
"Actions.ExecuteAction": {
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
},
|
||||
"Devices.AddConfiguredDevice": {
|
||||
"description": "Add a configured device. Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class.",
|
||||
"description": "Add a configured device with a setupMethod of SetupMethodJustAdd. For devices with a setupMethod different than SetupMethodJustAdd, use PairDevice. Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. CreateMethodJustAdd takes the parameters you want to have with that device. CreateMethodDiscovery requires the use of a deviceDescriptorId.",
|
||||
"params": {
|
||||
"deviceClassId": "uuid",
|
||||
"o:deviceDescriptorId": "uuid",
|
||||
|
|
@ -47,6 +47,18 @@
|
|||
"success": "bool"
|
||||
}
|
||||
},
|
||||
"Devices.ConfirmPairing": {
|
||||
"description": "Confirm an ongoing pairing. In case of SetupMethodEnterPin also provide the pin in the params.",
|
||||
"params": {
|
||||
"o:secret": "string",
|
||||
"pairingTransactionId": "uuid"
|
||||
},
|
||||
"returns": {
|
||||
"errorMessage": "string",
|
||||
"o:deviceId": "uuid",
|
||||
"success": "bool"
|
||||
}
|
||||
},
|
||||
"Devices.GetActionTypes": {
|
||||
"description": "Get action types for a specified deviceClassId.",
|
||||
"params": {
|
||||
|
|
@ -162,6 +174,23 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"Devices.PairDevice": {
|
||||
"description": "Pair a device. Use this for DeviceClasses with a setupMethod different than SetupMethodJustAdd.Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. CreateMethodJustAdd takes the parameters you want to have with that device. CreateMethodDiscovery requires the use of a deviceDescriptorId. If success is true, the return values will contain a pairingTransactionId, a displayMessage and the setupMethod. Depending on the setupMethod you should either proceed with AddConfiguredDevice or PairDevice.",
|
||||
"params": {
|
||||
"deviceClassId": "uuid",
|
||||
"o:deviceDescriptorId": "uuid",
|
||||
"o:deviceParams": [
|
||||
"$ref:Param"
|
||||
]
|
||||
},
|
||||
"returns": {
|
||||
"errorMessage": "string",
|
||||
"o:displayMessage": "string",
|
||||
"o:pairingTransactionId": "uuid",
|
||||
"o:setupMethod": "$ref:SetupMethodType",
|
||||
"success": "bool"
|
||||
}
|
||||
},
|
||||
"Devices.RemoveConfiguredDevice": {
|
||||
"description": "Remove a device from the system.",
|
||||
"params": {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,225 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import telnetlib
|
||||
import json
|
||||
|
||||
HOST='localhost'
|
||||
PORT=1234
|
||||
commandId=0
|
||||
|
||||
methods = {'List supported Vendors': 'list_vendors',
|
||||
'List supported Devices': 'list_deviceClasses',
|
||||
'List configured Devices': 'list_configured_devices',
|
||||
'Add Device': 'add_device',
|
||||
'Remove a device': 'remove_device',
|
||||
'List supported Devices by vendor': 'list_deviceClasses_by_vendor' }
|
||||
|
||||
|
||||
def get_selection(title, options):
|
||||
print "\n\n", title
|
||||
for i in range(0,len(options)):
|
||||
print "%i: %s" % (i, options[i])
|
||||
selection = raw_input("Enter selection: ")
|
||||
return int(selection)
|
||||
|
||||
def send_command(method, params = None):
|
||||
global commandId
|
||||
if params == None or len(params) == 0:
|
||||
command = '{"id": %i, "method":"%s"}\n' % (commandId, method)
|
||||
else:
|
||||
paramString = ""
|
||||
for i in range(0, len(params)):
|
||||
if paramString != "":
|
||||
paramString = paramString + ", "
|
||||
paramKey = params.keys()[i]
|
||||
paramString = paramString + ('"%s":"%s"' % (paramKey, params[paramKey].encode('utf-8')))
|
||||
command = '{"id": %i, "method":"%s", "params":{%s}}\n' % (commandId, method, paramString)
|
||||
|
||||
commandId = commandId + 1
|
||||
tn.write(command)
|
||||
response = json.loads(tn.read_until("\n}\n"))
|
||||
if response['status'] != "success":
|
||||
print "JSON error happened: %s" % response
|
||||
return response
|
||||
|
||||
def get_vendors():
|
||||
return send_command("Devices.GetSupportedVendors")
|
||||
|
||||
def list_vendors():
|
||||
response = get_vendors();
|
||||
print "=== Vendors ==="
|
||||
for vendor in response['params']['vendors']:
|
||||
print "%40s %s" % (vendor['name'], vendor['id'])
|
||||
print "=== Vendors ==="
|
||||
|
||||
def select_vendor():
|
||||
vendors = get_vendors()['params']['vendors']
|
||||
vendorList = []
|
||||
vendorIdList = []
|
||||
for i in range(0,len(vendors)):
|
||||
vendorList.append(vendors[i]['name'])
|
||||
vendorIdList.append(vendors[i]['id'])
|
||||
selection = get_selection("Please select vendor", vendorList)
|
||||
return vendorIdList[selection]
|
||||
|
||||
def get_deviceClasses(vendorId = None):
|
||||
params = {};
|
||||
if vendorId != None:
|
||||
params['vendorId'] = vendorId
|
||||
return send_command("Devices.GetSupportedDevices", params)['params']['deviceClasses']
|
||||
|
||||
def list_deviceClasses(vendorId = None):
|
||||
response = get_deviceClasses(vendorId)
|
||||
print "=== Devices ==="
|
||||
for deviceClass in response:
|
||||
print "%40s %s" % (deviceClass['name'], deviceClass['id'])
|
||||
print "=== Devices ==="
|
||||
|
||||
def select_deviceClass():
|
||||
vendorId = select_vendor()
|
||||
deviceClasses = get_deviceClasses(vendorId)
|
||||
if len(deviceClasses) == 0:
|
||||
print "No supported devices for this vendor"
|
||||
return ""
|
||||
deviceClassList = []
|
||||
deviceClassIdList = []
|
||||
for i in range(0,len(deviceClasses)):
|
||||
deviceClassList.append(deviceClasses[i]['name'])
|
||||
deviceClassIdList.append(deviceClasses[i]['id'])
|
||||
selection = get_selection("Please select device class", deviceClassList)
|
||||
return deviceClassIdList[selection]
|
||||
|
||||
def list_deviceClasses_by_vendor():
|
||||
vendorId = select_vendor()
|
||||
list_deviceClasses(vendorId)
|
||||
|
||||
def get_configured_devices():
|
||||
return send_command("Devices.GetConfiguredDevices")['params']['devices']
|
||||
|
||||
def list_configured_devices():
|
||||
deviceList = get_configured_devices()
|
||||
print "=== Configured Devices ==="
|
||||
for device in deviceList:
|
||||
print "Name: %40s, ID: %s, DeviceClassID: %s" % (device['name'], device['id'], device['deviceClassId'])
|
||||
print "=== Configured Devices ==="
|
||||
|
||||
|
||||
def discover_device(deviceClassId = None):
|
||||
if deviceClassId == None:
|
||||
deviceClassId = select_deviceClass()
|
||||
params = {}
|
||||
params['deviceClassId'] = deviceClassId
|
||||
print "\ndiscovering..."
|
||||
response = send_command("Devices.GetDiscoveredDevices", params)
|
||||
deviceDescriptorList = [];
|
||||
deviceDescriptorIdList = [];
|
||||
for deviceDescriptor in response['params']['deviceDescriptors']:
|
||||
deviceDescriptorList.append("%s (%s)" % (deviceDescriptor['title'], deviceDescriptor['description']))
|
||||
deviceDescriptorIdList.append(deviceDescriptor['id'])
|
||||
selection = get_selection("Please select a device descriptor", deviceDescriptorList)
|
||||
return deviceDescriptorIdList[selection]
|
||||
|
||||
def get_deviceClass(deviceClassId):
|
||||
deviceClasses = get_deviceClasses()
|
||||
for deviceClass in deviceClasses:
|
||||
# print "got deviceclass", deviceClass
|
||||
if deviceClass['id'] == deviceClassId:
|
||||
return deviceClass
|
||||
return None
|
||||
|
||||
def add_configured_device(deviceClassId):
|
||||
params = {}
|
||||
params['deviceClassId'] = deviceClassId
|
||||
response = send_command("Devices.AddConfiguredDevice", params)
|
||||
if response['params']['success'] != "true":
|
||||
print "Error executing method: %s" % response['params']['errorMessage']
|
||||
return
|
||||
print "Added device: %s" % response['params']['deviceId']
|
||||
|
||||
def add_discovered_device(deviceClassId, deviceDescriptorId):
|
||||
params = {}
|
||||
params['deviceClassId'] = deviceClassId
|
||||
params['deviceDescriptorId'] = deviceDescriptorId
|
||||
|
||||
deviceClass = get_deviceClass(deviceClassId)
|
||||
if deviceClass['setupMethod'] == "SetupMethodJustAdd":
|
||||
response = send_command("Devices.AddConfiguredDevice", params)
|
||||
if not response['params']['success']:
|
||||
print "Adding device failed: %s" % response['params']['errorMessage']
|
||||
else:
|
||||
print "Device added successfully. Device ID: %s" % response['params']['deviceId']
|
||||
else:
|
||||
params = {}
|
||||
params['deviceClassId'] = deviceClassId
|
||||
params['deviceDescriptorId'] = deviceDescriptorId
|
||||
response = send_command("Devices.PairDevice", params)
|
||||
print "pairdevice response:", response
|
||||
if not response['params']['success']:
|
||||
print "Pairing failed: %s", response['params']['errorMessage']
|
||||
return
|
||||
else:
|
||||
print "\nPairing device %s\n\n%s" % (deviceClass['name'], response['params']['displayMessage'])
|
||||
if response['params']['setupMethod'] == "SetupMethodPushButton":
|
||||
raw_input("Press enter to confirm")
|
||||
|
||||
params = {}
|
||||
params['pairingTransactionId'] = response['params']['pairingTransactionId']
|
||||
response = send_command("Devices.ConfirmPairing", params)
|
||||
if response['params']['success']:
|
||||
success = True
|
||||
print "Device paired successfully"
|
||||
else:
|
||||
print "Error pairing device: %s" % response['params']['errorMessage']
|
||||
|
||||
|
||||
def add_device():
|
||||
deviceClassId = select_deviceClass()
|
||||
if deviceClassId == "":
|
||||
print "Empty deviceClass. Can't continue"
|
||||
return
|
||||
deviceClass = get_deviceClass(deviceClassId)
|
||||
print "createmethod is", deviceClass['createMethod']
|
||||
if deviceClass['createMethod'] == "CreateMethodUser":
|
||||
add_configured_device(deviceClassId)
|
||||
elif deviceClass['createMethod'] == "CreateMethodDiscovery":
|
||||
deviceDescriptorId = discover_device(deviceClassId)
|
||||
add_discovered_device(deviceClassId, deviceDescriptorId)
|
||||
elif deviceClass['createMethod'] == "CreateMethodAuto":
|
||||
print "Can't create this device manually. It'll be created automatically when hardware is discovered."
|
||||
|
||||
def select_device():
|
||||
devices = get_configured_devices()
|
||||
deviceList = []
|
||||
deviceIdList = []
|
||||
for i in range(len(devices)):
|
||||
deviceList.append(devices[i]['name'])
|
||||
deviceIdList.append(devices[i]['id'])
|
||||
selection = get_selection("Please select a device", deviceList)
|
||||
return deviceIdList[selection]
|
||||
|
||||
def remove_device():
|
||||
deviceId = select_device()
|
||||
print "should remove device", deviceId
|
||||
params = {}
|
||||
params['deviceId'] = deviceId
|
||||
response = send_command("Devices.RemoveConfiguredDevice", params)
|
||||
if response['params']['success']:
|
||||
print "Successfully deleted device"
|
||||
else:
|
||||
print "Error deleting device %s" % deviceId
|
||||
|
||||
|
||||
tn = telnetlib.Telnet(HOST, PORT)
|
||||
packet = tn.read_until("\n}\n")
|
||||
|
||||
packet = json.loads(packet)
|
||||
print "connected to", packet["server"], "\nserver version:", packet["version"], "\nprotocol version:", packet["protocol version"], "\n"
|
||||
|
||||
while True:
|
||||
selection = get_selection("What do you want to do?", methods.keys())
|
||||
selectionKey = methods.keys()
|
||||
methodName = methods[methods.keys()[selection]]
|
||||
methodToCall = globals()[methods[methods.keys()[selection]]]
|
||||
methodToCall()
|
||||
|
||||
|
||||
Loading…
Reference in New Issue