Mmmh I thought so but I’m not sure!!^^ I’ll double-check!!
Edit:
@pierre-gilles, I found it: 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
I’d be happy to take care of it as soon as possible (I did it for the Netatmo service that runs at home and it works perfectly). However, you would need to validate the operating principle so as not to start something and have to redo everything.
-
Front-end:
- a checkbox on each feature « Record only state changes »,
- this box is unchecked by default to remain as it is now,
-
Server-side:
- if the « Record only state changes » box is checked, then:
- add a column « only_keep_value_changes » in the t_device_feature table, this is 0 by default,
- or when checked, add a parameter in device_param:
{
"name": "[feature id]:only_keep_value_changes",
"value": true
}
- if the value of this parameter is true and the new value is the same as the previous one, we go through a new file server/lib/device/device.saveLastStateChanged.js to save in the t_device_feature table the
saveLastStateChanged as you asked me at the time of the Netatmo dev:
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,
};
- When the value changes again, we go back through the function of the file server/lib/device/device.saveState.js that we must modify to re-record, before the new value, the old value already in the database, to have an adjusted curve:
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,
}
For example, if we receive for a consumed power:
{
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
}
We will only find in the DB
{
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
},
// here we did not save the identical values
{
value: 1014.9,
created_at: 2022-04-19 05:10:13.277 +00:00
},
// After writing the value below, we sent
{
value: 78.0,
created_at: 2022-04-19 05:20:13.277 +00:00
}
Do you see it differently? In that case, would you roughly have the line to follow?