Skip to content

Commit

Permalink
ewelink: websocket instead of poll
Browse files Browse the repository at this point in the history
  • Loading branch information
atrovato committed Dec 12, 2023
1 parent e69876d commit 3024450
Show file tree
Hide file tree
Showing 45 changed files with 563 additions and 365 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class EweLinkDeviceBox extends Component {
) {
const validModel = device.features && device.features.length > 0;
const online = device.params.find(param => param.name === DEVICE_ONLINE).value === '1';
const firmware = device.params.find(param => param.name === DEVICE_FIRMWARE).value;
const firmware = (device.params.find(param => param.name === DEVICE_FIRMWARE) || { value: '?.?.?' }).value;

return (
<div class="col-md-6">
Expand Down
6 changes: 6 additions & 0 deletions server/services/ewelink/lib/config/ewelink.createClients.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ function createClients() {
appSecret: applicationSecret,
region: applicationRegion,
});

this.ewelinkWebSocketClientFactory = new this.eweLinkApi.Ws({
appId: applicationId,
appSecret: applicationSecret,
region: applicationRegion,
});
}

module.exports = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ async function loadConfiguration() {
}

const tokenObject = JSON.parse(tokens);

this.ewelinkWebAPIClient.at = tokenObject.accessToken;
this.ewelinkWebAPIClient.rt = tokenObject.refreshToken;

await this.createWebSocketClient();

