rework how auto devices are created
also updated plugins to work with new api
This commit is contained in:
parent
1c00b4c3f9
commit
ac77fc669c
@ -106,7 +106,7 @@ DeviceManager::DeviceManager(QObject *parent) :
|
||||
// Give hardware a chance to start up before loading plugins etc.
|
||||
QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, "loadConfiguredDevices", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, "createNewAutoDevices", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, "startMonitoringAutoDevices", Qt::QueuedConnection);
|
||||
// Make sure this is always emitted after plugins and devices are loaded
|
||||
QMetaObject::invokeMethod(this, "loaded", Qt::QueuedConnection);
|
||||
}
|
||||
@ -149,7 +149,6 @@ QPair<DeviceManager::DeviceError, QString> DeviceManager::setPluginConfig(const
|
||||
}
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
createNewAutoDevices();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -540,6 +539,7 @@ void DeviceManager::loadPlugins()
|
||||
connect(pluginIface, &DevicePlugin::deviceSetupFinished, this, &DeviceManager::slotDeviceSetupFinished);
|
||||
connect(pluginIface, &DevicePlugin::actionExecutionFinished, this, &DeviceManager::actionExecutionFinished);
|
||||
connect(pluginIface, &DevicePlugin::pairingFinished, this, &DeviceManager::slotPairingFinished);
|
||||
connect(pluginIface, &DevicePlugin::autoDevicesAppeared, this, &DeviceManager::autoDevicesAppeared);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -595,36 +595,10 @@ void DeviceManager::storeConfiguredDevices()
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void DeviceManager::createNewAutoDevices()
|
||||
void DeviceManager::startMonitoringAutoDevices()
|
||||
{
|
||||
bool haveNewDevice = false;
|
||||
foreach (const DeviceClass &deviceClass, m_supportedDevices) {
|
||||
if (deviceClass.createMethod() != DeviceClass::CreateMethodAuto) {
|
||||
continue;
|
||||
}
|
||||
|
||||
qDebug() << "found auto device class" << deviceClass.name();
|
||||
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
|
||||
bool success = false;
|
||||
do {
|
||||
QList<Device*> loadedDevices = findConfiguredDevices(deviceClass.id());
|
||||
Device *device = new Device(plugin->pluginId(), DeviceId::createDeviceId(), deviceClass.id());
|
||||
success = plugin->configureAutoDevice(loadedDevices, device);
|
||||
if (success) {
|
||||
qDebug() << "New device detected for" << deviceClass.name() << device->name();
|
||||
haveNewDevice = true;
|
||||
|
||||
// We'll always add auto devices, even if setup fails in order to keep track of them.
|
||||
QPair<DeviceSetupStatus, QString> setupStatus = setupDevice(device);
|
||||
m_configuredDevices.append(device);
|
||||
} else {
|
||||
qDebug() << "No newly detected devices for" << deviceClass.name();
|
||||
delete device;
|
||||
}
|
||||
} while (success);
|
||||
}
|
||||
if (haveNewDevice) {
|
||||
storeConfiguredDevices();
|
||||
foreach (DevicePlugin *plugin, m_devicePlugins) {
|
||||
plugin->startMonitoringAutoDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,6 +744,41 @@ void DeviceManager::slotPairingFinished(const QUuid &pairingTransactionId, Devic
|
||||
emit deviceSetupFinished(device, DeviceError::DeviceErrorNoError, QString());
|
||||
}
|
||||
|
||||
void DeviceManager::autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors)
|
||||
{
|
||||
DeviceClass deviceClass = findDeviceClass(deviceClassId);
|
||||
if (!deviceClass.isValid()) {
|
||||
return;
|
||||
}
|
||||
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
|
||||
if (!plugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const DeviceDescriptor &deviceDescriptor, deviceDescriptors) {
|
||||
Device *device = new Device(plugin->pluginId(), deviceClassId, this);
|
||||
device->setName(deviceClass.name());
|
||||
device->setParams(deviceDescriptor.params());
|
||||
|
||||
QPair<DeviceSetupStatus, QString> setupStatus = setupDevice(device);
|
||||
switch (setupStatus.first) {
|
||||
case DeviceSetupStatusFailure:
|
||||
qWarning() << "Device setup failed. Not adding device to system.";
|
||||
emit deviceSetupFinished(device, DeviceError::DeviceErrorSetupFailed, QString("Device setup failed: %1").arg(setupStatus.second));
|
||||
delete device;
|
||||
break;
|
||||
case DeviceSetupStatusAsync:
|
||||
break;
|
||||
case DeviceSetupStatusSuccess:
|
||||
qDebug() << "Device setup complete.";
|
||||
emit deviceSetupFinished(device, DeviceError::DeviceErrorNoError, QString());
|
||||
m_configuredDevices.append(device);
|
||||
storeConfiguredDevices();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value)
|
||||
{
|
||||
Device *device = qobject_cast<Device*>(sender());
|
||||
|
||||
@ -108,10 +108,11 @@ private slots:
|
||||
void loadPlugins();
|
||||
void loadConfiguredDevices();
|
||||
void storeConfiguredDevices();
|
||||
void createNewAutoDevices();
|
||||
void startMonitoringAutoDevices();
|
||||
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);
|
||||
void autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
|
||||
|
||||
// Only connect this to Devices. It will query the sender()
|
||||
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
|
||||
|
||||
@ -127,24 +127,14 @@ DevicePlugin::~DevicePlugin()
|
||||
|
||||
/*! Override this if your plugin supports Device with DeviceClass::CreationMethodAuto.
|
||||
This will be called at startup, after the configured devices have been loaded.
|
||||
You should walk through loadedDevices and check whether all the detected devices
|
||||
are contained in there. If all the detected devices are already contained, return
|
||||
false. If instead you've found a new device which isn't known to the system yet,
|
||||
fill in the parameters of the passed device with some details that makes it possible
|
||||
for you to match this Device object with the detected hardware. After that, return true.
|
||||
The DeviceManager will then insert the device into its database and call setupDevice()
|
||||
for this device. Therefore you should not do any hardware initialisation in this state yet
|
||||
but rather wait for the subsequent setupDevice() call to set it up like in any other
|
||||
case where Device can be created.
|
||||
Returning false will cause the passed device object to be destroyed.
|
||||
If you have detected multiple new devices, just load them one by one. The DeviceManager
|
||||
will continue to call this method until you return false.
|
||||
This is the earliest time you should start emitting autoDevicesAppeared(). If you
|
||||
are monitoring some hardware/service for devices to appear, start monitoring now.
|
||||
If you are building the devices based on a static list, you may emit
|
||||
autoDevicesAppeard() in here.
|
||||
*/
|
||||
bool DevicePlugin::configureAutoDevice(QList<Device*> loadedDevices, Device *device) const
|
||||
void DevicePlugin::startMonitoringAutoDevices()
|
||||
{
|
||||
Q_UNUSED(loadedDevices)
|
||||
Q_UNUSED(device)
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/*! Reimplement this if you support a DeviceClass with createMethod CreateMethodDiscovery.
|
||||
|
||||
@ -49,7 +49,7 @@ public:
|
||||
virtual QList<DeviceClass> supportedDevices() const = 0;
|
||||
virtual DeviceManager::HardwareResources requiredHardware() const = 0;
|
||||
|
||||
virtual bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const;
|
||||
virtual void startMonitoringAutoDevices();
|
||||
virtual DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const QList<Param> ¶ms) const;
|
||||
|
||||
virtual QPair<DeviceManager::DeviceSetupStatus, QString> setupDevice(Device *device);
|
||||
|
||||
@ -89,23 +89,35 @@ DeviceManager::HardwareResources DevicePluginBoblight::requiredHardware() const
|
||||
return DeviceManager::HardwareResourceNone;
|
||||
}
|
||||
|
||||
bool DevicePluginBoblight::configureAutoDevice(QList<Device *> loadedDevices, Device *device) const
|
||||
void DevicePluginBoblight::startMonitoringAutoDevices()
|
||||
{
|
||||
if (!m_bobClient->connected()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
if (loadedDevices.count() < m_bobClient->lightsCount()) {
|
||||
int index = loadedDevices.count();
|
||||
device->setName("Boblight Channel " + QString::number(index));
|
||||
|
||||
QList<Device*> loadedDevices = deviceManager()->findConfiguredDevices(boblightDeviceClassId);
|
||||
|
||||
QList<DeviceDescriptor> deviceDescriptorList;
|
||||
for (int i = loadedDevices.count(); i < m_bobClient->lightsCount(); i++) {
|
||||
DeviceDescriptor deviceDescriptor(boblightDeviceClassId, "Boblight Channel " + QString::number(i));
|
||||
QList<Param> params;
|
||||
Param param("channel");
|
||||
param.setValue(index);
|
||||
param.setValue(i);
|
||||
params.append(param);
|
||||
device->setParams(params);
|
||||
device->setStateValue(colorStateTypeId, m_bobClient->currentColor(index));
|
||||
return true;
|
||||
deviceDescriptor.setParams(params);
|
||||
deviceDescriptorList.append(deviceDescriptor);
|
||||
}
|
||||
return false;
|
||||
emit autoDevicesAppeared(boblightDeviceClassId, deviceDescriptorList);
|
||||
}
|
||||
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> DevicePluginBoblight::setupDevice(Device *device)
|
||||
{
|
||||
if (!m_bobClient->connected()) {
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusFailure, "Cannot connect to Boblight");
|
||||
}
|
||||
|
||||
m_bobClient->currentColor(device->paramValue("channel").toInt());
|
||||
return reportDeviceSetup();
|
||||
}
|
||||
|
||||
QString DevicePluginBoblight::pluginName() const
|
||||
|
||||
@ -39,7 +39,8 @@ public:
|
||||
QList<DeviceClass> supportedDevices() const override;
|
||||
DeviceManager::HardwareResources requiredHardware() const override;
|
||||
|
||||
bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const override;
|
||||
void startMonitoringAutoDevices() override;
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> setupDevice(Device *device) override;
|
||||
|
||||
QString pluginName() const override;
|
||||
PluginId pluginId() const override;
|
||||
|
||||
@ -257,21 +257,19 @@ void DevicePluginMock::deviceRemoved(Device *device)
|
||||
delete m_daemons.take(device);
|
||||
}
|
||||
|
||||
bool DevicePluginMock::configureAutoDevice(QList<Device *> loadedDevices, Device *device) const
|
||||
void DevicePluginMock::startMonitoringAutoDevices()
|
||||
{
|
||||
Q_ASSERT(device->deviceClassId() == mockDeviceAutoClassId);
|
||||
DeviceDescriptor mockDescriptor(mockDeviceAutoClassId, "Mock Device (Auto created)");
|
||||
|
||||
// We only want to have one auto mock device. So if there's already anything in loadedDevices, don't crearte a new one.
|
||||
if (loadedDevices.count() > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
device->setName("Mock Device (Auto created)");
|
||||
QList<Param> params;
|
||||
Param param("httpport", 4242);
|
||||
params.append(param);
|
||||
device->setParams(params);
|
||||
return true;
|
||||
mockDescriptor.setParams(params);
|
||||
|
||||
QList<DeviceDescriptor> deviceDescriptorList;
|
||||
deviceDescriptorList.append(mockDescriptor);
|
||||
|
||||
emit autoDevicesAppeared(mockDeviceAutoClassId, deviceDescriptorList);
|
||||
}
|
||||
|
||||
QList<ParamType> DevicePluginMock::configurationDescription() const
|
||||
|
||||
@ -47,7 +47,7 @@ public:
|
||||
QPair<DeviceManager::DeviceSetupStatus, QString> setupDevice(Device *device) override;
|
||||
void deviceRemoved(Device *device) override;
|
||||
|
||||
bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const override;
|
||||
void startMonitoringAutoDevices() override;
|
||||
|
||||
QList<ParamType> configurationDescription() const override;
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@ VendorId hueVendorId = VendorId("0ae1e001-2aa6-47ed-b8c0-334c3728a68f");
|
||||
|
||||
PluginId huePluginUuid = PluginId("5f2e634b-b7f3-48ee-976a-b5ae22aa5c55");
|
||||
DeviceClassId hueDeviceClassId = DeviceClassId("d8f4c397-e05e-47c1-8917-8e72d4d0d47c");
|
||||
DeviceClassId hueDeviceClassAutoId = DeviceClassId("9cce5981-50a1-4873-a374-c53c095feb3b");
|
||||
|
||||
StateTypeId hueColorStateTypeId = StateTypeId("d25423e7-b924-4b20-80b6-77eecc65d089");
|
||||
ActionTypeId hueSetColorActionTypeId = ActionTypeId("29cc299a-818b-47b2-817f-c5a6361545e4");
|
||||
@ -114,6 +115,20 @@ QList<DeviceClass> DevicePluginPhilipsHue::supportedDevices() const
|
||||
|
||||
ret.append(deviceClassHue);
|
||||
|
||||
// Now create the same device again with CreateMethodAuto
|
||||
// When we pair a bridge, one discovered device is created.
|
||||
// The other light bulbs connected to the bridge will
|
||||
// then appear as auto devices.
|
||||
DeviceClass deviceClassHueAuto(pluginId(), hueVendorId, hueDeviceClassAutoId);
|
||||
deviceClassHueAuto.setName("Hue");
|
||||
deviceClassHueAuto.setCreateMethod(DeviceClass::CreateMethodAuto);
|
||||
deviceClassHueAuto.setParamTypes(paramTypes);
|
||||
deviceClassHueAuto.setStateTypes(hueStates);
|
||||
deviceClassHueAuto.setActions(hueActons);
|
||||
|
||||
ret.append(deviceClassHueAuto);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -122,23 +137,10 @@ DeviceManager::HardwareResources DevicePluginPhilipsHue::requiredHardware() cons
|
||||
return DeviceManager::HardwareResourceNone;
|
||||
}
|
||||
|
||||
bool DevicePluginPhilipsHue::configureAutoDevice(QList<Device *> loadedDevices, Device *device) const
|
||||
void DevicePluginPhilipsHue::startMonitoringAutoDevices()
|
||||
{
|
||||
// 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;
|
||||
// TODO: We could call the bridge to discover new light bulbs here maybe?
|
||||
// Although we maybe want to think of a user triggered approach to do such things.
|
||||
}
|
||||
|
||||
QString DevicePluginPhilipsHue::pluginName() const
|
||||
@ -189,6 +191,23 @@ QPair<DeviceManager::DeviceSetupStatus, QString> DevicePluginPhilipsHue::setupDe
|
||||
m_lights.insert(light, device);
|
||||
m_asyncSetups.insert(light, device);
|
||||
|
||||
// If we have more unconfigured lights around, lets add them as auto devices
|
||||
QList<DeviceDescriptor> descriptorList;
|
||||
while (!m_unconfiguredLights.isEmpty()) {
|
||||
Light *light = m_unconfiguredLights.takeFirst();
|
||||
DeviceDescriptor descriptor(hueDeviceClassAutoId, light->name());
|
||||
QList<Param> params;
|
||||
params.append(Param("number", light->id()));
|
||||
params.append(Param("ip", light->ip().toString()));
|
||||
params.append(Param("username", light->username()));
|
||||
descriptor.setParams(params);
|
||||
descriptorList.append(descriptor);
|
||||
}
|
||||
if (!descriptorList.isEmpty()) {
|
||||
qDebug() << "adding" << descriptorList.count() << "autodevices";
|
||||
metaObject()->invokeMethod(this, "autoDevicesAppeared", Qt::QueuedConnection, Q_ARG(DeviceClassId, hueDeviceClassAutoId), Q_ARG(QList<DeviceDescriptor>, descriptorList));
|
||||
}
|
||||
|
||||
return reportDeviceSetup(DeviceManager::DeviceSetupStatusAsync);
|
||||
}
|
||||
|
||||
@ -296,10 +315,10 @@ void DevicePluginPhilipsHue::getLightsFinished(int id, const QVariant ¶ms)
|
||||
|
||||
emit pairingFinished(pairingInfo.pairingTransactionId, DeviceManager::DeviceSetupStatusSuccess, QString());
|
||||
|
||||
// // If we have more than one device on that bridge, tell DeviceManager that there are more.
|
||||
// if (params.count() > 1) {
|
||||
// If we have more than one device on that bridge, tell DeviceManager that there are more.
|
||||
if (params.toMap().count() > 1) {
|
||||
// emit autoDevicesAppeared();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::getFinished(int id, const QVariant ¶ms)
|
||||
|
||||
@ -40,7 +40,7 @@ public:
|
||||
QList<DeviceClass> supportedDevices() const override;
|
||||
DeviceManager::HardwareResources requiredHardware() const override;
|
||||
|
||||
bool configureAutoDevice(QList<Device *> loadedDevices, Device *device) const override;
|
||||
void startMonitoringAutoDevices() override;
|
||||
|
||||
QString pluginName() const override;
|
||||
PluginId pluginId() const override;
|
||||
|
||||
@ -40,6 +40,16 @@ Light::Light(const QHostAddress &ip, const QString &username, int id, QObject *p
|
||||
{
|
||||
}
|
||||
|
||||
QHostAddress Light::ip() const
|
||||
{
|
||||
return m_ip;
|
||||
}
|
||||
|
||||
QString Light::username() const
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
|
||||
int Light::id() const
|
||||
{
|
||||
return m_id;
|
||||
|
||||
@ -39,6 +39,9 @@ public:
|
||||
|
||||
Light(const QHostAddress &ip, const QString &username, int id, QObject *parent = 0);
|
||||
|
||||
QHostAddress ip() const;
|
||||
QString username() const;
|
||||
|
||||
int id() const;
|
||||
|
||||
QString name() const;
|
||||
|
||||
@ -165,7 +165,7 @@ def discover_device(deviceClassId = None):
|
||||
params = {}
|
||||
params['deviceClassId'] = deviceClassId
|
||||
|
||||
discoveryParams = read_params(deviceClass['paramTypes'])
|
||||
discoveryParams = read_params(deviceClass['discoveryParamTypes'])
|
||||
if len(discoveryParams) > 0:
|
||||
params['discoveryParams'] = discoveryParams
|
||||
|
||||
|
||||
Reference in New Issue
Block a user