mirror of https://github.com/nymea/nymea.git
Add API to configure logging/filtering by the client
parent
32eb6d6dd7
commit
3fb74cc9e4
|
|
@ -506,6 +506,47 @@ Thing::ThingError ThingManagerImplementation::setThingSettings(const ThingId &th
|
|||
return Thing::ThingErrorNoError;
|
||||
}
|
||||
|
||||
Thing::ThingError ThingManagerImplementation::setEventLogging(const ThingId &thingId, const EventTypeId &eventTypeId, bool enabled)
|
||||
{
|
||||
Thing *thing = m_configuredThings.value(thingId);
|
||||
if (!thing) {
|
||||
qCWarning(dcThingManager()) << "Cannot configure event logging. Thing" << thingId.toString() << "not found";
|
||||
return Thing::ThingErrorThingNotFound;
|
||||
}
|
||||
if (!thing->thingClass().eventTypes().findById(eventTypeId).isValid()) {
|
||||
qCWarning(dcThingManager()) << "Cannot configure event logging. Thing" << thingId.toString() << "has no event type with id" << eventTypeId;
|
||||
return Thing::ThingErrorEventTypeNotFound;
|
||||
}
|
||||
QList<EventTypeId> loggedEventTypes = thing->loggedEventTypeIds();
|
||||
if (enabled && !loggedEventTypes.contains(eventTypeId)) {
|
||||
loggedEventTypes.append(eventTypeId);
|
||||
thing->setLoggedEventTypeIds(loggedEventTypes);
|
||||
emit thingChanged(thing);
|
||||
} else if (!enabled && loggedEventTypes.contains(eventTypeId)) {
|
||||
loggedEventTypes.removeAll(eventTypeId);
|
||||
thing->setLoggedEventTypeIds(loggedEventTypes);
|
||||
emit thingChanged(thing);
|
||||
}
|
||||
return Thing::ThingErrorNoError;
|
||||
}
|
||||
|
||||
Thing::ThingError ThingManagerImplementation::setStateFilter(const ThingId &thingId, const StateTypeId &stateTypeId, Types::StateValueFilter filter)
|
||||
{
|
||||
Thing *thing = m_configuredThings.value(thingId);
|
||||
if (!thing) {
|
||||
qCWarning(dcThingManager()) << "Cannot configure state filter. Thing" << thingId.toString() << "not found";
|
||||
return Thing::ThingErrorThingNotFound;
|
||||
}
|
||||
if (!thing->thingClass().stateTypes().findById(stateTypeId).isValid()) {
|
||||
qCWarning(dcThingManager()) << "Cannot configure state filter. Thing" << thingId.toString() << "has no state type with id" << stateTypeId;
|
||||
return Thing::ThingErrorEventTypeNotFound;
|
||||
}
|
||||
|
||||
thing->setStateValueFilter(stateTypeId, filter);
|
||||
emit thingChanged(thing);
|
||||
return Thing::ThingErrorNoError;
|
||||
}
|
||||
|
||||
ThingPairingInfo* ThingManagerImplementation::pairThing(const ThingClassId &thingClassId, const ParamList ¶ms, const QString &name)
|
||||
{
|
||||
PairingTransactionId transactionId = PairingTransactionId::createPairingTransactionId();
|
||||
|
|
|
|||
|
|
@ -106,6 +106,9 @@ public:
|
|||
Thing::ThingError editThing(const ThingId &thingId, const QString &name) override;
|
||||
Thing::ThingError setThingSettings(const ThingId &thingId, const ParamList &settings) override;
|
||||
|
||||
Thing::ThingError setEventLogging(const ThingId &thingId, const EventTypeId &eventTypeId, bool enabled) override;
|
||||
Thing::ThingError setStateFilter(const ThingId &thingId, const StateTypeId &stateTypeId, Types::StateValueFilter filter) override;
|
||||
|
||||
Thing::ThingError removeConfiguredThing(const ThingId &thingId) override;
|
||||
|
||||
ThingActionInfo* executeAction(const Action &action) override;
|
||||
|
|
|
|||
|
|
@ -242,6 +242,22 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||
returns.insert("thingError", enumRef<Thing::ThingError>());
|
||||
registerMethod("SetThingSettings", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Enable/disable logging for the given event type on the given thing.";
|
||||
params.insert("thingId", enumValueName(Uuid));
|
||||
params.insert("eventTypeId", enumValueName(Uuid));
|
||||
params.insert("enabled", enumValueName(Bool));
|
||||
returns.insert("thingError", enumRef<Thing::ThingError>());
|
||||
registerMethod("SetEventLogging", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Set the filter for the given state on the given thing.";
|
||||
params.insert("thingId", enumValueName(Uuid));
|
||||
params.insert("stateTypeId", enumValueName(Uuid));
|
||||
params.insert("filter", enumRef<Types::StateValueFilter>());
|
||||
returns.insert("thingError", enumRef<Thing::ThingError>());
|
||||
registerMethod("SetStateFilter", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Remove a thing from the system.";
|
||||
params.insert("thingId", enumValueName(Uuid));
|
||||
|
|
@ -839,6 +855,26 @@ JsonReply *IntegrationsHandler::SetThingSettings(const QVariantMap ¶ms)
|
|||
return createReply(statusToReply(status));
|
||||
}
|
||||
|
||||
JsonReply *IntegrationsHandler::SetEventLogging(const QVariantMap ¶ms)
|
||||
{
|
||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
||||
EventTypeId eventTypeId = EventTypeId(params.value("eventTypeId").toUuid());
|
||||
bool enabled = params.value("enabled").toBool();
|
||||
Thing::ThingError status = NymeaCore::instance()->thingManager()->setEventLogging(thingId, eventTypeId, enabled);
|
||||
return createReply(statusToReply(status));
|
||||
}
|
||||
|
||||
JsonReply *IntegrationsHandler::SetStateFilter(const QVariantMap ¶ms)
|
||||
{
|
||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
||||
StateTypeId stateTypeId = StateTypeId(params.value("stateTypeId").toUuid());
|
||||
QString filterString = params.value("filter").toString();
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<Types::StateValueFilter>();
|
||||
Types::StateValueFilter filter = static_cast<Types::StateValueFilter>(metaEnum.keyToValue(filterString.toUtf8()));
|
||||
Thing::ThingError status = NymeaCore::instance()->thingManager()->setStateFilter(thingId, stateTypeId, filter);
|
||||
return createReply(statusToReply(status));
|
||||
}
|
||||
|
||||
JsonReply* IntegrationsHandler::GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
||||
{
|
||||
ThingClass thingClass = NymeaCore::instance()->thingManager()->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ public:
|
|||
Q_INVOKABLE JsonReply *EditThing(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *RemoveThing(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *SetThingSettings(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *SetEventLogging(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *SetStateFilter(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE JsonReply *GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
Q_INVOKABLE JsonReply *GetActionTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ StateValueFilterAdaptive::StateValueFilterAdaptive()
|
|||
|
||||
void StateValueFilterAdaptive::addValue(const QVariant &value)
|
||||
{
|
||||
qCDebug(dcStateValueFilter()) << "Adding value:" << value.toDouble();
|
||||
m_inputValues.prepend(value.toDouble());
|
||||
m_inputValueCount++;
|
||||
update();
|
||||
|
|
@ -40,6 +39,7 @@ void StateValueFilterAdaptive::update()
|
|||
|
||||
double currentValue = m_inputValues.first();
|
||||
if (qFuzzyCompare(currentValue, 0)) {
|
||||
// If we went to 0, follow right away.
|
||||
m_outputValue = 0;
|
||||
return;
|
||||
}
|
||||
|
|
@ -49,20 +49,20 @@ void StateValueFilterAdaptive::update()
|
|||
for (int i = 0; i < m_inputValues.count(); i++) {
|
||||
sum += m_inputValues.at(i);
|
||||
}
|
||||
double normalizedValue = sum / m_inputValues.count();
|
||||
double previousNormalizedValue = (sum - m_inputValues.first()) / (m_inputValues.count() - 1);
|
||||
|
||||
double filteredValue = sum / m_inputValues.count();
|
||||
double previousFilteredValue = (sum - m_inputValues.first()) / (m_inputValues.count() - 1);
|
||||
|
||||
if (qFuzzyCompare(previousFilteredValue, 0)) {
|
||||
m_outputValue = m_inputValues.first();
|
||||
if (qFuzzyCompare(previousNormalizedValue, 0)) {
|
||||
// We can't calculate anything if the history is at 0. Follow right away to the new value.
|
||||
m_outputValue = currentValue;
|
||||
m_outputValueCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate change ratio of the last value compared to the previous one, unflitered and filtered
|
||||
double changeRatioToAverage = 1 - qAbs(currentValue / previousFilteredValue);
|
||||
double changeRatioToAverage = 1 - qAbs(currentValue / previousNormalizedValue);
|
||||
double changeRatioToCurrentOutput = 1 - qAbs(currentValue / m_outputValue);
|
||||
double changeRatioFiltered = 1 - qAbs(filteredValue / previousFilteredValue);
|
||||
double changeRatioFiltered = 1 - qAbs(normalizedValue / previousNormalizedValue);
|
||||
|
||||
|
||||
// If the unfiltered value changes for more than 3 times the standard deviation of the jittering values
|
||||
|
|
@ -72,7 +72,7 @@ void StateValueFilterAdaptive::update()
|
|||
m_inputValues.clear();
|
||||
m_inputValues.prepend(currentValue);
|
||||
m_totalDeviation = 0;
|
||||
if (!qFuzzyCompare(m_outputValue, filteredValue)) {
|
||||
if (!qFuzzyCompare(m_outputValue, normalizedValue)) {
|
||||
m_outputValue = currentValue;
|
||||
qCDebug(dcStateValueFilter()) << "Updating output value:" << m_outputValue << "(input exceeds max jitter)";
|
||||
m_outputValueCount++;
|
||||
|
|
@ -88,9 +88,9 @@ void StateValueFilterAdaptive::update()
|
|||
// to the new value when the summed up deviation exceeds the maximum allowed total deviation
|
||||
if (qAbs(changeRatioFiltered) > m_standardDeviation || qAbs(m_totalDeviation) > m_maxTotalDeviation) {
|
||||
m_totalDeviation = 0;
|
||||
if (!qFuzzyCompare(m_outputValue, filteredValue)) {
|
||||
qCDebug(dcStateValueFilter()) << "Updating output value:" << filteredValue << "(drift compensation)";
|
||||
m_outputValue = filteredValue;
|
||||
if (!qFuzzyCompare(m_outputValue, normalizedValue)) {
|
||||
qCDebug(dcStateValueFilter()) << "Updating output value:" << normalizedValue << "(drift compensation)";
|
||||
m_outputValue = normalizedValue;
|
||||
m_outputValueCount++;
|
||||
}
|
||||
}
|
||||
|
|
@ -99,15 +99,13 @@ void StateValueFilterAdaptive::update()
|
|||
m_standardDeviation = ((m_standardDeviation * m_windowSize) + qAbs(changeRatioToAverage)) / (m_windowSize + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// correct stats on overflow of counters
|
||||
// reset stats on overflow of counters
|
||||
if (m_inputValueCount < m_outputValueCount) {
|
||||
m_outputValueCount = 0;
|
||||
}
|
||||
|
||||
qCDebug(dcStateValueFilter()) << "Filter statistics for" << this;
|
||||
qCDebug(dcStateValueFilter()) << "Input:" << currentValue << "AVG:" << previousFilteredValue << "Filtered:" << filteredValue;
|
||||
qCDebug(dcStateValueFilter()) << "Input:" << currentValue << "AVG:" << previousNormalizedValue << "Filtered:" << normalizedValue;
|
||||
qCDebug(dcStateValueFilter()) << "Change ratios: Input/average:" << changeRatioToAverage << "Filtered/average:" << changeRatioFiltered << "Input/output:" << changeRatioToCurrentOutput;
|
||||
qCDebug(dcStateValueFilter()) << "Std deviation:" << m_standardDeviation << "Total deviation:" << m_totalDeviation;
|
||||
qCDebug(dcStateValueFilter()) << "Compression ratio:" << (1.0 * m_inputValueCount / m_outputValueCount) << "(" << m_outputValueCount << "/" << m_inputValueCount << ")";
|
||||
|
|
|
|||
|
|
@ -81,6 +81,9 @@ public:
|
|||
virtual Thing::ThingError editThing(const ThingId &thingId, const QString &name) = 0;
|
||||
virtual Thing::ThingError setThingSettings(const ThingId &thingId, const ParamList &settings) = 0;
|
||||
|
||||
virtual Thing::ThingError setEventLogging(const ThingId &thingId, const EventTypeId &eventTypeId, bool enabled) = 0;
|
||||
virtual Thing::ThingError setStateFilter(const ThingId &thingId, const StateTypeId &stateTypeId, Types::StateValueFilter filter) = 0;
|
||||
|
||||
virtual Thing::ThingError removeConfiguredThing(const ThingId &thingId) = 0;
|
||||
|
||||
virtual ThingActionInfo* executeAction(const Action &action) = 0;
|
||||
|
|
@ -112,7 +115,7 @@ signals:
|
|||
void thingRemoved(const ThingId &thingId);
|
||||
void thingDisappeared(const ThingId &thingId);
|
||||
void thingAdded(Thing *thing);
|
||||
void thingChanged(Thing *device);
|
||||
void thingChanged(Thing *thing);
|
||||
void thingSettingChanged(const ThingId &thingId, const ParamTypeId &settingParamTypeId, const QVariant &value);
|
||||
void ioConnectionAdded(const IOConnection &ioConnection);
|
||||
void ioConnectionRemoved(const IOConnectionId &ioConnectionId);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ class LIBNYMEA_EXPORT Event
|
|||
Q_PROPERTY(QUuid thingId READ thingId)
|
||||
Q_PROPERTY(QUuid deviceId READ thingId REVISION 1)
|
||||
Q_PROPERTY(ParamList params READ params)
|
||||
Q_PROPERTY(bool logged READ logged)
|
||||
public:
|
||||
Event();
|
||||
Event(const EventTypeId &eventTypeId, const ThingId &thingId, const ParamList ¶ms = ParamList(), bool isStateChangeEvent = false);
|
||||
|
|
|
|||
Loading…
Reference in New Issue