logger.info('eWeLink: stored configuration well loaded...');
} catch (e) {
this.updateStatus({ configured: true, connected: false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async function saveConfiguration({ applicationId = '', applicationSecret = '', a

this.configuration = { applicationId, applicationSecret, applicationRegion };

this.closeWebSocketClient();
this.createClients();

this.updateStatus({ configured: true, connected: false });
Expand Down
88 changes: 0 additions & 88 deletions server/services/ewelink/lib/device/poll.js

This file was deleted.

3 changes: 1 addition & 2 deletions server/services/ewelink/lib/device/setValue.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const { DEVICE_FEATURE_TYPES } = require('../../../../utils/constants');
const logger = require('../../../../utils/logger');
const { writeBinaryValue } = require('../features/binary');
const { parseExternalId } = require('../utils/externalId');

/**
Expand All @@ -22,7 +21,7 @@ async function setValue(device, deviceFeature, value) {
0,
);

const binaryValue = writeBinaryValue(value);
const binaryValue = value ? 'on' : 'off';
if (nbBinaryFeatures > 1) {
params.switches = [{ switch: binaryValue, outlet: channel }];
} else {
Expand Down
1 change: 1 addition & 0 deletions server/services/ewelink/lib/ewelink.stop.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* await this.stop();
*/
async function stop() {
this.closeWebSocketClient();
this.ewelinkWebAPIClient = null;
this.updateStatus({ connected: false });
}
Expand Down
35 changes: 19 additions & 16 deletions server/services/ewelink/lib/features/binary.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
const { DEVICE_FEATURE_CATEGORIES, DEVICE_FEATURE_TYPES, STATE } = require('../../../../utils/constants');
const logger = require('../../../../utils/logger');
const { parseExternalId } = require('../utils/externalId');

module.exports = {
// Gladys feature
Expand All @@ -15,22 +13,27 @@ module.exports = {
max: 1,
};
},
pollBinary: (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;
}
readStates: (externalId, params) => {
const states = [];

// Single switch
if (params.switch) {
const state = params.switch === 'on' ? STATE.ON : STATE.OFF;
states.push({ featureExternalId: `${externalId}:binary:1`, state });
}
const currentBinaryState = state === 'on' ? STATE.ON : STATE.OFF;
// if the value is different from the value we have, save new state
if (state && feature.last_value !== currentBinaryState) {
logger.debug(`eWeLink: Polling device "${deviceId}", binary new value = ${currentBinaryState}`);
return currentBinaryState;

// Multiple switches
if (params.switches) {
params.switches.forEach(({ switch: value, outlet }) => {
const state = value === 'on' ? STATE.ON : STATE.OFF;
states.push({
featureExternalId: `${externalId}:binary:${outlet}`,
state,
});
});
}
return null;

return states;
},
// Gladys vs eWeLink transformers
writeBinaryValue: (value) => {
Expand Down
23 changes: 12 additions & 11 deletions server/services/ewelink/lib/features/humidity.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ const {
DEVICE_FEATURE_TYPES,
DEVICE_FEATURE_UNITS,
} = require('../../../../utils/constants');
const logger = require('../../../../utils/logger');
const { parseExternalId } = require('../utils/externalId');

module.exports = {
// Gladys feature
generateFeature: (name, channel = 0) => {
generateFeature: (name) => {
return {
name: `${name} Humidity`,
category: DEVICE_FEATURE_CATEGORIES.HUMIDITY_SENSOR,
Expand All @@ -20,14 +18,17 @@ module.exports = {
unit: DEVICE_FEATURE_UNITS.PERCENT,
};
},
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;
readStates: (externalId, params) => {
const states = [];

// Current humidity
if (params.currentHumidity) {
states.push({
featureExternalId: `${externalId}:humidity`,
state: params.currentHumidity,
});
}
return null;

return states;
},
};
55 changes: 25 additions & 30 deletions server/services/ewelink/lib/features/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const { DEVICE_POLL_FREQUENCIES } = require('../../../../utils/constants');
const logger = require('../../../../utils/logger');
const { titleize } = require('../../../../utils/titleize');
const { DEVICE_IP_ADDRESS, DEVICE_FIRMWARE, DEVICE_ONLINE } = require('../utils/constants');
const { readParams } = require('../params');
const { getExternalId } = require('../utils/externalId');

// Features
const binaryFeature = require('./binary');
const humidityFeature = require('./humidity');
const temperatureFeature = require('./temperature');

const AVAILABLE_FEATURES = [binaryFeature, humidityFeature, temperatureFeature];

const AVAILABLE_FEATURE_MODELS = {
binary: {
uiid: [1, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15],
Expand Down Expand Up @@ -37,17 +38,6 @@ const getDeviceName = (device) => {
return name.trim();
};

/**
* @description Convert online state.
* @param {boolean} online - Online device state.
* @returns {string} Return the prefix, the device ID and the channel count.
* @example
* readOnlineValue(true);
*/
function readOnlineValue(online) {
return online ? '1' : '0';
}

/**
* @description Create an eWeLink device for Gladys.
* @param {string} serviceId - The UUID of the service.
Expand All @@ -68,22 +58,8 @@ function getDevice(serviceId, device) {
selector: externalId,
features: [],
service_id: serviceId,
should_poll: true,
poll_frequency: DEVICE_POLL_FREQUENCIES.EVERY_30_SECONDS,
params: [
{
name: DEVICE_IP_ADDRESS,
value: device.ip || '?.?.?.?',
},
{
name: DEVICE_FIRMWARE,
value: params.fwVersion || '?.?.?',
},
{
name: DEVICE_ONLINE,
value: readOnlineValue(device.online),
},
],
should_poll: false,
params: readParams(device),
};

const deviceUiid = (device.extra || {}).uiid;
Expand Down Expand Up @@ -111,7 +87,26 @@ function getDevice(serviceId, device) {
return createdDevice;
}

/**
* @description Read and decode Gladys feature state from eWeLink object.
* @param {string} externalId - Device external ID.
* @param {object} params - EWeLink received params.
* @returns {Array} Arry of featureExternalId / state objects.
* @example
* const states = readStates('ewelink:10001a', { switch: 'on' });
*/
function readStates(externalId, params) {
const states = [];
AVAILABLE_FEATURES.forEach((feature) => {
const updatedStates = feature.readState(externalId, params);
updatedStates.forEach((state) => {
states.push(state);
});
});
return states;
}

module.exports = {
readOnlineValue,
getDevice,
readStates,
};
23 changes: 12 additions & 11 deletions server/services/ewelink/lib/features/temperature.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ const {
DEVICE_FEATURE_TYPES,
DEVICE_FEATURE_UNITS,
} = require('../../../../utils/constants');
const logger = require('../../../../utils/logger');
const { parseExternalId } = require('../utils/externalId');

module.exports = {
// Gladys feature
generateFeature: (name, channel = 0) => {
generateFeature: (name) => {
return {
name: `${name} Temperature`,
category: DEVICE_FEATURE_CATEGORIES.TEMPERATURE_SENSOR,
Expand All @@ -20,14 +18,17 @@ module.exports = {
unit: DEVICE_FEATURE_UNITS.CELSIUS,
};
},
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;
readStates: (externalId, params) => {
const states = [];

// Current temperature
if (params.currentTemperature) {
states.push({
featureExternalId: `${externalId}:temperature`,
state: params.currentTemperature,
});
}
return null;

return states;
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ async function handleResponse(response) {
case 401:
case 402:
await this.gladys.variable.destroy(CONFIGURATION_KEYS.USER_TOKENS, this.serviceId);
this.closeWebSocketClient();
this.updateStatus({ connected: false });
throw new ServiceNotConfiguredError(msg);
case 400:
Expand Down
Loading

0 comments on commit 3024450

Please sign in to comment.