mirror of https://github.com/nymea/nymea.git
474 lines
15 KiB
C++
474 lines
15 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* *
|
|
* Copyright (C) 2015-2018 Simon Stürz <simon.stuerz@guh.io> *
|
|
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
|
* *
|
|
* This file is part of nymea. *
|
|
* *
|
|
* This library 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; either *
|
|
* version 2.1 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library 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 library; If not, see *
|
|
* <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*!
|
|
\class Device
|
|
\brief A Device represents a installed and configured hardware device.
|
|
|
|
\ingroup devices
|
|
\inmodule libnymea
|
|
|
|
This class holds the values for configured devices. It is associated with a \{DeviceClass} which
|
|
can be used to get more details about the device.
|
|
|
|
\sa DeviceClass, DeviceDescriptor
|
|
*/
|
|
|
|
/*! \enum Device::DeviceError
|
|
|
|
This enum type specifies the errors that can happen when working with \l{Device}{Devices}.
|
|
|
|
\value DeviceErrorNoError
|
|
No Error. Everything went fine.
|
|
\value DeviceErrorPluginNotFound
|
|
Couldn't find the Plugin for the given id.
|
|
\value DeviceErrorVendorNotFound
|
|
Couldn't find the Vendor for the given id.
|
|
\value DeviceErrorDeviceNotFound
|
|
Couldn't find a \l{Device} for the given id.
|
|
\value DeviceErrorDeviceClassNotFound
|
|
Couldn't find a \l{DeviceClass} for the given id.
|
|
\value DeviceErrorActionTypeNotFound
|
|
Couldn't find the \l{ActionType} for the given id.
|
|
\value DeviceErrorStateTypeNotFound
|
|
Couldn't find the \l{StateType} for the given id.
|
|
\value DeviceErrorEventTypeNotFound
|
|
Couldn't find the \l{EventType} for the given id.
|
|
\value DeviceErrorDeviceDescriptorNotFound
|
|
Couldn't find the \l{DeviceDescriptor} for the given id.
|
|
\value DeviceErrorMissingParameter
|
|
Parameters do not comply to the template.
|
|
\value DeviceErrorInvalidParameter
|
|
One of the given parameter is not valid.
|
|
\value DeviceErrorSetupFailed
|
|
Error setting up the \l{Device}. It will not be functional.
|
|
\value DeviceErrorDuplicateUuid
|
|
Error setting up the \l{Device}. The given DeviceId already exists.
|
|
\value DeviceErrorCreationMethodNotSupported
|
|
Error setting up the \l{Device}. This \l{DeviceClass}{CreateMethod} is not supported for this \l{Device}.
|
|
\value DeviceErrorSetupMethodNotSupported
|
|
Error setting up the \l{Device}. This \l{DeviceClass}{SetupMethod} is not supported for this \l{Device}.
|
|
\value DeviceErrorHardwareNotAvailable
|
|
The Hardware of the \l{Device} is not available.
|
|
\value DeviceErrorHardwareFailure
|
|
The Hardware of the \l{Device} has an error.
|
|
\value DeviceErrorAsync
|
|
The response of the \l{Device} will be asynchronously.
|
|
\value DeviceErrorDeviceInUse
|
|
The \l{Device} is currently bussy.
|
|
\value DeviceErrorPairingTransactionIdNotFound
|
|
Couldn't find the PairingTransactionId for the given id.
|
|
\value DeviceErrorAuthentificationFailure
|
|
The device could not authentificate with something.
|
|
\value DeviceErrorDeviceIsChild
|
|
The device is a child device and can not be deleted directly.
|
|
\value DeviceErrorDeviceInRule
|
|
The device is in a rule and can not be deleted withou \l{nymeaserver::RuleEngine::RemovePolicy}.
|
|
\value DeviceErrorParameterNotWritable
|
|
One of the given device params is not writable.
|
|
*/
|
|
|
|
/*! \enum Device::DeviceSetupStatus
|
|
|
|
This enum type specifies the setup status of a \l{Device}.
|
|
|
|
\value DeviceSetupStatusSuccess
|
|
No Error. Everything went fine.
|
|
\value DeviceSetupStatusFailure
|
|
Something went wrong during the setup.
|
|
\value DeviceSetupStatusAsync
|
|
The status of the \l{Device} setup will be emitted asynchronous.
|
|
*/
|
|
|
|
/*! \fn void Device::stateValueChanged(const StateTypeId &stateTypeId, const QVariant &value)
|
|
This signal is emitted when the \l{State} with the given \a stateTypeId changed.
|
|
The \a value parameter describes the new value of the State.
|
|
*/
|
|
#include "device.h"
|
|
#include "deviceplugin.h"
|
|
#include "types/event.h"
|
|
#include "loggingcategories.h"
|
|
|
|
#include <QDebug>
|
|
|
|
/*! Construct an Device with the given \a pluginId, \a id, \a deviceClassId and \a parent. */
|
|
Device::Device(DevicePlugin *plugin, const DeviceClass &deviceClass, const DeviceId &id, QObject *parent):
|
|
QObject(parent),
|
|
m_deviceClass(deviceClass),
|
|
m_plugin(plugin),
|
|
m_id(id)
|
|
{
|
|
|
|
}
|
|
|
|
/*! Construct an Device with the given \a pluginId, \a deviceClassId and \a parent. A new DeviceId will be created for this Device. */
|
|
Device::Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *parent):
|
|
QObject(parent),
|
|
m_deviceClass(deviceClass),
|
|
m_plugin(plugin),
|
|
m_id(DeviceId::createDeviceId())
|
|
{
|
|
|
|
}
|
|
|
|
void Device::setupCompleted()
|
|
{
|
|
m_setupComplete = true;
|
|
}
|
|
|
|
/*! Returns the id of this Device. */
|
|
DeviceId Device::id() const
|
|
{
|
|
return m_id;
|
|
}
|
|
|
|
/*! Returns the deviceClassId of the associated \l{DeviceClass}. */
|
|
DeviceClassId Device::deviceClassId() const
|
|
{
|
|
return m_deviceClass.id();
|
|
}
|
|
|
|
/*! Returns the id of the \l{DevicePlugin} this Device is managed by. */
|
|
PluginId Device::pluginId() const
|
|
{
|
|
return m_plugin->pluginId();
|
|
}
|
|
|
|
/*! Returns the \l{DeviceClass} of this device. */
|
|
DeviceClass Device::deviceClass() const
|
|
{
|
|
return m_deviceClass;
|
|
}
|
|
|
|
/*! Returns the the \l{DevicePlugin} this Device is managed by. */
|
|
DevicePlugin *Device::plugin() const
|
|
{
|
|
return m_plugin;
|
|
}
|
|
|
|
/*! Returns the name of this Device. This is visible to the user. */
|
|
QString Device::name() const
|
|
{
|
|
return m_name;
|
|
}
|
|
|
|
/*! Set the \a name for this Device. This is visible to the user.*/
|
|
void Device::setName(const QString &name)
|
|
{
|
|
if (m_name != name) {
|
|
m_name = name;
|
|
emit nameChanged();
|
|
}
|
|
}
|
|
|
|
/*! Returns the parameter of this Device. It must match the parameter description in the associated \l{DeviceClass}. */
|
|
ParamList Device::params() const
|
|
{
|
|
return m_params;
|
|
}
|
|
|
|
/*! Sets the \a params of this Device. It must match the parameter description in the associated \l{DeviceClass}. */
|
|
void Device::setParams(const ParamList ¶ms)
|
|
{
|
|
m_params = params;
|
|
}
|
|
|
|
/*! Returns the value of the \l{Param} of this Device with the given \a paramTypeId. */
|
|
QVariant Device::paramValue(const ParamTypeId ¶mTypeId) const
|
|
{
|
|
foreach (const Param ¶m, m_params) {
|
|
if (param.paramTypeId() == paramTypeId) {
|
|
return param.value();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
/*! Sets the \a value of the \l{Param} with the given \a paramTypeId. */
|
|
void Device::setParamValue(const ParamTypeId ¶mTypeId, const QVariant &value)
|
|
{
|
|
ParamList params;
|
|
foreach (Param param, m_params) {
|
|
if (param.paramTypeId() == paramTypeId) {
|
|
param.setValue(value);
|
|
}
|
|
params << param;
|
|
}
|
|
m_params = params;
|
|
}
|
|
|
|
ParamList Device::settings() const
|
|
{
|
|
return m_settings;
|
|
}
|
|
|
|
bool Device::hasSetting(const ParamTypeId ¶mTypeId) const
|
|
{
|
|
return m_settings.hasParam(paramTypeId);
|
|
}
|
|
|
|
void Device::setSettings(const ParamList &settings)
|
|
{
|
|
m_settings = settings;
|
|
foreach (const Param ¶m, m_settings) {
|
|
emit settingChanged(param.paramTypeId(), param.value());
|
|
}
|
|
}
|
|
|
|
QVariant Device::setting(const ParamTypeId ¶mTypeId) const
|
|
{
|
|
foreach (Param setting, m_settings) {
|
|
if (setting.paramTypeId() == paramTypeId) {
|
|
return setting.value();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
void Device::setSettingValue(const ParamTypeId ¶mTypeId, const QVariant &value)
|
|
{
|
|
ParamList settings;
|
|
bool found = false;
|
|
bool changed = false;
|
|
foreach (Param param, m_settings) {
|
|
if (param.paramTypeId() == paramTypeId) {
|
|
found = true;
|
|
if (param.value() != value) {
|
|
param.setValue(value);
|
|
changed = true;
|
|
}
|
|
}
|
|
settings << param;
|
|
}
|
|
if (!found) {
|
|
qCWarning(dcDeviceManager()) << "Device" << m_name << "(" << m_id.toString() << ") does not have a setting with id" << paramTypeId;
|
|
return;
|
|
}
|
|
if (changed) {
|
|
m_settings = settings;
|
|
emit settingChanged(paramTypeId, value);
|
|
}
|
|
}
|
|
|
|
/*! Returns the states of this Device. It must match the \l{StateType} description in the associated \l{DeviceClass}. */
|
|
States Device::states() const
|
|
{
|
|
return m_states;
|
|
}
|
|
|
|
/*! Returns true, a \l{Param} with the given \a paramTypeId exists for this Device. */
|
|
bool Device::hasParam(const ParamTypeId ¶mTypeId) const
|
|
{
|
|
return m_params.hasParam(paramTypeId);
|
|
}
|
|
|
|
/*! Set the \l{State}{States} of this \l{Device} to the given \a states.*/
|
|
void Device::setStates(const States &states)
|
|
{
|
|
m_states = states;
|
|
}
|
|
|
|
/*! Returns true, a \l{State} with the given \a stateTypeId exists for this Device. */
|
|
bool Device::hasState(const StateTypeId &stateTypeId) const
|
|
{
|
|
foreach (const State &state, m_states) {
|
|
if (state.stateTypeId() == stateTypeId) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*! For convenience, this finds the \l{State} matching the given \a stateTypeId and returns the current valie in this Device. */
|
|
QVariant Device::stateValue(const StateTypeId &stateTypeId) const
|
|
{
|
|
foreach (const State &state, m_states) {
|
|
if (state.stateTypeId() == stateTypeId) {
|
|
return state.value();
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
/*! For convenience, this finds the \l{State} matching the given \a stateTypeId in this Device and sets the current value to \a value. */
|
|
void Device::setStateValue(const StateTypeId &stateTypeId, const QVariant &value)
|
|
{
|
|
for (int i = 0; i < m_states.count(); ++i) {
|
|
if (m_states.at(i).stateTypeId() == stateTypeId) {
|
|
if (m_states.at(i).value() == value)
|
|
return;
|
|
|
|
|
|
// TODO: check min/max value + possible values
|
|
// to prevent an invalid state type from the plugin side
|
|
|
|
State newState(stateTypeId, m_id);
|
|
newState.setValue(value);
|
|
m_states[i] = newState;
|
|
emit stateValueChanged(stateTypeId, value);
|
|
return;
|
|
}
|
|
}
|
|
qCWarning(dcDeviceManager) << "Failed setting state for" << m_name << value;
|
|
}
|
|
|
|
/*! Returns the \l{State} with the given \a stateTypeId of this Device. */
|
|
State Device::state(const StateTypeId &stateTypeId) const
|
|
{
|
|
for (int i = 0; i < m_states.count(); ++i) {
|
|
if (m_states.at(i).stateTypeId() == stateTypeId) {
|
|
return m_states.at(i);
|
|
}
|
|
}
|
|
return State(StateTypeId(), DeviceId());
|
|
}
|
|
|
|
/*! Returns the \l{DeviceId} of the parent Device from Device. If the parentId
|
|
is not set, this device is a parent device.
|
|
*/
|
|
DeviceId Device::parentId() const
|
|
{
|
|
return m_parentId;
|
|
}
|
|
|
|
/*! Sets the \a parentId of this Device. If the parentId
|
|
is not set, this device is a parent device.
|
|
*/
|
|
void Device::setParentId(const DeviceId &parentId)
|
|
{
|
|
m_parentId = parentId;
|
|
}
|
|
|
|
/*! Returns true, if setup of this Device is already completed. */
|
|
bool Device::setupComplete() const
|
|
{
|
|
return m_setupComplete;
|
|
}
|
|
|
|
/*! Returns true if this device has been auto-created (not created by the user) */
|
|
bool Device::autoCreated() const
|
|
{
|
|
return m_autoCreated;
|
|
}
|
|
|
|
void Device::setSetupComplete(bool complete)
|
|
{
|
|
m_setupComplete = complete;
|
|
}
|
|
|
|
Devices::Devices(const QList<Device*> &other)
|
|
{
|
|
foreach (Device* device, other) {
|
|
this->append(device);
|
|
}
|
|
}
|
|
|
|
Device *Devices::findById(const DeviceId &id)
|
|
{
|
|
foreach (Device *device, *this) {
|
|
if (device->id() == id) {
|
|
return device;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/*! Find a certain device by its \a params. All parameters must
|
|
match or the device will not be found. Be prepared for nullptrs.
|
|
*/
|
|
Device *Devices::findByParams(const ParamList ¶ms) const
|
|
{
|
|
foreach (Device *device, *this) {
|
|
bool matching = true;
|
|
foreach (const Param ¶m, params) {
|
|
if (device->paramValue(param.paramTypeId()) != param.value()) {
|
|
matching = false;
|
|
}
|
|
}
|
|
if (matching) {
|
|
return device;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
QDebug operator<<(QDebug dbg, Device *device)
|
|
{
|
|
dbg.nospace() << "Device(" << device->name();
|
|
dbg.nospace() << ", id: " << device->id().toString();
|
|
dbg.nospace() << ", deviceClassId: " << device->deviceClassId().toString() << ")";
|
|
return dbg.space();
|
|
}
|
|
|
|
/*! Filter a Devices list by a parameter. Only Devices having a parameter of the given
|
|
\a paramTypeId will be returned. If \a value is given and it is not null, only Devices
|
|
with the given \a paramTypeId and the same \a value will be returned.
|
|
*/
|
|
Devices Devices::filterByParam(const ParamTypeId ¶mTypeId, const QVariant &value)
|
|
{
|
|
Devices ret;
|
|
foreach (Device* device, *this) {
|
|
if (paramTypeId != paramTypeId) {
|
|
continue;
|
|
}
|
|
if (!value.isNull() && device->paramValue(paramTypeId) != value) {
|
|
continue;
|
|
}
|
|
ret << device;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
Devices Devices::filterByDeviceClassId(const DeviceClassId &deviceClassId)
|
|
{
|
|
Devices ret;
|
|
foreach (Device* device, *this) {
|
|
if (device->deviceClassId() == deviceClassId) {
|
|
ret << device;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
Devices Devices::filterByParentDeviceId(const DeviceId &deviceId)
|
|
{
|
|
Devices ret;
|
|
foreach (Device *device, *this) {
|
|
if (device->parentId() == deviceId) {
|
|
ret << device;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
Devices Devices::filterByInterface(const QString &interface)
|
|
{
|
|
Devices ret;
|
|
foreach (Device *device, *this) {
|
|
if (device->deviceClass().interfaces().indexOf(interface) >= 0) {
|
|
ret.append(device);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|