Skip to content

Commit

Permalink
Netatmo: Add support for NRV module type - Energy / Valves (#2014)
Browse files Browse the repository at this point in the history
  • Loading branch information
Terdious authored Feb 12, 2024
1 parent fa39291 commit 0de29d7
Show file tree
Hide file tree
Showing 19 changed files with 535 additions and 49 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,29 @@ function buildFeatureBoilerStatus(name, externalId) {
};
}

/**
* @description Transforms Netatmo feature as Gladys feature. Heating power request.
* @param {string} name - Name device from Netatmo.
* @param {string} externalId - Gladys external ID.
* @returns {object} Gladys feature or undefined.
* @example
* buildFeatureHeatingPowerRequest(device_name, 'netatmo:device_id');
*/
function buildFeatureHeatingPowerRequest(name, externalId) {
return {
name: `Heating power request - ${name}`,
external_id: `${externalId}:heating_power_request`,
selector: `${externalId}:heating_power_request`,
category: DEVICE_FEATURE_CATEGORIES.SWITCH,
type: DEVICE_FEATURE_TYPES.SWITCH.BINARY,
read_only: true,
keep_history: true,
has_feedback: false,
min: 0,
max: 1,
};
}

/**
* @description Transforms Netatmo feature as Gladys feature. Plug connected boiler.
* @param {string} name - Name device from Netatmo.
Expand All @@ -77,5 +100,6 @@ function buildFeaturePlugConnectedBoiler(name, externalId) {
module.exports = {
buildFeatureThermSetpointTemperature,
buildFeatureBoilerStatus,
buildFeatureHeatingPowerRequest,
buildFeaturePlugConnectedBoiler,
};
25 changes: 22 additions & 3 deletions server/services/netatmo/lib/device/netatmo.convertDevice.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const { buildFeatureRfStrength, buildFeatureWifiStrength } = require('./netatmo.
const {
buildFeatureThermSetpointTemperature,
buildFeatureBoilerStatus,
buildFeatureHeatingPowerRequest,
buildFeaturePlugConnectedBoiler,
} = require('./netatmo.buildFeaturesSpecifEnergy');

Expand All @@ -26,14 +27,14 @@ function convertDevice(netatmoDevice) {
case SUPPORTED_MODULE_TYPE.THERMOSTAT: {
/* features common */
features.push(buildFeatureBattery(name, externalId));
/* features common Netatmo Energy */
/* features common Netatmo */
features.push(buildFeatureTemperature(name, externalId, 'temperature'));
features.push(buildFeatureTemperature(`room ${room.name}`, externalId, 'therm_measured_temperature'));
features.push(buildFeatureThermSetpointTemperature(name, externalId));
features.push(buildFeatureOpenWindow(name, externalId));
/* features common modules RF */
features.push(buildFeatureRfStrength(name, externalId));
/* features specific Energy */
features.push(buildFeatureThermSetpointTemperature(name, externalId));
features.push(buildFeatureOpenWindow(name, externalId));
features.push(buildFeatureBoilerStatus(name, externalId));
/* params */
params = [
Expand All @@ -54,6 +55,24 @@ function convertDevice(netatmoDevice) {
params = [{ name: PARAMS.MODULES_BRIDGE_ID, value: JSON.stringify(modulesBridged) }];
break;
}
case SUPPORTED_MODULE_TYPE.NRV: {
/* features common */
features.push(buildFeatureBattery(name, externalId));
/* features common Netatmo */
features.push(buildFeatureTemperature(`room ${room.name}`, externalId, 'therm_measured_temperature'));
/* features common modules RF */
features.push(buildFeatureRfStrength(name, externalId));
/* features specific Energy */
features.push(buildFeatureThermSetpointTemperature(name, externalId));
features.push(buildFeatureOpenWindow(name, externalId));
features.push(buildFeatureHeatingPowerRequest(name, externalId));
/* params */
params = [
{ name: PARAMS.PLUG_ID, value: plug.id },
{ name: PARAMS.PLUG_NAME, value: plug.name },
];
break;
}
default:
break;
}
Expand Down
13 changes: 12 additions & 1 deletion server/services/netatmo/lib/device/netatmo.deviceMapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,19 @@ const readValues = {
},
[DEVICE_FEATURE_CATEGORIES.BATTERY]: {
/* battery_percent: 76 */
/* battery_state: 'medium' */
[DEVICE_FEATURE_TYPES.BATTERY.INTEGER]: (valueFromDevice) => {
const valueToGladys = parseInt(valueFromDevice, 10);
const batteryLevels = {
max: 100,
full: 90,
high: 75,
medium: 50,
low: 25,
'very low': 10,
};

const valueToGladys =
batteryLevels[valueFromDevice] !== undefined ? batteryLevels[valueFromDevice] : parseInt(valueFromDevice, 10);
return valueToGladys;
},
},
Expand Down
8 changes: 4 additions & 4 deletions server/services/netatmo/lib/device/netatmo.updateNAPlug.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async function updateNAPlug(deviceGladys, deviceNetatmo, externalId) {
.filter((feature) => feature.external_id === `${externalId}:rf_strength`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:rf_strength`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.rf_strength),
});
});
Expand All @@ -24,7 +24,7 @@ async function updateNAPlug(deviceGladys, deviceNetatmo, externalId) {
.filter((feature) => feature.external_id === `${externalId}:wifi_strength`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:wifi_strength`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.wifi_strength),
});
});
Expand All @@ -33,12 +33,12 @@ async function updateNAPlug(deviceGladys, deviceNetatmo, externalId) {
.forEach((feature) => {
if (typeof deviceNetatmo.plug_connected_boiler !== 'undefined') {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:plug_connected_boiler`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.plug_connected_boiler),
});
} else {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:plug_connected_boiler`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](false),
});
}
Expand Down
14 changes: 7 additions & 7 deletions server/services/netatmo/lib/device/netatmo.updateNATherm1.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,55 +16,55 @@ async function updateNATherm1(deviceGladys, deviceNetatmo, externalId) {
.filter((feature) => feature.external_id === `${externalId}:battery_percent`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:battery_percent`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.battery_percent),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:temperature`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:temperature`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](measured.temperature),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:therm_measured_temperature`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:therm_measured_temperature`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](room.therm_measured_temperature),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:therm_setpoint_temperature`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:therm_setpoint_temperature`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](room.therm_setpoint_temperature),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:open_window`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:open_window`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](room.open_window),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:rf_strength`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:rf_strength`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.rf_strength),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:boiler_status`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: `${externalId}:boiler_status`,
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.boiler_status),
});
});
Expand Down
71 changes: 71 additions & 0 deletions server/services/netatmo/lib/device/netatmo.updateNRV.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const { EVENTS } = require('../../../../utils/constants');
const logger = require('../../../../utils/logger');
const { readValues } = require('./netatmo.deviceMapping');

