Skip to content

Commit

Permalink
Change in feature management
Browse files Browse the repository at this point in the history
  • Loading branch information
NickDub committed Feb 18, 2021
1 parent e935c21 commit 2fbf431
Show file tree
Hide file tree
Showing 24 changed files with 298 additions and 274 deletions.
2 changes: 1 addition & 1 deletion server/lib/device/device.pollAll.js
Expand Up @@ -10,7 +10,7 @@ const Promise = require('bluebird');
function pollAll(pollFrequency) {
return async () => {
if (this.devicesByPollFrequency[pollFrequency]) {
return Promise.map(this.devicesByPollFrequency[pollFrequency], (device) => this.poll(device));
return Promise.map(this.devicesByPollFrequency[pollFrequency], (device) => this.poll(device), { concurrency: 1 });
}
return Promise.resolve();
};
Expand Down
4 changes: 2 additions & 2 deletions server/services/ewelink/lib/device/connect.js
Expand Up @@ -16,7 +16,7 @@ async function connect() {
let region = await this.gladys.variable.getValue(EWELINK_REGION_KEY, this.serviceId);

if (!email || !password) {
this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
await this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
type: WEBSOCKET_MESSAGE_TYPES.EWELINK.ERROR,
payload: 'Service is not configured',
});
Expand Down Expand Up @@ -46,7 +46,7 @@ async function connect() {
this.accessToken = auth.at;
this.apiKey = auth.user.apikey;

this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
await this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
type: WEBSOCKET_MESSAGE_TYPES.EWELINK.CONNECTED,
});
}
Expand Down
45 changes: 13 additions & 32 deletions server/services/ewelink/lib/device/discover.js
Expand Up @@ -29,40 +29,21 @@ async function discover() {
await Promise.map(
discoveredDevices,
async (discoveredDevice) => {
const channels = await connection.getDeviceChannelCount(discoveredDevice.deviceid);
logger.debug(`eWeLink: Get device channel count "${discoveredDevice.deviceid}": ${JSON.stringify(channels)}`);

if (channels.switchesAmount > 1) {
// ...for each channel of the device...
for (let channel = 1; channel <= channels.switchesAmount; channel += 1) {
// ...if it is already in Gladys...
const deviceInGladys = this.gladys.stateManager.get(
'deviceByExternalId',
features.getExternalId(discoveredDevice, channel),
);
if (deviceInGladys) {
logger.debug(`eWeLink: Device "${discoveredDevice.deviceid}" is already in Gladys !`);
} else {
logger.debug(
`eWeLink: Device "${discoveredDevice.deviceid}" found, uiid: ${discoveredDevice.uiid}, model: "${discoveredDevice.productModel}, channel: ${channel}/${channels.switchesAmount}`,
);
unknownDevices.push(features.getDevice(this.serviceId, discoveredDevice, channel));
}
}
// ...if it is already in Gladys...
const deviceInGladys = await this.gladys.stateManager.get(
'deviceByExternalId',
features.getExternalId(discoveredDevice),
);
if (deviceInGladys) {
logger.debug(`eWeLink: Device "${discoveredDevice.deviceid}" is already in Gladys !`);
} else {
// ...if it is already in Gladys...
const deviceInGladys = this.gladys.stateManager.get(
'deviceByExternalId',
features.getExternalId(discoveredDevice),
const channels = await connection.getDeviceChannelCount(discoveredDevice.deviceid);
logger.debug(`eWeLink: Get device channel count "${discoveredDevice.deviceid}": ${JSON.stringify(channels)}`);

logger.debug(
`eWeLink: Device "${discoveredDevice.deviceid}" found, uiid: ${discoveredDevice.uiid}, model: "${discoveredDevice.productModel}, switches: ${channels.switchesAmount}`,
);
if (deviceInGladys) {
logger.debug(`eWeLink: Device "${discoveredDevice.deviceid}" is already in Gladys !`);
} else {
logger.debug(
`eWeLink: Device "${discoveredDevice.deviceid}" found, uiid: ${discoveredDevice.uiid}, model: "${discoveredDevice.productModel}`,
);
unknownDevices.push(features.getDevice(this.serviceId, discoveredDevice));
}
unknownDevices.push(features.getDevice(this.serviceId, discoveredDevice, channels.switchesAmount));
}
},
{ concurrency: 1 },
Expand Down
4 changes: 2 additions & 2 deletions server/services/ewelink/lib/device/index.js
Expand Up @@ -41,7 +41,7 @@ async function throwErrorIfNeeded(response, emit = false, config = false) {
this.accessToken = '';
this.apiKey = '';
if (emit) {
this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
await this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
type: WEBSOCKET_MESSAGE_TYPES.EWELINK.ERROR,
payload: response.msg,
});
Expand All @@ -57,7 +57,7 @@ async function throwErrorIfNeeded(response, emit = false, config = false) {
throw new Error403(`eWeLink: ${response.msg}`);
}
if (emit) {
this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
await this.gladys.event.emit(EVENTS.WEBSOCKET.SEND_ALL, {
type: WEBSOCKET_MESSAGE_TYPES.EWELINK.ERROR,
payload: response.msg,
});
Expand Down
162 changes: 86 additions & 76 deletions server/services/ewelink/lib/device/poll.js
@@ -1,12 +1,68 @@
const Promise = require('bluebird');
const { EVENTS, DEVICE_FEATURE_CATEGORIES, DEVICE_FEATURE_TYPES } = require('../../../../utils/constants');
const { NotFoundError } = require('../../../../utils/coreErrors');
const { getDeviceFeature, getDeviceParam, setDeviceParam } = require('../../../../utils/device');
const { getDeviceParam, setDeviceParam } = require('../../../../utils/device');
const logger = require('../../../../utils/logger');
const { parseExternalId, readOnlineValue } = require('../features');
const power = require('../features/power');
const { DEVICE_FIRMWARE, EWELINK_REGION_KEY, DEVICE_ONLINE } = require('../utils/constants');

const pollPower = (eWeLinkDevice, feature) => {
const { deviceId, channel } = parseExternalId(feature.external_id);
let state = (eWeLinkDevice.params && eWeLinkDevice.params.switch) || false;
const switches = (eWeLinkDevice.params && eWeLinkDevice.params.switches) || false;
if (state || switches) {
if (switches) {
state = switches[channel - 1].switch;
}
}
const currentPowerState = power.readValue(state);
// if the value is different from the value we have, save new state
if (state && feature.last_value !== currentPowerState) {
logger.debug(`eWeLink: Polling device "${deviceId}", power new value = ${currentPowerState}`);
return currentPowerState;
}
return null;
};

const pollHumidity = (eWeLinkDevice, feature) => {
const { deviceId } = parseExternalId(feature.external_id);
const currentHumidity = (eWeLinkDevice.params && eWeLinkDevice.params.currentHumidity) || false;
// if the value is different from the value we have, save new state
if (currentHumidity && feature.last_value !== currentHumidity) {
logger.debug(`eWeLink: Polling device "${deviceId}", humidity new value = ${currentHumidity}`);
return currentHumidity;
}
return null;
};

const pollTemperature = (eWeLinkDevice, feature) => {
const { deviceId } = parseExternalId(feature.external_id);
const currentTemperature = (eWeLinkDevice.params && eWeLinkDevice.params.currentTemperature) || false;
// if the value is different from the value we have, save new state
if (currentTemperature && feature.last_value !== currentTemperature) {
logger.debug(`eWeLink: Polling device "${deviceId}", temperature new value = ${currentTemperature}`);
return currentTemperature;
}
return null;
};

// const pollEnergyPower = async (gladys, eWeLinkDevice, feature) => {
// const { deviceId } = parseExternalId(feature.external_id);
// const response = await connection.getDevicePowerUsage(deviceId);
// await this.throwErrorIfNeeded(response);

// const currentEnergyPowerState = response.monthly;
// // if the value is different from the value we have, save new state
// if (feature && feature.last_value !== currentEnergyPowerState) {
// logger.debug(`eWeLink: Polling device "${deviceId}", energyPower new value = ${currentEnergyPowerState}`);
// await gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
// device_feature_external_id: feature.external_id,
// state: currentEnergyPowerState,
// });
// }
// };

/**
*
* @description Poll values of an eWeLink device.
Expand All @@ -21,9 +77,10 @@ async function poll(device) {
}

const region = await this.gladys.variable.getValue(EWELINK_REGION_KEY, this.serviceId);
const { deviceId, channel } = parseExternalId(device.external_id);
const { deviceId } = parseExternalId(device.external_id);
const connection = new this.EweLinkApi({ at: this.accessToken, region });
const eWeLinkDevice = await connection.getDevice(deviceId);
logger.debug(`eWeLink: eWeLinkDevice: ${JSON.stringify(eWeLinkDevice)}`);
await this.throwErrorIfNeeded(eWeLinkDevice);

const onlineParam = getDeviceParam(device, DEVICE_ONLINE);
Expand All @@ -38,88 +95,41 @@ async function poll(device) {
throw new NotFoundError('eWeLink: Error, device is not currently online');
}

const powerFeature = getDeviceFeature(device, DEVICE_FEATURE_CATEGORIES.SWITCH, DEVICE_FEATURE_TYPES.SWITCH.BINARY);
if (powerFeature) {
const response = await connection.getDevicePowerState(deviceId, channel);
await this.throwErrorIfNeeded(response);

const currentPowerState = power.readValue(response.state);
// if the value is different from the value we have, save new state
if (powerFeature && powerFeature.last_value !== currentPowerState) {
logger.debug(`eWeLink: Polling device "${deviceId}", power new value = ${currentPowerState}`);
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: powerFeature.external_id,
state: currentPowerState,
});
await Promise.mapSeries(device.features || [], async (feature) => {
let state;
switch (feature.category) {
case DEVICE_FEATURE_CATEGORIES.SWITCH: // Power
if (feature.type === DEVICE_FEATURE_TYPES.SWITCH.BINARY) {
state = pollPower(eWeLinkDevice, feature);
}
// } else if (feature.type === DEVICE_FEATURE_TYPES.SWITCH.POWER) {
// await pollEnergyPower(this.gladys, eWeLinkDevice, feature);
// }
break;
case DEVICE_FEATURE_CATEGORIES.HUMIDITY_SENSOR: // Humidity
state = pollHumidity(eWeLinkDevice, feature);
break;
case DEVICE_FEATURE_CATEGORIES.TEMPERATURE_SENSOR: // Temperature
state = pollTemperature(eWeLinkDevice, feature);
break;
default:
break;
}
}

const energyPowerFeature = getDeviceFeature(
device,
DEVICE_FEATURE_CATEGORIES.SWITCH,
DEVICE_FEATURE_TYPES.SWITCH.POWER,
);
if (energyPowerFeature) {
const response = await connection.getDevicePowerUsage(deviceId);
await this.throwErrorIfNeeded(response);

const currentEnergyPowerState = response.monthly;
// if the value is different from the value we have, save new state
if (energyPowerFeature && energyPowerFeature.last_value !== currentEnergyPowerState) {
logger.debug(`eWeLink: Polling device "${deviceId}", energyPower new value = ${currentEnergyPowerState}`);
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: energyPowerFeature.external_id,
state: currentEnergyPowerState,
if (state !== null) {
logger.debug(`eWeLink: Polling device "${deviceId}", emit feature "${feature.external_id}" update`);
await this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: feature.external_id,
state,
});
}
}

const humidityFeature = getDeviceFeature(
device,
DEVICE_FEATURE_CATEGORIES.HUMIDITY_SENSOR,
DEVICE_FEATURE_TYPES.SENSOR.DECIMAL,
);
const temperatureFeature = getDeviceFeature(
device,
DEVICE_FEATURE_CATEGORIES.TEMPERATURE_SENSOR,
DEVICE_FEATURE_TYPES.SENSOR.DECIMAL,
);
if (humidityFeature || temperatureFeature) {
const response = await connection.getDeviceCurrentTH(deviceId);
await this.throwErrorIfNeeded(response);

if (humidityFeature && response.humidity) {
const currentHumidity = response.humidity;
// if the value is different from the value we have, save new state
if (temperatureFeature && temperatureFeature.last_value !== currentHumidity) {
logger.debug(`eWeLink: Polling device "${deviceId}", humidity new value = ${currentHumidity}`);
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: humidityFeature.external_id,
state: currentHumidity,
});
}
}
if (temperatureFeature && response.temperature) {
const currentTemperature = response.temperature;
// if the value is different from the value we have, save new state
if (temperatureFeature && temperatureFeature.last_value !== currentTemperature) {
logger.debug(`eWeLink: Polling device "${deviceId}", temperature new value = ${currentTemperature}`);
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: temperatureFeature.external_id,
state: currentTemperature,
});
}
}
}
});

const firmwareParam = getDeviceParam(device, DEVICE_FIRMWARE);
if (firmwareParam) {
const response = await connection.getFirmwareVersion(deviceId);
await this.throwErrorIfNeeded(response);

const currentVersion = response.fwVersion;
const currentVersion = (eWeLinkDevice.params && eWeLinkDevice.params.fwVersion) || false;
// if the value is different from the value we have, save new param
if (firmwareParam !== currentVersion) {
if (currentVersion && firmwareParam !== currentVersion) {
logger.debug(`eWeLink: Polling device "${deviceId}", firmware new value = ${currentVersion}`);
setDeviceParam(device, DEVICE_FIRMWARE, currentVersion);
}
Expand Down
Expand Up @@ -6,7 +6,7 @@ const {

module.exports = {
// Gladys feature
generateFeature: () => {
generateFeature: (channel = 0) => {
return {
name: 'Power',
category: DEVICE_FEATURE_CATEGORIES.SWITCH,
Expand Down
2 changes: 1 addition & 1 deletion server/services/ewelink/lib/features/humidity.js
Expand Up @@ -6,7 +6,7 @@ const {

module.exports = {
// Gladys feature
generateFeature: () => {
generateFeature: (channel = 0) => {
return {
name: 'Humidity',
category: DEVICE_FEATURE_CATEGORIES.HUMIDITY_SENSOR,
Expand Down

0 comments on commit 2fbf431

Please sign in to comment.