Add API to configure logging/filtering by the client
This commit is contained in:
parent
32eb6d6dd7
commit
3fb74cc9e4
@ -506,6 +506,47 @@ Thing::ThingError ThingManagerImplementation::setThingSettings(const ThingId &th
|
|||||||
return Thing::ThingErrorNoError;
|
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)
|
ThingPairingInfo* ThingManagerImplementation::pairThing(const ThingClassId &thingClassId, const ParamList ¶ms, const QString &name)
|
||||||
{
|
{
|
||||||
PairingTransactionId transactionId = PairingTransactionId::createPairingTransactionId();
|
PairingTransactionId transactionId = PairingTransactionId::createPairingTransactionId();
|
||||||
|
|||||||
@ -106,6 +106,9 @@ public:
|
|||||||
Thing::ThingError editThing(const ThingId &thingId, const QString &name) override;
|
Thing::ThingError editThing(const ThingId &thingId, const QString &name) override;
|
||||||
Thing::ThingError setThingSettings(const ThingId &thingId, const ParamList &settings) 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;
|
Thing::ThingError removeConfiguredThing(const ThingId &thingId) override;
|
||||||
|
|
||||||
ThingActionInfo* executeAction(const Action &action) override;
|
ThingActionInfo* executeAction(const Action &action) override;
|
||||||
|
|||||||
@ -242,6 +242,22 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
returns.insert("thingError", enumRef<Thing::ThingError>());
|
returns.insert("thingError", enumRef<Thing::ThingError>());
|
||||||
registerMethod("SetThingSettings", description, params, returns);
|
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();
|
params.clear(); returns.clear();
|
||||||
description = "Remove a thing from the system.";
|
description = "Remove a thing from the system.";
|
||||||
params.insert("thingId", enumValueName(Uuid));
|
params.insert("thingId", enumValueName(Uuid));
|
||||||
@ -839,6 +855,26 @@ JsonReply *IntegrationsHandler::SetThingSettings(const QVariantMap ¶ms)
|
|||||||
return createReply(statusToReply(status));
|
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
|
JsonReply* IntegrationsHandler::GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingClass thingClass = NymeaCore::instance()->thingManager()->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
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 *EditThing(const QVariantMap ¶ms);
|
||||||
Q_INVOKABLE JsonReply *RemoveThing(const QVariantMap ¶ms);
|
Q_INVOKABLE JsonReply *RemoveThing(const QVariantMap ¶ms);
|
||||||
Q_INVOKABLE JsonReply *SetThingSettings(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 *GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
Q_INVOKABLE JsonReply *GetActionTypes(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)
|
void StateValueFilterAdaptive::addValue(const QVariant &value)
|
||||||
{
|
{
|
||||||
qCDebug(dcStateValueFilter()) << "Adding value:" << value.toDouble();
|
|
||||||
m_inputValues.prepend(value.toDouble());
|
m_inputValues.prepend(value.toDouble());
|
||||||
m_inputValueCount++;
|
m_inputValueCount++;
|
||||||
update();
|
update();
|
||||||
@ -40,6 +39,7 @@ void StateValueFilterAdaptive::update()
|
|||||||
|
|
||||||
double currentValue = m_inputValues.first();
|
double currentValue = m_inputValues.first();
|
||||||
if (qFuzzyCompare(currentValue, 0)) {
|
if (qFuzzyCompare(currentValue, 0)) {
|
||||||
|
// If we went to 0, follow right away.
|
||||||
m_outputValue = 0;
|
m_outputValue = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -49,20 +49,20 @@ void StateValueFilterAdaptive::update()
|
|||||||
for (int i = 0; i < m_inputValues.count(); i++) {
|
for (int i = 0; i < m_inputValues.count(); i++) {
|
||||||
sum += m_inputValues.at(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();
|
if (qFuzzyCompare(previousNormalizedValue, 0)) {
|
||||||
double previousFilteredValue = (sum - m_inputValues.first()) / (m_inputValues.count() - 1);
|
// We can't calculate anything if the history is at 0. Follow right away to the new value.
|
||||||
|
m_outputValue = currentValue;
|
||||||
if (qFuzzyCompare(previousFilteredValue, 0)) {
|
|
||||||
m_outputValue = m_inputValues.first();
|
|
||||||
m_outputValueCount++;
|
m_outputValueCount++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate change ratio of the last value compared to the previous one, unflitered and filtered
|
// 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 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
|
// 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.clear();
|
||||||
m_inputValues.prepend(currentValue);
|
m_inputValues.prepend(currentValue);
|
||||||
m_totalDeviation = 0;
|
m_totalDeviation = 0;
|
||||||
if (!qFuzzyCompare(m_outputValue, filteredValue)) {
|
if (!qFuzzyCompare(m_outputValue, normalizedValue)) {
|
||||||
m_outputValue = currentValue;
|
m_outputValue = currentValue;
|
||||||
qCDebug(dcStateValueFilter()) << "Updating output value:" << m_outputValue << "(input exceeds max jitter)";
|
qCDebug(dcStateValueFilter()) << "Updating output value:" << m_outputValue << "(input exceeds max jitter)";
|
||||||
m_outputValueCount++;
|
m_outputValueCount++;
|
||||||
@ -88,9 +88,9 @@ void StateValueFilterAdaptive::update()
|
|||||||
// to the new value when the summed up deviation exceeds the maximum allowed total deviation
|
// 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) {
|
if (qAbs(changeRatioFiltered) > m_standardDeviation || qAbs(m_totalDeviation) > m_maxTotalDeviation) {
|
||||||
m_totalDeviation = 0;
|
m_totalDeviation = 0;
|
||||||
if (!qFuzzyCompare(m_outputValue, filteredValue)) {
|
if (!qFuzzyCompare(m_outputValue, normalizedValue)) {
|
||||||
qCDebug(dcStateValueFilter()) << "Updating output value:" << filteredValue << "(drift compensation)";
|
qCDebug(dcStateValueFilter()) << "Updating output value:" << normalizedValue << "(drift compensation)";
|
||||||
m_outputValue = filteredValue;
|
m_outputValue = normalizedValue;
|
||||||
m_outputValueCount++;
|
m_outputValueCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,15 +99,13 @@ void StateValueFilterAdaptive::update()
|
|||||||
m_standardDeviation = ((m_standardDeviation * m_windowSize) + qAbs(changeRatioToAverage)) / (m_windowSize + 1);
|
m_standardDeviation = ((m_standardDeviation * m_windowSize) + qAbs(changeRatioToAverage)) / (m_windowSize + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset stats on overflow of counters
|
||||||
|
|
||||||
// correct stats on overflow of counters
|
|
||||||
if (m_inputValueCount < m_outputValueCount) {
|
if (m_inputValueCount < m_outputValueCount) {
|
||||||
m_outputValueCount = 0;
|
m_outputValueCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcStateValueFilter()) << "Filter statistics for" << this;
|
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()) << "Change ratios: Input/average:" << changeRatioToAverage << "Filtered/average:" << changeRatioFiltered << "Input/output:" << changeRatioToCurrentOutput;
|
||||||
qCDebug(dcStateValueFilter()) << "Std deviation:" << m_standardDeviation << "Total deviation:" << m_totalDeviation;
|
qCDebug(dcStateValueFilter()) << "Std deviation:" << m_standardDeviation << "Total deviation:" << m_totalDeviation;
|
||||||
qCDebug(dcStateValueFilter()) << "Compression ratio:" << (1.0 * m_inputValueCount / m_outputValueCount) << "(" << m_outputValueCount << "/" << m_inputValueCount << ")";
|
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 editThing(const ThingId &thingId, const QString &name) = 0;
|
||||||
virtual Thing::ThingError setThingSettings(const ThingId &thingId, const ParamList &settings) = 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 Thing::ThingError removeConfiguredThing(const ThingId &thingId) = 0;
|
||||||
|
|
||||||
virtual ThingActionInfo* executeAction(const Action &action) = 0;
|
virtual ThingActionInfo* executeAction(const Action &action) = 0;
|
||||||
@ -112,7 +115,7 @@ signals:
|
|||||||
void thingRemoved(const ThingId &thingId);
|
void thingRemoved(const ThingId &thingId);
|
||||||
void thingDisappeared(const ThingId &thingId);
|
void thingDisappeared(const ThingId &thingId);
|
||||||
void thingAdded(Thing *thing);
|
void thingAdded(Thing *thing);
|
||||||
void thingChanged(Thing *device);
|
void thingChanged(Thing *thing);
|
||||||
void thingSettingChanged(const ThingId &thingId, const ParamTypeId &settingParamTypeId, const QVariant &value);
|
void thingSettingChanged(const ThingId &thingId, const ParamTypeId &settingParamTypeId, const QVariant &value);
|
||||||
void ioConnectionAdded(const IOConnection &ioConnection);
|
void ioConnectionAdded(const IOConnection &ioConnection);
|
||||||
void ioConnectionRemoved(const IOConnectionId &ioConnectionId);
|
void ioConnectionRemoved(const IOConnectionId &ioConnectionId);
|
||||||
|
|||||||
@ -46,7 +46,6 @@ class LIBNYMEA_EXPORT Event
|
|||||||
Q_PROPERTY(QUuid thingId READ thingId)
|
Q_PROPERTY(QUuid thingId READ thingId)
|
||||||
Q_PROPERTY(QUuid deviceId READ thingId REVISION 1)
|
Q_PROPERTY(QUuid deviceId READ thingId REVISION 1)
|
||||||
Q_PROPERTY(ParamList params READ params)
|
Q_PROPERTY(ParamList params READ params)
|
||||||
Q_PROPERTY(bool logged READ logged)
|
|
||||||
public:
|
public:
|
||||||
Event();
|
Event();
|
||||||
Event(const EventTypeId &eventTypeId, const ThingId &thingId, const ParamList ¶ms = ParamList(), bool isStateChangeEvent = false);
|
Event(const EventTypeId &eventTypeId, const ThingId &thingId, const ParamList ¶ms = ParamList(), bool isStateChangeEvent = false);
|
||||||
|
|||||||
Reference in New Issue
Block a user