/**
* @description Save values of valves NRV.
* @param {object} deviceGladys - Device object in Gladys.
* @param {object} deviceNetatmo - Device object coming from the Netatmo API.
* @param {string} externalId - Device identifier in gladys.
* @example updateNRV(deviceGladys, deviceNetatmo, externalId);
*/
async function updateNRV(deviceGladys, deviceNetatmo, externalId) {
const { room } = deviceNetatmo;
try {
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:battery_percent`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.battery_state),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:therm_measured_temperature`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](room.therm_measured_temperature),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:therm_setpoint_temperature`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](room.therm_setpoint_temperature),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:open_window`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](room.open_window),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:rf_strength`)
.forEach((feature) => {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](deviceNetatmo.rf_strength),
});
});
deviceGladys.features
.filter((feature) => feature.external_id === `${externalId}:heating_power_request`)
.forEach((feature) => {
const value = room.heating_power_request > 0;
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state: readValues[feature.category][feature.type](value),
});
});
} catch (e) {
logger.error('deviceGladys NRV: ', deviceGladys.name, 'error: ', e);
}
}

module.exports = {
updateNRV,
};
2 changes: 2 additions & 0 deletions server/services/netatmo/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const { setValue } = require('./netatmo.setValue');
const { updateValues } = require('./netatmo.updateValues');
const { updateNAPlug } = require('./device/netatmo.updateNAPlug');
const { updateNATherm1 } = require('./device/netatmo.updateNATherm1');
const { updateNRV } = require('./device/netatmo.updateNRV');

const { STATUS, SCOPES } = require('./utils/netatmo.constants');
const buildScopesConfig = require('./utils/netatmo.buildScopesConfig');
Expand Down Expand Up @@ -66,5 +67,6 @@ NetatmoHandler.prototype.setValue = setValue;
NetatmoHandler.prototype.updateValues = updateValues;
NetatmoHandler.prototype.updateNAPlug = updateNAPlug;
NetatmoHandler.prototype.updateNATherm1 = updateNATherm1;
NetatmoHandler.prototype.updateNRV = updateNRV;

module.exports = NetatmoHandler;
4 changes: 4 additions & 0 deletions server/services/netatmo/lib/netatmo.loadDeviceDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ async function loadDeviceDetails(homeData) {
moduleSupported = true;
categoryAPI = SUPPORTED_CATEGORY_TYPE.ENERGY;
break;
case SUPPORTED_MODULE_TYPE.NRV:
moduleSupported = true;
categoryAPI = SUPPORTED_CATEGORY_TYPE.ENERGY;
break;
default:
moduleSupported = false;
break;
Expand Down
4 changes: 4 additions & 0 deletions server/services/netatmo/lib/netatmo.updateValues.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ async function updateValues(deviceGladys, deviceNetatmo, externalId) {
await this.updateNATherm1(deviceGladys, deviceNetatmo, externalId);
break;
}
case SUPPORTED_MODULE_TYPE.NRV: {
await this.updateNRV(deviceGladys, deviceNetatmo, externalId);
break;
}
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions server/services/netatmo/lib/utils/netatmo.constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const SUPPORTED_CATEGORY_TYPE = {
const SUPPORTED_MODULE_TYPE = {
THERMOSTAT: 'NATherm1',
PLUG: 'NAPlug',
NRV: 'NRV',
};

const PARAMS = {
Expand Down
Loading

0 comments on commit 0de29d7

Please sign in to comment.