Mmmh, dachte ich, aber ich bin mir nicht sicher!!^^ Ich überprüfe das nochmal!!
Edit:
@pierre-gilles, ich habe es gefunden: Case à cochée "Ne pas enregistrer les nouvelles valeurs identiques" + Choix de durée de backup indépendant pour chaque Device Features - #2 par pierre-gilles
Ich würde gerne versuchen, mich so schnell wie möglich darum zu kümmern (ich habe es für den Netatmo-Dienst gemacht, der zu Hause läuft, und es funktioniert perfekt). Es müsste aber das Funktionsprinzip validiert werden, damit wir nicht etwas anfangen und dann alles wieder von vorne machen müssen.
-
Frontend:
- ein Kontrollkästchen für jede Funktion « Nur Zustandsänderungen speichern »,
- dieses Kästchen ist standardmäßig deaktiviert, um es wie bisher zu belassen,
-
Server:
- wenn das Kontrollkästchen « Nur Zustandsänderungen speichern » aktiviert ist, dann:
- eine Spalte « only_keep_value_changes » in der Tabelle t_device_feature hinzufügen, diese ist standardmäßig auf 0 gesetzt,
- oder wenn aktiviert, einen Parameter in device_param hinzufügen:
{
"name": "[id der Funktion]:only_keep_value_changes",
"value": true
}
- wenn der Wert dieses Parameters true ist und der neue Wert derselbe wie der vorherige ist, wird eine neue Datei server/lib/device/device.saveLastStateChanged.js verwendet, um in der Tabelle t_device_feature die
saveLastStateChanged zu speichern, wie du es mir damals während der Netatmo-Entwicklung vorgeschlagen hast:
const db = require('../../models');
const logger = require('../../utils/logger');
const { EVENTS, WEBSOCKET_MESSAGE_TYPES } = require('../../utils/constants');
/**
* @description Save new device feature state in DB.
* @param {Object} deviceFeature - A DeviceFeature object.
* @example
* saveLastValueChanged({
* id: 'fc235c88-b10d-4706-8b59-fef92a7119b2',
* selector: 'my-light'
* });
*/
async function saveLastStateChanged(deviceFeature) {
// logger.debug(`device.saveLastStateChanged of deviceFeature ${deviceFeature.selector}`);
const now = new Date();
// save local state in RAM
this.stateManager.setState('deviceFeature', deviceFeature.selector, {
last_value_changed: now,
});
await db.sequelize.transaction(async (t) => {
// update deviceFeature lastValue in DB
await db.DeviceFeature.update(
{
last_value_changed: now,
},
{
where: {
id: deviceFeature.id,
},
},
{
transaction: t,
},
);
});
// send websocket event
this.eventManager.emit(EVENTS.WEBSOCKET.SEND_ALL, {
type: WEBSOCKET_MESSAGE_TYPES.DEVICE.NEW_STATE_NO_CHANGED,
payload: {
device_feature_selector: deviceFeature.selector,
last_value_changed: now,
},
});
}
module.exports = {
saveLastStateChanged,
};
- Wenn sich der Wert erneut ändert, wird die Funktion der Datei server/lib/device/device.saveState.js verwendet, die geändert werden muss, um vor dem neuen Wert den alten Wert, der bereits in der Datenbank gespeichert ist, erneut zu speichern, um eine angepasste Kurve zu erhalten:
const db = require('../../models');
const logger = require('../../utils/logger');
const { EVENTS, WEBSOCKET_MESSAGE_TYPES } = require('../../utils/constants');
const { BadParameters } = require('../../utils/coreErrors');
const DEFAULT_OPTIONS = {
skip: 0,
order_dir: 'DESC',
order_by: 'created_at',
};
/**
* @description Save new device feature state in DB.
* @param {Object} deviceFeature - A DeviceFeature object.
* @param {number} newValue - The new value of the deviceFeature to save.
* @example
* saveState({
* id: 'fc235c88-b10d-4706-8b59-fef92a7119b2',
* selector: 'my-light'
* }, 12);
*/
async function saveState(deviceFeature, newValue) {
if (Number.isNaN(newValue)) {
throw new BadParameters(`device.saveState of NaN value on ${deviceFeature.selector}`);
}
const optionsWithDefault = Object.assign({}, DEFAULT_OPTIONS);
// logger.debug(`device.saveState of deviceFeature ${deviceFeature.selector}`);
const now = new Date();
const previousDeviceFeature = this.stateManager.get('deviceFeature', deviceFeature.selector);
const previousDeviceFeatureValue = previousDeviceFeature ? previousDeviceFeature.last_value : null;
const previousDeviceFeatureLastValueChanged = previousDeviceFeature ? previousDeviceFeature.last_value_changed : null;
const deviceFeaturesState = await db.DeviceFeatureState.findOne({
attributes: ['device_feature_id', 'value', 'created_at'],
order: [[optionsWithDefault.order_by, optionsWithDefault.order_dir]],
where: {
device_feature_id: deviceFeature.id,
},
});
const previousDeviceFeatureStateLastValueChanged = deviceFeaturesState ? deviceFeaturesState.created_at : 0;
// save local state in RAM
this.stateManager.setState('deviceFeature', deviceFeature.selector, {
last_value: newValue,
last_value_changed: now,
});
// update deviceFeature lastValue in DB
await db.DeviceFeature.update(
{
last_value: newValue,
last_value_changed: now,
},
{
where: {
id: deviceFeature.id,
},
},
);
// if the deviceFeature should keep history, we save a new deviceFeatureState
if (deviceFeature.keep_history) {
// if the previous created deviceFeatureState is different of deviceFeature
// last value changed, we save a new deviceFeatureState of old state
if (previousDeviceFeatureLastValueChanged - previousDeviceFeatureStateLastValueChanged > 0) {
await db.DeviceFeatureState.create({
device_feature_id: deviceFeature.id,
value: previousDeviceFeatureValue,
created_at: previousDeviceFeatureLastValueChanged,
});
}
await db.DeviceFeatureState.create({
device_feature_id: deviceFeature.id,
value: newValue,
});
}
// });
// send websocket event
this.eventManager.emit(EVENTS.WEBSOCKET.SEND_ALL, {
type: WEBSOCKET_MESSAGE_TYPES.DEVICE.NEW_STATE,
payload: {
device_feature_selector: deviceFeature.selector,
last_value: newValue,
last_value_changed: now,
},
});
// check if there is a trigger matching
this.eventManager.emit(EVENTS.TRIGGERS.CHECK, {
type: EVENTS.DEVICE.NEW_STATE,
device_feature: deviceFeature.selector,
previous_value: previousDeviceFeatureValue,
last_value: newValue,
last_value_changed: now,
});
}
module.exports = {
saveState,
};
Beispiel, wenn wir für einen verbrauchten Leistungswert erhalten:
{
value: 1014.7,
created_at: 2022-04-19 04:20:13.277 +00:00
},
{
value: 1014.9,
created_at: 2022-04-19 04:30:13.277 +00:00
},
{
value: 1014.9,
created_at: 2022-04-19 04:40:13.277 +00:00
},
{
value: 1014.9,
created_at: 2022-04-19 04:50:13.277 +00:00
},
{
value: 1014.9,
created_at: 2022-04-19 05:00:13.277 +00:00
},
{
value: 1014.9,
created_at: 2022-04-19 05:10:13.277 +00:00
},
{
value: 78.0,
created_at: 2022-04-19 05:20:13.277 +00:00
}
In der Datenbank wird nur folgendes gespeichert:
{
value: 1014.7,
created_at: 2022-04-19 04:20:13.277 +00:00
},
{
value: 1014.9,
created_at: 2022-04-19 04:30:13.277 +00:00
},
// Hier wurden die identischen Werte nicht gespeichert
{
value: 1014.9,
created_at: 2022-04-19 05:10:13.277 +00:00
},
// Nach dem Schreiben des folgenden Wertes wurde zurückgeschickt
{
value: 78.0,
created_at: 2022-04-19 05:20:13.277 +00:00
}
Siehst du das anders? In diesem Fall hättest du grob die Richtung, die wir einschlagen sollten?