diff --git a/front/src/routes/integration/all/ewelink/EweLinkDeviceBox.jsx b/front/src/routes/integration/all/ewelink/EweLinkDeviceBox.jsx
index 03c7dcf9b4..d68cb24271 100644
--- a/front/src/routes/integration/all/ewelink/EweLinkDeviceBox.jsx
+++ b/front/src/routes/integration/all/ewelink/EweLinkDeviceBox.jsx
@@ -4,7 +4,7 @@ import cx from 'classnames';
import { Link } from 'preact-router';
import get from 'get-value';
-import { DEVICE_FIRMWARE, DEVICE_ONLINE } from '../../../../../../server/services/ewelink/lib/utils/constants';
+import { DEVICE_PARAMS } from '../../../../../../server/services/ewelink/lib/utils/constants';
import DeviceFeatures from '../../../../components/device/view/DeviceFeatures';
class EweLinkDeviceBox extends Component {
@@ -68,8 +68,8 @@ class EweLinkDeviceBox extends Component {
{ loading, errorMessage, tooMuchStatesError, statesNumber }
) {
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: '?.?.?' }).value;
+ const online = device.params.find(param => param.name === DEVICE_PARAMS.ONLINE).value === '1';
+ const firmware = (device.params.find(param => param.name === DEVICE_PARAMS.FIRMWARE) || { value: '?.?.?' }).value;
return (
- {device.params.find(param => param.name === DEVICE_FIRMWARE) && (
+ {device.params.find(param => param.name === DEVICE_PARAMS.FIRMWARE) && (
{`Firmware: ${firmware}`}
)}
diff --git a/server/services/ewelink/lib/config/ewelink.createClients.js b/server/services/ewelink/lib/config/ewelink.createClients.js
index 68287775cd..b033361ffa 100644
--- a/server/services/ewelink/lib/config/ewelink.createClients.js
+++ b/server/services/ewelink/lib/config/ewelink.createClients.js
@@ -12,7 +12,7 @@ function createClients() {
region: applicationRegion,
});
- this.ewelinkWebSocketClientFactory = new this.eweLinkApi.Ws({
+ this.ewelinkWebSocketClient = new this.eweLinkApi.Ws({
appId: applicationId,
appSecret: applicationSecret,
region: applicationRegion,
diff --git a/server/services/ewelink/lib/config/ewelink.loadConfiguration.js b/server/services/ewelink/lib/config/ewelink.loadConfiguration.js
index 6a47c9aaa5..bfb68a0a7a 100644
--- a/server/services/ewelink/lib/config/ewelink.loadConfiguration.js
+++ b/server/services/ewelink/lib/config/ewelink.loadConfiguration.js
@@ -46,6 +46,12 @@ async function loadConfiguration() {
this.ewelinkWebAPIClient.at = tokenObject.accessToken;
this.ewelinkWebAPIClient.rt = tokenObject.refreshToken;
+ // Load user API key
+ this.userApiKey = await this.gladys.variable.getValue(CONFIGURATION_KEYS.USER_API_KEY, this.serviceId);
+ if (!this.userApiKey) {
+ await this.retrieveUserApiKey();
+ }
+
await this.createWebSocketClient();
logger.info('eWeLink: stored configuration well loaded...');
diff --git a/server/services/ewelink/lib/device/discover.js b/server/services/ewelink/lib/device/discover.js
index 6463ba1185..813d56c655 100644
--- a/server/services/ewelink/lib/device/discover.js
+++ b/server/services/ewelink/lib/device/discover.js
@@ -1,3 +1,4 @@
+const { mergeDevices } = require('../../../../utils/device');
const logger = require('../../../../utils/logger');
const features = require('../features');
const { getExternalId } = require('../utils/externalId');
@@ -14,20 +15,16 @@ async function discover() {
);
logger.info(`eWeLink: ${thingList.length} device(s) found while retrieving from the cloud !`);
- const discoveredDevices = [];
+ const discoveredDevices = thingList.map(({ itemData }) => {
+ logger.debug(`eWeLink: new device "${itemData.deviceid}" (${itemData.productModel}) discovered`);
- thingList.forEach(({ itemData }) => {
const deviceInGladys = this.gladys.stateManager.get('deviceByExternalId', getExternalId(itemData));
- // ...if it is already in Gladys, ignore it...
- if (deviceInGladys) {
- logger.debug(`eWeLink: device "${itemData.deviceid}" is already in Gladys !`);
- } else {
- logger.debug(`eWeLink: new device "${itemData.deviceid}" (${itemData.productModel}) discovered`);
- const discoveredDevice = features.getDevice(this.serviceId, itemData);
- discoveredDevices.push(discoveredDevice);
- }
+ const discoveredDevice = features.getDevice(this.serviceId, itemData);
+ return mergeDevices(discoveredDevice, deviceInGladys);
});
+ this.discoveredDevices = discoveredDevices;
+
return discoveredDevices;
}
diff --git a/server/services/ewelink/lib/device/setValue.js b/server/services/ewelink/lib/device/setValue.js
index 0e93f971fe..89fb4630d9 100644
--- a/server/services/ewelink/lib/device/setValue.js
+++ b/server/services/ewelink/lib/device/setValue.js
@@ -1,39 +1,32 @@
const { DEVICE_FEATURE_TYPES } = require('../../../../utils/constants');
const logger = require('../../../../utils/logger');
+const binary = require('../features/binary');
const { parseExternalId } = require('../utils/externalId');
+const FEATURE_TYPE_MAP = {
+ [DEVICE_FEATURE_TYPES.SWITCH.BINARY]: binary,
+};
+
/**
* @description Change value of an eWeLink device.
* @param {object} device - The device to control.
* @param {object} deviceFeature - The deviceFeature to control.
* @param {string|number} value - The new value.
* @example
- * setValue(device, deviceFeature);
+ * setValue({ ...device }, { ...deviceFeature }, 1);
*/
async function setValue(device, deviceFeature, value) {
- const { deviceId, channel } = parseExternalId(deviceFeature.external_id);
- switch (deviceFeature.type) {
- case DEVICE_FEATURE_TYPES.SWITCH.BINARY: {
- const params = {};
- // Count number of binary features to determine if "switch" or "switches" param need to be changed
- const nbBinaryFeatures = device.features.reduce(
- (acc, currentFeature) => (currentFeature.type === DEVICE_FEATURE_TYPES.SWITCH.BINARY ? acc + 1 : acc),
- 0,
- );
+ const { external_id: featureExternalId, type } = deviceFeature;
- const binaryValue = value ? 'on' : 'off';
- if (nbBinaryFeatures > 1) {
- params.switches = [{ switch: binaryValue, outlet: channel }];
- } else {
- params.switch = binaryValue;
- }
+ const mapper = FEATURE_TYPE_MAP[type];
+ if (mapper) {
+ const parsedExternalId = parseExternalId(featureExternalId);
+ const { deviceId } = parsedExternalId;
+ const params = binary.writeParams(device, parsedExternalId, value);
- await this.handleRequest(async () => this.ewelinkWebAPIClient.device.setThingStatus(1, deviceId, params));
- break;
- }
- default:
- logger.warn(`eWeLink: Warning, feature type "${deviceFeature.type}" not handled yet!`);
- break;
+ this.ewelinkWebSocketClient.Connect.updateState(deviceId, params);
+ } else {
+ logger.warn(`eWeLink: Warning, feature type "${type}" not handled yet!`);
}
}
diff --git a/server/services/ewelink/lib/ewelink.stop.js b/server/services/ewelink/lib/ewelink.stop.js
index 60d41f2605..fb293e9131 100644
--- a/server/services/ewelink/lib/ewelink.stop.js
+++ b/server/services/ewelink/lib/ewelink.stop.js
@@ -4,8 +4,8 @@
* await this.stop();
*/
async function stop() {
- this.closeWebSocketClient();
this.ewelinkWebAPIClient = null;
+ this.closeWebSocketClient();
this.updateStatus({ connected: false });
}
diff --git a/server/services/ewelink/lib/features/binary.js b/server/services/ewelink/lib/features/binary.js
index f420fc7e60..6c8c16ccf3 100644
--- a/server/services/ewelink/lib/features/binary.js
+++ b/server/services/ewelink/lib/features/binary.js
@@ -27,7 +27,7 @@ module.exports = {
params.switches.forEach(({ switch: value, outlet }) => {
const state = value === 'on' ? STATE.ON : STATE.OFF;
states.push({
- featureExternalId: `${externalId}:binary:${outlet}`,
+ featureExternalId: `${externalId}:binary:${outlet + 1}`,
state,
});
});
@@ -35,4 +35,20 @@ module.exports = {
return states;
},
+ writeParams: (device, parsedExternalId, value) => {
+ const convertedValue = value ? 'on' : 'off';
+
+ // Count number of binary features to determine if "switch" or "switches" param need to be changed
+ const nbBinaryFeatures = device.features.reduce(
+ (acc, currentFeature) => (currentFeature.type === DEVICE_FEATURE_TYPES.SWITCH.BINARY ? acc + 1 : acc),
+ 0,
+ );
+
+ if (nbBinaryFeatures > 1) {
+ const { channel } = parsedExternalId;
+ return { switches: [{ switch: convertedValue, outlet: channel - 1 }] };
+ }
+
+ return { switch: convertedValue };
+ },
};
diff --git a/server/services/ewelink/lib/features/index.js b/server/services/ewelink/lib/features/index.js
index 377aec6da3..588f402373 100644
--- a/server/services/ewelink/lib/features/index.js
+++ b/server/services/ewelink/lib/features/index.js
@@ -12,7 +12,7 @@ const AVAILABLE_FEATURES = [binaryFeature, humidityFeature, temperatureFeature];
const AVAILABLE_FEATURE_MODELS = {
binary: {
- uiid: [1, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15],
+ uiid: [1, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 126],
feature: binaryFeature,
},
humidity: {
diff --git a/server/services/ewelink/lib/handlers/ewelink.handleRequest.js b/server/services/ewelink/lib/handlers/ewelink.handleRequest.js
index a64a1a73c9..2e7577a1f9 100644
--- a/server/services/ewelink/lib/handlers/ewelink.handleRequest.js
+++ b/server/services/ewelink/lib/handlers/ewelink.handleRequest.js
@@ -4,15 +4,16 @@ const { NB_MAX_RETRY_EXPIRED } = require('../utils/constants');
/**
* @description Provides a single way to manage WS requests with retries and refresh token.
* @param {Function} request - Client request.
+ * @param {boolean} force - Forces API call even if service is not marked as ready (eg. At the init phase).
* @param {number} nbRetry - Number of retry.
* @returns {Promise} The WS call response.
* @example
* const data = await this.handleRequest(() => client.getDevices());
*/
-async function handleRequest(request, nbRetry = 0) {
+async function handleRequest(request, force = false, nbRetry = 0) {
// Do not call API if service is not ready
const { configured, connected } = this.status;
- if (!configured || !connected) {
+ if (!force && (!configured || !connected)) {
throw new ServiceNotConfiguredError('eWeLink is not ready, please complete the configuration');
}
@@ -26,7 +27,7 @@ async function handleRequest(request, nbRetry = 0) {
// Store new tokens
await this.saveTokens(tokens);
// Retry request
- return this.handleRequest(request, nbRetry + 1);
+ return this.handleRequest(request, force, nbRetry + 1);
}
return this.handleResponse(response);
diff --git a/server/services/ewelink/lib/handlers/ewelink.handleResponse.js b/server/services/ewelink/lib/handlers/ewelink.handleResponse.js
index 75a4b3ab01..3f8d147117 100644
--- a/server/services/ewelink/lib/handlers/ewelink.handleResponse.js
+++ b/server/services/ewelink/lib/handlers/ewelink.handleResponse.js
@@ -10,26 +10,27 @@ const { CONFIGURATION_KEYS } = require('../utils/constants');
* const data = this.handleResponse(res, (data) => console.log);
*/
async function handleResponse(response) {
- const { error, msg, data } = response;
+ const { error, msg, reason, data } = response;
+ const message = msg || reason;
logger.debug(`eWeLink response: %j`, response);
if (error) {
// see https://coolkit-technologies.github.io/eWeLink-API/#/en/APICenterV2?id=error-codes
- logger.error(`eWeLink: error with API - ${msg}`);
+ logger.error(`eWeLink: error with API - ${message}`);
switch (error) {
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);
+ throw new ServiceNotConfiguredError(message);
case 400:
- throw new BadParameters(msg);
+ throw new BadParameters(message);
case 405:
case 4002:
- throw new NotFoundError(msg);
+ throw new NotFoundError(message);
default:
- throw new Error(msg);
+ throw new Error(message);
}
}
diff --git a/server/services/ewelink/lib/index.js b/server/services/ewelink/lib/index.js
index 19c0957c30..2caf77566b 100644
--- a/server/services/ewelink/lib/index.js
+++ b/server/services/ewelink/lib/index.js
@@ -12,6 +12,7 @@ const { buildLoginUrl } = require('./user/ewelink.buildLoginUrl');
const { exchangeToken } = require('./user/ewelink.exchangeToken');
const { deleteTokens } = require('./user/ewelink.deleteTokens');
const { saveTokens } = require('./user/ewelink.saveTokens');
+const { retrieveUserApiKey } = require('./user/ewelink.retrieveUserApiKey');
const { handleRequest } = require('./handlers/ewelink.handleRequest');
const { handleResponse } = require('./handlers/ewelink.handleResponse');
@@ -41,8 +42,10 @@ const EweLinkHandler = function EweLinkHandler(gladys, eweLinkApi, serviceId) {
this.serviceId = serviceId;
this.ewelinkWebAPIClient = null;
- this.ewelinkWebSocketClientFactory = null;
this.ewelinkWebSocketClient = null;
+ this.userApiKey = null;
+
+ this.discoveredDevices = [];
this.loginState = null;
this.configuration = {};
@@ -53,6 +56,7 @@ const EweLinkHandler = function EweLinkHandler(gladys, eweLinkApi, serviceId) {
};
EweLinkHandler.prototype.updateStatus = updateStatus;
+EweLinkHandler.prototype.getStatus = getStatus;
EweLinkHandler.prototype.saveConfiguration = saveConfiguration;
EweLinkHandler.prototype.loadConfiguration = loadConfiguration;
@@ -62,13 +66,13 @@ EweLinkHandler.prototype.buildLoginUrl = buildLoginUrl;
EweLinkHandler.prototype.exchangeToken = exchangeToken;
EweLinkHandler.prototype.deleteTokens = deleteTokens;
EweLinkHandler.prototype.saveTokens = saveTokens;
+EweLinkHandler.prototype.retrieveUserApiKey = retrieveUserApiKey;
EweLinkHandler.prototype.handleRequest = handleRequest;
EweLinkHandler.prototype.handleResponse = handleResponse;
EweLinkHandler.prototype.discover = discover;
EweLinkHandler.prototype.setValue = setValue;
-EweLinkHandler.prototype.getStatus = getStatus;
EweLinkHandler.prototype.createWebSocketClient = createWebSocketClient;
EweLinkHandler.prototype.closeWebSocketClient = closeWebSocketClient;
diff --git a/server/services/ewelink/lib/params/apikey.param.js b/server/services/ewelink/lib/params/apikey.param.js
new file mode 100644
index 0000000000..442a39bad1
--- /dev/null
+++ b/server/services/ewelink/lib/params/apikey.param.js
@@ -0,0 +1,6 @@
+const { DEVICE_PARAMS } = require('../utils/constants');
+
+module.exports = {
+ EWELINK_KEY_PATH: 'apikey',
+ GLADYS_PARAM_KEY: DEVICE_PARAMS.API_KEY,
+};
diff --git a/server/services/ewelink/lib/params/firmware.param.js b/server/services/ewelink/lib/params/firmware.param.js
index de586be0f9..f15a989097 100644
--- a/server/services/ewelink/lib/params/firmware.param.js
+++ b/server/services/ewelink/lib/params/firmware.param.js
@@ -1,4 +1,6 @@
+const { DEVICE_PARAMS } = require('../utils/constants');
+
module.exports = {
EWELINK_KEY_PATH: 'params.fwVersion',
- GLADYS_PARAM_KEY: 'FIRMWARE',
+ GLADYS_PARAM_KEY: DEVICE_PARAMS.FIRMWARE,
};
diff --git a/server/services/ewelink/lib/params/index.js b/server/services/ewelink/lib/params/index.js
index e16581b789..e5197f662f 100644
--- a/server/services/ewelink/lib/params/index.js
+++ b/server/services/ewelink/lib/params/index.js
@@ -1,9 +1,10 @@
const get = require('get-value');
-const onlineParam = require('./online.param');
const firmwareParam = require('./firmware.param');
+const onlineParam = require('./online.param');
+const apiKeyParam = require('./apikey.param');
-const PARAMS = [firmwareParam, onlineParam];
+const PARAMS = [firmwareParam, onlineParam, apiKeyParam];
/**
* @description Read device params from eWeLink device params.
diff --git a/server/services/ewelink/lib/params/online.param.js b/server/services/ewelink/lib/params/online.param.js
index 884a4408f0..284ae015d7 100644
--- a/server/services/ewelink/lib/params/online.param.js
+++ b/server/services/ewelink/lib/params/online.param.js
@@ -1,3 +1,5 @@
+const { DEVICE_PARAMS } = require('../utils/constants');
+
/**
* @description Convert online state.
* @param {boolean} rawValue - Param raw value.
@@ -11,6 +13,6 @@ function convertValue(rawValue) {
module.exports = {
EWELINK_KEY_PATH: 'online',
- GLADYS_PARAM_KEY: 'ONLINE',
+ GLADYS_PARAM_KEY: DEVICE_PARAMS.ONLINE,
convertValue,
};
diff --git a/server/services/ewelink/lib/user/ewelink.exchangeToken.js b/server/services/ewelink/lib/user/ewelink.exchangeToken.js
index d9e0ce54f5..2413368721 100644
--- a/server/services/ewelink/lib/user/ewelink.exchangeToken.js
+++ b/server/services/ewelink/lib/user/ewelink.exchangeToken.js
@@ -31,6 +31,8 @@ async function exchangeToken({ redirectUrl, code, region, state }) {
await this.saveTokens(data);
+ await this.retrieveUserApiKey();
+
await this.createWebSocketClient();
this.updateStatus({ connected: true });
diff --git a/server/services/ewelink/lib/user/ewelink.retrieveUserApiKey.js b/server/services/ewelink/lib/user/ewelink.retrieveUserApiKey.js
new file mode 100644
index 0000000000..915dbb5a9a
--- /dev/null
+++ b/server/services/ewelink/lib/user/ewelink.retrieveUserApiKey.js
@@ -0,0 +1,32 @@
+const { ServiceNotConfiguredError } = require('../../../../utils/coreErrors');
+const logger = require('../../../../utils/logger');
+const { CONFIGURATION_KEYS } = require('../utils/constants');
+
+/**
+ * @description Retrieve the user API key from eWeLink user family. It also store in database.
+ * @example
+ * await this.retrieveUserApiKey();
+ */
+async function retrieveUserApiKey() {
+ logger.info('eWeLink: loading user API key...');
+
+ // Load API key
+ const { currentFamilyId, familyList } = await this.handleRequest(
+ () => this.ewelinkWebAPIClient.home.getFamily(),
+ true,
+ );
+ const { apikey: apiKey } = familyList.find((family) => family.id === currentFamilyId) || {};
+
+ // Store API key
+ if (apiKey) {
+ logger.info('eWeLink: saving user API key...');
+ this.userApiKey = apiKey;
+ await this.gladys.variable.setValue(CONFIGURATION_KEYS.USER_API_KEY, apiKey, this.serviceId);
+ } else {
+ throw new ServiceNotConfiguredError('eWeLink: no user API key retrieved');
+ }
+}
+
+module.exports = {
+ retrieveUserApiKey,
+};
diff --git a/server/services/ewelink/lib/utils/constants.js b/server/services/ewelink/lib/utils/constants.js
index 85c5431602..3b454525ad 100644
--- a/server/services/ewelink/lib/utils/constants.js
+++ b/server/services/ewelink/lib/utils/constants.js
@@ -3,9 +3,16 @@ const CONFIGURATION_KEYS = {
APPLICATION_SECRET: 'APPLICATION_SECRET',
APPLICATION_REGION: 'APPLICATION_REGION',
USER_TOKENS: 'USER_TOKENS',
+ USER_API_KEY: 'USER_API_KEY',
SERVICE_VERSION: 'SERVICE_VERSION',
};
+const DEVICE_PARAMS = {
+ ONLINE: 'ONLINE',
+ FIRMWARE: 'FIRMWARE',
+ API_KEY: 'API_KEY',
+};
+
const DEVICE_SERVICE_ID = 'ewelink';
const DEVICE_EXTERNAL_ID_BASE = 'ewelink';
@@ -13,6 +20,7 @@ const NB_MAX_RETRY_EXPIRED = 1;
module.exports = {
CONFIGURATION_KEYS,
+ DEVICE_PARAMS,
DEVICE_SERVICE_ID,
DEVICE_EXTERNAL_ID_BASE,
NB_MAX_RETRY_EXPIRED,
diff --git a/server/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.js b/server/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.js
index d1303823b5..9929433077 100644
--- a/server/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.js
+++ b/server/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.js
@@ -4,9 +4,8 @@
* this.closeWebSocketClient();
*/
function closeWebSocketClient() {
- if (this.ewelinkWebSocketClient !== null) {
- this.ewelinkWebSocketClient.close();
- this.ewelinkWebSocketClient = null;
+ if (this.ewelinkWebSocketClient && this.ewelinkWebSocketClient.Connect && this.ewelinkWebSocketClient.Connect.ws) {
+ this.ewelinkWebSocketClient.Connect.ws.close();
}
}
diff --git a/server/services/ewelink/lib/websocket/ewelink.createWebSocketClient.js b/server/services/ewelink/lib/websocket/ewelink.createWebSocketClient.js
index 9ca5444e1c..351359dae3 100644
--- a/server/services/ewelink/lib/websocket/ewelink.createWebSocketClient.js
+++ b/server/services/ewelink/lib/websocket/ewelink.createWebSocketClient.js
@@ -5,7 +5,8 @@
*/
async function createWebSocketClient() {
const { applicationId: appId, applicationRegion: region } = this.configuration;
- this.ewelinkWebSocketClient = await this.ewelinkWebSocketClientFactory.Connect.create(
+ this.ewelinkWebSocketClient.userApiKey = this.userApiKey;
+ await this.ewelinkWebSocketClient.Connect.create(
{
appId,
region,
diff --git a/server/services/ewelink/lib/websocket/ewelink.onWebSocketClose.js b/server/services/ewelink/lib/websocket/ewelink.onWebSocketClose.js
index a3fd3bf0fe..ccf2609b18 100644
--- a/server/services/ewelink/lib/websocket/ewelink.onWebSocketClose.js
+++ b/server/services/ewelink/lib/websocket/ewelink.onWebSocketClose.js
@@ -3,11 +3,15 @@ const logger = require('../../../../utils/logger');
/**
* @description Action to execute when WebSocket is closed.
* @example
- * this.onWebSocketClose();
+ * await this.onWebSocketClose();
*/
-function onWebSocketClose() {
- this.closeWebSocketClient();
- logger.info('eWeLink: WebSocket is closed');
+async function onWebSocketClose() {
+ logger.warn('eWeLink: WebSocket is closed');
+
+ // Try to reopen it if Gladys is not stopping
+ if (this.ewelinkWebSocketClient !== null) {
+ await this.createWebSocketClient();
+ }
}
module.exports = {
diff --git a/server/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.js b/server/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.js
index 623fbb5fab..cf95b91e84 100644
--- a/server/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.js
+++ b/server/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.js
@@ -11,16 +11,30 @@ const { readParams } = require('../params');
/**
* @description Action to execute when WebSocket receives a message.
* @param {object} ws - Current WebSocket client.
- * @param {object} message - WebSocket message.
+ * @param {object} message - WebSocket event message.
* @example
- * this.onWebSocketMessage();
+ * await this.onWebSocketMessage();
*/
async function onWebSocketMessage(ws, message) {
- logger.debug('eWeLink: WebSocket received a message: %j', message);
+ const { data: rawData = '' } = message;
+ logger.debug('eWeLink: WebSocket received a message with data: %s', rawData);
+ let data = {};
+ try {
+ data = JSON.parse(rawData);
+ } catch (e) {
+ logger.debug('eWeLink: WebSocket message is not a JSON object');
+ }
+
+ await this.handleResponse(data);
+
+ const { deviceid, params = {} } = data;
- await this.handleResponse(message);
+ // Message is not concerning a device
+ if (!deviceid) {
+ logger.debug('eWeLink: WebSocket message is not about a device, skipping it...');
+ return;
+ }
- const { deviceid = '', params = {} } = message;
const externalId = getExternalId({ deviceid });
// Load device to update params
@@ -33,13 +47,16 @@ async function onWebSocketMessage(ws, message) {
states.forEach(({ featureExternalId, state }) => {
// Before sending event, check if feature exists
const feature = this.gladys.stateManager.get('deviceFeatureByExternalId', featureExternalId);
- if (feature) {
+ if (!feature) {
+ logger.debug(`eWeLink: feature "${featureExternalId}" not found in Gladys`);
+ } else if (feature.last_value === state) {
+ // And check if value has really changed
+ logger.debug(`eWeLink: feature "${featureExternalId}" state already up-to-date`);
+ } else {
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
device_feature_external_id: featureExternalId,
state,
});
- } else {
- logger.debug(`eWeLink: feature ${featureExternalId} not found in Gladys`);
}
});
diff --git a/server/test/services/ewelink/lib/config/ewelink.loadConfiguration.test.js b/server/test/services/ewelink/lib/config/ewelink.loadConfiguration.test.js
index 95bc480b3e..cc95f5815a 100644
--- a/server/test/services/ewelink/lib/config/ewelink.loadConfiguration.test.js
+++ b/server/test/services/ewelink/lib/config/ewelink.loadConfiguration.test.js
@@ -1,9 +1,14 @@
const { expect } = require('chai');
const sinon = require('sinon');
+const proxyquire = require('proxyquire').noCallThru();
const { assert, fake, stub, match } = sinon;
-const EwelinkHandler = require('../../../../../services/ewelink/lib');
+const retrieveUserApiKey = fake.resolves(null);
+
+const EwelinkHandler = proxyquire('../../../../../services/ewelink/lib', {
+ './user/ewelink.retrieveUserApiKey': { retrieveUserApiKey },
+});
const { SERVICE_ID } = require('../constants');
const { ServiceNotConfiguredError } = require('../../../../../utils/coreErrors');
const { EVENTS, WEBSOCKET_MESSAGE_TYPES } = require('../../../../../utils/constants');
@@ -46,21 +51,22 @@ describe('eWeLinkHandler loadConfiguration', () => {
} catch (e) {
expect(e).instanceOf(ServiceNotConfiguredError);
expect(e.message).is.eq('eWeLink configuration is not setup');
+ }
- assert.callCount(gladys.event.emit, 2);
- assert.alwaysCalledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
- type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
- payload: { configured: false, connected: false },
- });
+ assert.callCount(gladys.event.emit, 2);
+ assert.alwaysCalledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
+ type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
+ payload: { configured: false, connected: false },
+ });
- assert.callCount(gladys.variable.getValue, 3);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
+ assert.callCount(gladys.variable.getValue, 3);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
- assert.notCalled(eWeLinkApiMock.WebAPI);
- assert.notCalled(eWeLinkApiMock.Ws);
- }
+ assert.notCalled(eWeLinkApiMock.WebAPI);
+ assert.notCalled(eWeLinkApiMock.Ws);
+ assert.notCalled(retrieveUserApiKey);
});
it('should throw a ServiceNotConfiguredError as only APPLICATION_ID variable is stored in database', async () => {
@@ -75,21 +81,22 @@ describe('eWeLinkHandler loadConfiguration', () => {
} catch (e) {
expect(e).instanceOf(ServiceNotConfiguredError);
expect(e.message).is.eq('eWeLink configuration is not setup');
+ }
- assert.callCount(gladys.event.emit, 2);
- assert.alwaysCalledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
- type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
- payload: { configured: false, connected: false },
- });
+ assert.callCount(gladys.event.emit, 2);
+ assert.alwaysCalledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
+ type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
+ payload: { configured: false, connected: false },
+ });
- assert.callCount(gladys.variable.getValue, 3);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
+ assert.callCount(gladys.variable.getValue, 3);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
- assert.notCalled(eWeLinkApiMock.WebAPI);
- assert.notCalled(eWeLinkApiMock.Ws);
- }
+ assert.notCalled(eWeLinkApiMock.WebAPI);
+ assert.notCalled(eWeLinkApiMock.Ws);
+ assert.notCalled(retrieveUserApiKey);
});
it('should throw a ServiceNotConfiguredError as only APPLICATION_ID and APPLICATION_SECRET variable are stored in database', async () => {
@@ -106,21 +113,22 @@ describe('eWeLinkHandler loadConfiguration', () => {
} catch (e) {
expect(e).instanceOf(ServiceNotConfiguredError);
expect(e.message).is.eq('eWeLink configuration is not setup');
+ }
- assert.callCount(gladys.event.emit, 2);
- assert.alwaysCalledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
- type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
- payload: { configured: false, connected: false },
- });
+ assert.callCount(gladys.event.emit, 2);
+ assert.alwaysCalledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
+ type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
+ payload: { configured: false, connected: false },
+ });
- assert.callCount(gladys.variable.getValue, 3);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
+ assert.callCount(gladys.variable.getValue, 3);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
- assert.notCalled(eWeLinkApiMock.WebAPI);
- assert.notCalled(eWeLinkApiMock.Ws);
- }
+ assert.notCalled(eWeLinkApiMock.WebAPI);
+ assert.notCalled(eWeLinkApiMock.Ws);
+ assert.notCalled(retrieveUserApiKey);
});
it('should throw a ServiceNotConfiguredError as USER_TOKENS variable is missing in database', async () => {
@@ -139,36 +147,37 @@ describe('eWeLinkHandler loadConfiguration', () => {
} catch (e) {
expect(e).instanceOf(ServiceNotConfiguredError);
expect(e.message).is.eq('eWeLink user is not connected');
-
- assert.callCount(gladys.event.emit, 2);
- assert.calledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
- type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
- payload: { configured: false, connected: false },
- });
- assert.calledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
- type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
- payload: { configured: true, connected: false },
- });
-
- assert.callCount(gladys.variable.getValue, 4);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
- assert.calledWithExactly(gladys.variable.getValue, 'USER_TOKENS', SERVICE_ID);
-
- assert.calledOnceWithExactly(eWeLinkApiMock.WebAPI, {
- appId: 'APPLICATION_ID_VALUE',
- appSecret: 'APPLICATION_SECRET_VALUE',
- region: 'APPLICATION_REGION_VALUE',
- });
- assert.calledOnceWithExactly(eWeLinkApiMock.Ws, {
- appId: 'APPLICATION_ID_VALUE',
- appSecret: 'APPLICATION_SECRET_VALUE',
- region: 'APPLICATION_REGION_VALUE',
- });
-
- assert.notCalled(eWeLinkWsMock.prototype.Connect.create);
}
+
+ assert.callCount(gladys.event.emit, 2);
+ assert.calledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
+ type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
+ payload: { configured: false, connected: false },
+ });
+ assert.calledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
+ type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
+ payload: { configured: true, connected: false },
+ });
+
+ assert.callCount(gladys.variable.getValue, 4);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'USER_TOKENS', SERVICE_ID);
+
+ assert.calledOnceWithExactly(eWeLinkApiMock.WebAPI, {
+ appId: 'APPLICATION_ID_VALUE',
+ appSecret: 'APPLICATION_SECRET_VALUE',
+ region: 'APPLICATION_REGION_VALUE',
+ });
+ assert.calledOnceWithExactly(eWeLinkApiMock.Ws, {
+ appId: 'APPLICATION_ID_VALUE',
+ appSecret: 'APPLICATION_SECRET_VALUE',
+ region: 'APPLICATION_REGION_VALUE',
+ });
+
+ assert.notCalled(eWeLinkWsMock.prototype.Connect.create);
+ assert.notCalled(retrieveUserApiKey);
});
it('should be well configured', async () => {
@@ -180,7 +189,9 @@ describe('eWeLinkHandler loadConfiguration', () => {
.resolves('APPLICATION_SECRET_VALUE')
.onThirdCall()
.resolves('APPLICATION_REGION_VALUE')
- .resolves('{ "accessToken": "ACCESS_TOKEN", "refreshToken": "REFRESH_TOKEN" }');
+ .onCall(3)
+ .resolves('{ "accessToken": "ACCESS_TOKEN", "refreshToken": "REFRESH_TOKEN" }')
+ .resolves('API_KEY');
await eWeLinkHandler.loadConfiguration();
@@ -194,11 +205,74 @@ describe('eWeLinkHandler loadConfiguration', () => {
payload: { configured: true, connected: true },
});
- assert.callCount(gladys.variable.getValue, 4);
+ assert.callCount(gladys.variable.getValue, 5);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'USER_TOKENS', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'USER_API_KEY', SERVICE_ID);
+
+ assert.notCalled(retrieveUserApiKey);
+
+ assert.calledOnceWithExactly(eWeLinkApiMock.WebAPI, {
+ appId: 'APPLICATION_ID_VALUE',
+ appSecret: 'APPLICATION_SECRET_VALUE',
+ region: 'APPLICATION_REGION_VALUE',
+ });
+ assert.calledOnceWithExactly(eWeLinkApiMock.Ws, {
+ appId: 'APPLICATION_ID_VALUE',
+ appSecret: 'APPLICATION_SECRET_VALUE',
+ region: 'APPLICATION_REGION_VALUE',
+ });
+
+ assert.calledOnce(eWeLinkWsMock.prototype.Connect.create);
+ assert.calledWithMatch(
+ eWeLinkWsMock.prototype.Connect.create,
+ match({ appId: 'APPLICATION_ID_VALUE', region: 'APPLICATION_REGION_VALUE', at: 'ACCESS_TOKEN' }),
+ match.func,
+ match.func,
+ match.func,
+ match.func,
+ );
+
+ expect(eWeLinkHandler.ewelinkWebAPIClient.at).eq('ACCESS_TOKEN');
+ expect(eWeLinkHandler.ewelinkWebAPIClient.rt).eq('REFRESH_TOKEN');
+ expect(eWeLinkHandler.ewelinkWebSocketClient.userApiKey).eq('API_KEY');
+ });
+
+ it('should retreive API key', async () => {
+ gladys.variable.getValue = sinon
+ .stub()
+ .onFirstCall()
+ .resolves('APPLICATION_ID_VALUE')
+ .onSecondCall()
+ .resolves('APPLICATION_SECRET_VALUE')
+ .onThirdCall()
+ .resolves('APPLICATION_REGION_VALUE')
+ .onCall(3)
+ .resolves('{ "accessToken": "ACCESS_TOKEN", "refreshToken": "REFRESH_TOKEN" }')
+ .resolves(null);
+
+ await eWeLinkHandler.loadConfiguration();
+
+ assert.callCount(gladys.event.emit, 2);
+ assert.calledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
+ type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
+ payload: { configured: false, connected: false },
+ });
+ assert.calledWithExactly(gladys.event.emit, EVENTS.WEBSOCKET.SEND_ALL, {
+ type: WEBSOCKET_MESSAGE_TYPES.EWELINK.STATUS,
+ payload: { configured: true, connected: true },
+ });
+
+ assert.callCount(gladys.variable.getValue, 5);
assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_ID', SERVICE_ID);
assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_SECRET', SERVICE_ID);
assert.calledWithExactly(gladys.variable.getValue, 'APPLICATION_REGION', SERVICE_ID);
assert.calledWithExactly(gladys.variable.getValue, 'USER_TOKENS', SERVICE_ID);
+ assert.calledWithExactly(gladys.variable.getValue, 'USER_API_KEY', SERVICE_ID);
+
+ assert.calledOnceWithExactly(retrieveUserApiKey);
assert.calledOnceWithExactly(eWeLinkApiMock.WebAPI, {
appId: 'APPLICATION_ID_VALUE',
diff --git a/server/test/services/ewelink/lib/config/ewelink.saveConfiguration.test.js b/server/test/services/ewelink/lib/config/ewelink.saveConfiguration.test.js
index 6111dc12f7..8784c430e8 100644
--- a/server/test/services/ewelink/lib/config/ewelink.saveConfiguration.test.js
+++ b/server/test/services/ewelink/lib/config/ewelink.saveConfiguration.test.js
@@ -49,7 +49,7 @@ describe('eWeLinkHandler saveConfiguration', () => {
assert.notCalled(gladys.variable.destroy);
expect(eWeLinkHandler.ewelinkWebAPIClient).eq(null);
- expect(eWeLinkHandler.ewelinkWebSocketClientFactory).eq(null);
+ expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
});
@@ -67,7 +67,7 @@ describe('eWeLinkHandler saveConfiguration', () => {
assert.notCalled(gladys.variable.destroy);
expect(eWeLinkHandler.ewelinkWebAPIClient).eq(null);
- expect(eWeLinkHandler.ewelinkWebSocketClientFactory).eq(null);
+ expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
});
@@ -85,7 +85,7 @@ describe('eWeLinkHandler saveConfiguration', () => {
assert.notCalled(gladys.variable.destroy);
expect(eWeLinkHandler.ewelinkWebAPIClient).eq(null);
- expect(eWeLinkHandler.ewelinkWebSocketClientFactory).eq(null);
+ expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
});
@@ -113,7 +113,7 @@ describe('eWeLinkHandler saveConfiguration', () => {
assert.notCalled(gladys.variable.destroy);
expect(eWeLinkHandler.ewelinkWebAPIClient).eq(null);
- expect(eWeLinkHandler.ewelinkWebSocketClientFactory).eq(null);
+ expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
});
@@ -141,7 +141,6 @@ describe('eWeLinkHandler saveConfiguration', () => {
assert.calledOnceWithExactly(gladys.variable.destroy, 'USER_TOKENS', SERVICE_ID);
expect(eWeLinkHandler.ewelinkWebAPIClient).not.eq(null);
- expect(eWeLinkHandler.ewelinkWebSocketClientFactory).not.eq(null);
- expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
+ expect(eWeLinkHandler.ewelinkWebSocketClient).not.eq(null);
});
});
diff --git a/server/test/services/ewelink/lib/device/discover.test.js b/server/test/services/ewelink/lib/device/discover.test.js
index 357af47941..e12f6299fe 100644
--- a/server/test/services/ewelink/lib/device/discover.test.js
+++ b/server/test/services/ewelink/lib/device/discover.test.js
@@ -47,17 +47,28 @@ describe('EweLinkHandler discover', () => {
sinon.reset();
});
- it('should found 3 devices, 2 of wich are already in Gladys and 3 are a new unknown device', async () => {
+ it('should found 5 devices, 2 of wich are already in Gladys and 3 are a new unknown device', async () => {
const newDevices = await eWeLinkHandler.discover();
- expect(newDevices.length).to.equal(3);
- expect(newDevices).to.have.deep.members([GladysOfflineDevice, GladysThDevice, GladysUnhandledDevice]);
+ expect(newDevices.length).to.equal(5);
+ expect(newDevices).to.have.deep.members([
+ { ...Gladys2ChDevice, room_id: undefined, updatable: false },
+ GladysOfflineDevice,
+ { ...GladysPowDevice, room_id: undefined, updatable: false },
+ GladysThDevice,
+ GladysUnhandledDevice,
+ ]);
+
+ expect(eWeLinkHandler.discoveredDevices).to.deep.eq(newDevices);
});
+
it('should found 0 devices', async () => {
// Force eWeLink API to give empty response
sinon.stub(eWeLinkHandler.ewelinkWebAPIClient.device, 'getAllThingsAllPages').resolves({ error: 0, data: {} });
const newDevices = await eWeLinkHandler.discover();
expect(newDevices).to.have.deep.members([]);
+ expect(eWeLinkHandler.discoveredDevices).to.deep.eq([]);
});
+
it('should return not configured error', async () => {
eWeLinkHandler.ewelinkWebAPIClient.at = EWELINK_INVALID_ACCESS_TOKEN;
try {
@@ -66,8 +77,10 @@ describe('EweLinkHandler discover', () => {
} catch (error) {
expect(error).instanceOf(ServiceNotConfiguredError);
expect(error.message).to.equal('eWeLink: Error, service is not configured');
+ expect(eWeLinkHandler.discoveredDevices).to.deep.eq([]);
}
});
+
it('should throw an error and emit a message when AccessToken is no more valid', async () => {
eWeLinkHandler.ewelinkWebAPIClient.at = EWELINK_DENIED_ACCESS_TOKEN;
try {
@@ -76,6 +89,7 @@ describe('EweLinkHandler discover', () => {
} catch (error) {
expect(error).instanceOf(Error);
expect(error.message).to.equal('eWeLink: Authentication error');
+ expect(eWeLinkHandler.discoveredDevices).to.deep.eq([]);
}
});
});
diff --git a/server/test/services/ewelink/lib/device/setValue.test.js b/server/test/services/ewelink/lib/device/setValue.test.js
index 84269eef3a..f0f7e24775 100644
--- a/server/test/services/ewelink/lib/device/setValue.test.js
+++ b/server/test/services/ewelink/lib/device/setValue.test.js
@@ -1,12 +1,9 @@
-const { expect } = require('chai');
const sinon = require('sinon');
-const { NotFoundError } = require('../../../../../utils/coreErrors');
const EwelinkHandler = require('../../../../../services/ewelink/lib');
-const { SERVICE_ID, EWELINK_DENIED_ACCESS_TOKEN } = require('../constants');
+const { SERVICE_ID } = require('../constants');
const Gladys2ChDevice = require('../payloads/Gladys-2ch.json');
-const GladysOfflineDevice = require('../payloads/Gladys-offline.json');
const GladysPowDevice = require('../payloads/Gladys-pow.json');
const EweLinkApiMock = require('../ewelink-api.mock.test');
@@ -14,12 +11,12 @@ const { assert } = sinon;
describe('eWeLinkHandler setValue', () => {
let eWeLinkHandler;
- const functionToTest = sinon.spy(EweLinkApiMock.Device.prototype, 'setThingStatus');
+ const functionToTest = sinon.spy(EweLinkApiMock.Connect.prototype, 'updateState');
beforeEach(() => {
const gladys = {};
eWeLinkHandler = new EwelinkHandler(gladys, EweLinkApiMock, SERVICE_ID);
- eWeLinkHandler.ewelinkWebAPIClient = new EweLinkApiMock.WebAPI();
+ eWeLinkHandler.ewelinkWebSocketClient = new EweLinkApiMock.Ws();
eWeLinkHandler.status = { configured: true, connected: true };
});
@@ -27,22 +24,24 @@ describe('eWeLinkHandler setValue', () => {
sinon.reset();
});
- it('should set the binary value of the channel 1 of the "2CH" device to 1', async () => {
+ it('should set the binary value of the single channel of the "pow" device to 1', async () => {
await eWeLinkHandler.setValue(
GladysPowDevice,
{ external_id: 'ewelink:10004533ae:power:1', category: 'switch', type: 'binary' },
1,
);
- assert.calledOnceWithExactly(functionToTest, 1, '10004533ae', { switch: 'on' });
+ assert.calledOnceWithExactly(functionToTest, '10004533ae', { switch: 'on' });
});
+
it('should set the binary value of the channel 2 of the "2CH" device to 0', async () => {
await eWeLinkHandler.setValue(
Gladys2ChDevice,
{ external_id: 'ewelink:10004531ae:power:2', category: 'switch', type: 'binary' },
0,
);
- assert.calledOnceWithExactly(functionToTest, 1, '10004531ae', { switches: [{ outlet: 2, switch: 'off' }] });
+ assert.calledOnceWithExactly(functionToTest, '10004531ae', { switches: [{ outlet: 1, switch: 'off' }] });
});
+
it('should do nothing because of the feature type is not handled yet', async () => {
await eWeLinkHandler.setValue(
GladysPowDevice,
@@ -51,33 +50,4 @@ describe('eWeLinkHandler setValue', () => {
);
assert.notCalled(functionToTest);
});
- it('should throw an error when device is offline', async () => {
- try {
- await eWeLinkHandler.setValue(
- GladysOfflineDevice,
- { external_id: 'ewelink:10004532ae:power:1', category: 'switch', type: 'binary' },
- 1,
- );
- assert.fail();
- } catch (error) {
- assert.calledOnceWithExactly(functionToTest, 1, '10004532ae', { switch: 'on' });
- expect(error).instanceOf(NotFoundError);
- expect(error.message).to.equal('eWeLink: Error, device is not currently online');
- }
- });
- it('should throw an error when AccessToken is no more valid', async () => {
- eWeLinkHandler.ewelinkWebAPIClient.at = EWELINK_DENIED_ACCESS_TOKEN;
- try {
- await eWeLinkHandler.setValue(
- Gladys2ChDevice,
- { external_id: 'ewelink:10004531ae:power:2', category: 'switch', type: 'binary' },
- 1,
- );
- assert.fail();
- } catch (error) {
- assert.calledOnceWithExactly(functionToTest, 1, '10004531ae', { switches: [{ outlet: 2, switch: 'on' }] });
- expect(error).instanceOf(Error);
- expect(error.message).to.equal('eWeLink: Authentication error');
- }
- });
});
diff --git a/server/test/services/ewelink/lib/ewelink-api.mock.test.js b/server/test/services/ewelink/lib/ewelink-api.mock.test.js
index 6e1d84d401..ba8b8227bb 100644
--- a/server/test/services/ewelink/lib/ewelink-api.mock.test.js
+++ b/server/test/services/ewelink/lib/ewelink-api.mock.test.js
@@ -12,6 +12,7 @@ const {
EWELINK_VALID_ACCESS_TOKEN,
EWELINK_INVALID_ACCESS_TOKEN,
} = require('./constants');
+const logger = require('../../../../utils/logger');
const fakeDevices = [EweLink2ChDevice, EweLinkOfflineDevice, EweLinkPowDevice, EweLinkThDevice, EweLinkUnhandledDevice];
@@ -67,11 +68,6 @@ class Device {
return response;
}
-
- async setThingStatus(type, id, params) {
- const deviceResponse = await this.getThings({ thingList: [{ id }] });
- return { ...deviceResponse, data: {} };
- }
}
class WebAPI {
@@ -93,6 +89,18 @@ class Connect {
this.create = () => {};
}
+
+ updateState(deviceId, params, action, userAgent, userApiKey) {
+ logger.debug(
+ 'update state with user token %s and deviceId=%s - param=%j - action=%s - userAgent=%s - apiKey=%s',
+ this.root.at,
+ deviceId,
+ params,
+ action,
+ userAgent,
+ userApiKey,
+ );
+ }
}
class Ws {
diff --git a/server/test/services/ewelink/lib/features/binary.test.js b/server/test/services/ewelink/lib/features/binary.test.js
index 630577df5e..264669fb23 100644
--- a/server/test/services/ewelink/lib/features/binary.test.js
+++ b/server/test/services/ewelink/lib/features/binary.test.js
@@ -16,8 +16,8 @@ describe('eWeLink binary feature -> readState', () => {
it('should return switches states', () => {
const states = readStates('ewelink-id', {
switches: [
- { switch: 'on', outlet: 1 },
- { switch: 'off', outlet: 2 },
+ { switch: 'on', outlet: 0 },
+ { switch: 'off', outlet: 1 },
],
});
expect(states).deep.eq([
diff --git a/server/test/services/ewelink/lib/handlers/ewelink.handleRequest.test.js b/server/test/services/ewelink/lib/handlers/ewelink.handleRequest.test.js
index c4f167f751..4dbd195885 100644
--- a/server/test/services/ewelink/lib/handlers/ewelink.handleRequest.test.js
+++ b/server/test/services/ewelink/lib/handlers/ewelink.handleRequest.test.js
@@ -5,7 +5,7 @@ const { stub, assert } = sinon;
const EwelinkHandler = require('../../../../../services/ewelink/lib');
const { SERVICE_ID } = require('../constants');
-const { ServiceNotConfiguredError, BadParameters } = require('../../../../../utils/coreErrors');
+const { ServiceNotConfiguredError, BadParameters, NotFoundError } = require('../../../../../utils/coreErrors');
const { EVENTS, WEBSOCKET_MESSAGE_TYPES } = require('../../../../../utils/constants');
const tokens = { accessToken: 'ACCESS_TOKEN', refreshToken: 'REFRESH_TOKEN' };
@@ -168,4 +168,40 @@ describe('eWeLinkHandler handleRequest', () => {
assert.notCalled(gladys.variable.destroy);
assert.notCalled(gladys.event.emit);
});
+
+ it('should throws NotFoundError on 405 error', async () => {
+ const request = stub().resolves({ data: 'ERROR', error: 405, msg: 'API ERROR' });
+
+ try {
+ await eWeLinkHandler.handleRequest(request);
+ assert.fail();
+ } catch (e) {
+ expect(e).instanceOf(NotFoundError);
+ expect(e.message).to.equal('API ERROR');
+ }
+
+ assert.calledOnceWithExactly(request);
+ assert.notCalled(eWeLinkHandler.ewelinkWebAPIClient.user.refreshToken);
+ assert.notCalled(gladys.variable.setValue);
+ assert.notCalled(gladys.variable.destroy);
+ assert.notCalled(gladys.event.emit);
+ });
+
+ it('should throws NotFoundError on 4002 error', async () => {
+ const request = stub().resolves({ data: 'ERROR', error: 4002, msg: 'API ERROR' });
+
+ try {
+ await eWeLinkHandler.handleRequest(request);
+ assert.fail();
+ } catch (e) {
+ expect(e).instanceOf(NotFoundError);
+ expect(e.message).to.equal('API ERROR');
+ }
+
+ assert.calledOnceWithExactly(request);
+ assert.notCalled(eWeLinkHandler.ewelinkWebAPIClient.user.refreshToken);
+ assert.notCalled(gladys.variable.setValue);
+ assert.notCalled(gladys.variable.destroy);
+ assert.notCalled(gladys.event.emit);
+ });
});
diff --git a/server/test/services/ewelink/lib/payloads/Gladys-2ch.json b/server/test/services/ewelink/lib/payloads/Gladys-2ch.json
index 3267189b09..78fd936ec4 100644
--- a/server/test/services/ewelink/lib/payloads/Gladys-2ch.json
+++ b/server/test/services/ewelink/lib/payloads/Gladys-2ch.json
@@ -37,6 +37,10 @@
{
"name": "ONLINE",
"value": "1"
+ },
+ {
+ "name": "API_KEY",
+ "value": "validApikey"
}
]
}
diff --git a/server/test/services/ewelink/lib/payloads/Gladys-Basic.json b/server/test/services/ewelink/lib/payloads/Gladys-Basic.json
index 896a6f51cc..d63e643a0b 100644
--- a/server/test/services/ewelink/lib/payloads/Gladys-Basic.json
+++ b/server/test/services/ewelink/lib/payloads/Gladys-Basic.json
@@ -37,6 +37,10 @@
{
"name": "ONLINE",
"value": "0"
+ },
+ {
+ "name": "API_KEY",
+ "value": "validApikey"
}
]
}
diff --git a/server/test/services/ewelink/lib/payloads/Gladys-offline.json b/server/test/services/ewelink/lib/payloads/Gladys-offline.json
index 1ecd98bb95..120baf9322 100644
--- a/server/test/services/ewelink/lib/payloads/Gladys-offline.json
+++ b/server/test/services/ewelink/lib/payloads/Gladys-offline.json
@@ -10,6 +10,10 @@
{
"name": "ONLINE",
"value": "0"
+ },
+ {
+ "name": "API_KEY",
+ "value": "validApikey"
}
]
}
diff --git a/server/test/services/ewelink/lib/payloads/Gladys-pow.json b/server/test/services/ewelink/lib/payloads/Gladys-pow.json
index 7664064c48..464ef899be 100644
--- a/server/test/services/ewelink/lib/payloads/Gladys-pow.json
+++ b/server/test/services/ewelink/lib/payloads/Gladys-pow.json
@@ -26,6 +26,10 @@
{
"name": "ONLINE",
"value": "1"
+ },
+ {
+ "name": "API_KEY",
+ "value": "validApikey"
}
]
}
diff --git a/server/test/services/ewelink/lib/payloads/Gladys-th.json b/server/test/services/ewelink/lib/payloads/Gladys-th.json
index 03f8e821e0..3c31b20c3b 100644
--- a/server/test/services/ewelink/lib/payloads/Gladys-th.json
+++ b/server/test/services/ewelink/lib/payloads/Gladys-th.json
@@ -50,6 +50,10 @@
{
"name": "ONLINE",
"value": "1"
+ },
+ {
+ "name": "API_KEY",
+ "value": "validApikey"
}
]
}
diff --git a/server/test/services/ewelink/lib/payloads/Gladys-unhandled.json b/server/test/services/ewelink/lib/payloads/Gladys-unhandled.json
index a06f24770e..1f4462cda6 100644
--- a/server/test/services/ewelink/lib/payloads/Gladys-unhandled.json
+++ b/server/test/services/ewelink/lib/payloads/Gladys-unhandled.json
@@ -10,6 +10,10 @@
{
"name": "ONLINE",
"value": "1"
+ },
+ {
+ "name": "API_KEY",
+ "value": "validApikey"
}
]
}
diff --git a/server/test/services/ewelink/lib/user/ewelink.deleteTokens.test.js b/server/test/services/ewelink/lib/user/ewelink.deleteTokens.test.js
index 1cf0c5ce10..8baf7223ff 100644
--- a/server/test/services/ewelink/lib/user/ewelink.deleteTokens.test.js
+++ b/server/test/services/ewelink/lib/user/ewelink.deleteTokens.test.js
@@ -29,6 +29,7 @@ describe('eWeLinkHandler deleteTokens', () => {
delete: fake.resolves({}),
},
};
+ eWeLinkHandler.ewelinkWebSocketClient = {};
eWeLinkHandler.status = { configured: true, connected: true };
});
diff --git a/server/test/services/ewelink/lib/user/ewelink.exchangeToken.test.js b/server/test/services/ewelink/lib/user/ewelink.exchangeToken.test.js
index 214ed0f785..49c1b64964 100644
--- a/server/test/services/ewelink/lib/user/ewelink.exchangeToken.test.js
+++ b/server/test/services/ewelink/lib/user/ewelink.exchangeToken.test.js
@@ -1,9 +1,14 @@
const { expect } = require('chai');
const sinon = require('sinon');
+const proxyquire = require('proxyquire').noCallThru();
const { fake, assert, match } = sinon;
-const EwelinkHandler = require('../../../../../services/ewelink/lib');
+const retrieveUserApiKey = fake.resolves(null);
+
+const EwelinkHandler = proxyquire('../../../../../services/ewelink/lib', {
+ './user/ewelink.retrieveUserApiKey': { retrieveUserApiKey },
+});
const { SERVICE_ID, EWELINK_APP_ID, EWELINK_APP_REGION } = require('../constants');
const { EVENTS, WEBSOCKET_MESSAGE_TYPES } = require('../../../../../utils/constants');
const { BadParameters } = require('../../../../../utils/coreErrors');
@@ -30,7 +35,7 @@ describe('eWeLinkHandler exchangeToken', () => {
getToken: fake.resolves({ data: tokens }),
},
};
- eWeLinkHandler.ewelinkWebSocketClientFactory = {
+ eWeLinkHandler.ewelinkWebSocketClient = {
Connect: {
create: fake.returns({}),
},
@@ -65,12 +70,13 @@ describe('eWeLinkHandler exchangeToken', () => {
}
assert.notCalled(eWeLinkHandler.ewelinkWebAPIClient.oauth.getToken);
- assert.notCalled(eWeLinkHandler.ewelinkWebSocketClientFactory.Connect.create);
+ assert.notCalled(retrieveUserApiKey);
+ assert.notCalled(eWeLinkHandler.ewelinkWebSocketClient.Connect.create);
assert.notCalled(gladys.variable.setValue);
assert.notCalled(gladys.event.emit);
});
- it('should retreive, store user token and emit event', async () => {
+ it('should retreive, store user token and API key and emit event', async () => {
const redirectUrl = 'http://localhost:1440';
const code = 'auth_code';
const region = 'app_region';
@@ -83,9 +89,10 @@ describe('eWeLinkHandler exchangeToken', () => {
redirectUrl,
region,
});
- assert.calledOnce(eWeLinkHandler.ewelinkWebSocketClientFactory.Connect.create);
+ assert.calledOnceWithExactly(retrieveUserApiKey);
+ assert.calledOnce(eWeLinkHandler.ewelinkWebSocketClient.Connect.create);
assert.calledWithMatch(
- eWeLinkHandler.ewelinkWebSocketClientFactory.Connect.create,
+ eWeLinkHandler.ewelinkWebSocketClient.Connect.create,
match({ appId: EWELINK_APP_ID, region: EWELINK_APP_REGION, at: tokens.accessToken }),
match.func,
match.func,
diff --git a/server/test/services/ewelink/lib/user/ewelink.retrieveUserApiKey.test.js b/server/test/services/ewelink/lib/user/ewelink.retrieveUserApiKey.test.js
new file mode 100644
index 0000000000..26deea0601
--- /dev/null
+++ b/server/test/services/ewelink/lib/user/ewelink.retrieveUserApiKey.test.js
@@ -0,0 +1,69 @@
+const sinon = require('sinon');
+
+const { fake, assert } = sinon;
+
+const { expect } = require('chai');
+const EwelinkHandler = require('../../../../../services/ewelink/lib');
+const { SERVICE_ID } = require('../constants');
+const { ServiceNotConfiguredError } = require('../../../../../utils/coreErrors');
+
+describe('eWeLinkHandler retrieveUserApiKey', () => {
+ let eWeLinkHandler;
+ let gladys;
+
+ beforeEach(() => {
+ gladys = {
+ variable: {
+ setValue: fake.resolves(null),
+ },
+ };
+
+ eWeLinkHandler = new EwelinkHandler(gladys, null, SERVICE_ID);
+ eWeLinkHandler.ewelinkWebAPIClient = {
+ home: {
+ getFamily: fake.resolves({
+ data: { currentFamilyId: 'current-family', familyList: [{ id: 'current-family', apikey: 'USER-API-KEY' }] },
+ }),
+ },
+ };
+ });
+
+ afterEach(() => {
+ sinon.reset();
+ });
+
+ it('should throw an error as API key is not found', async () => {
+ eWeLinkHandler.ewelinkWebAPIClient = {
+ home: {
+ getFamily: fake.resolves({
+ data: {
+ currentFamilyId: 'current-family',
+ familyList: [{ id: 'not-current-family', apikey: 'USER-API-KEY' }],
+ },
+ }),
+ },
+ };
+
+ try {
+ await eWeLinkHandler.retrieveUserApiKey();
+ assert.fail();
+ } catch (e) {
+ expect(e).instanceOf(ServiceNotConfiguredError);
+ expect(e.message).to.eq('eWeLink: no user API key retrieved');
+ }
+
+ assert.calledOnceWithExactly(eWeLinkHandler.ewelinkWebAPIClient.home.getFamily);
+ assert.notCalled(gladys.variable.setValue);
+ });
+
+ it('should store user API key in database', async () => {
+ // Check value is not already set
+ expect(eWeLinkHandler.userApiKey).to.eq(null);
+
+ await eWeLinkHandler.retrieveUserApiKey();
+
+ assert.calledOnceWithExactly(eWeLinkHandler.ewelinkWebAPIClient.home.getFamily);
+ assert.calledOnceWithExactly(gladys.variable.setValue, 'USER_API_KEY', 'USER-API-KEY', SERVICE_ID);
+ expect(eWeLinkHandler.userApiKey).to.eq('USER-API-KEY');
+ });
+});
diff --git a/server/test/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.test.js b/server/test/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.test.js
index df878a5585..30e6264f6f 100644
--- a/server/test/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.test.js
+++ b/server/test/services/ewelink/lib/websocket/ewelink.closeWebSocketClient.test.js
@@ -11,6 +11,9 @@ describe('eWeLinkHandler closeWebSocketClient', () => {
beforeEach(() => {
eWeLinkHandler = new EwelinkHandler({}, null, SERVICE_ID);
+ eWeLinkHandler.ewelinkWebSocketClient = {
+ Connect: {},
+ };
});
afterEach(() => {
@@ -19,20 +22,18 @@ describe('eWeLinkHandler closeWebSocketClient', () => {
it('should do nothing', async () => {
// Check client is not set first
- expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
+ expect(eWeLinkHandler.ewelinkWebSocketClient.ws).eq(undefined);
eWeLinkHandler.closeWebSocketClient();
- expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
+ expect(eWeLinkHandler.ewelinkWebSocketClient.ws).eq(undefined);
});
it('should close websocket client', async () => {
- const wsClient = {
+ eWeLinkHandler.ewelinkWebSocketClient.Connect.ws = {
close: fake.resolves(null),
};
- eWeLinkHandler.ewelinkWebSocketClient = wsClient;
eWeLinkHandler.closeWebSocketClient();
- assert.calledOnceWithExactly(wsClient.close);
- expect(eWeLinkHandler.ewelinkWebSocketClient).eq(null);
+ assert.calledOnceWithExactly(eWeLinkHandler.ewelinkWebSocketClient.Connect.ws.close);
});
});
diff --git a/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketClose.test.js b/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketClose.test.js
index 6af3c50f60..c86ae29eb7 100644
--- a/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketClose.test.js
+++ b/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketClose.test.js
@@ -4,16 +4,16 @@ const proxyquire = require('proxyquire').noCallThru();
const { fake, assert } = sinon;
const logger = {
- info: fake.returns(null),
+ warn: fake.returns(null),
};
-const closeWebSocketClient = fake.returns(null);
+const createWebSocketClient = fake.returns(null);
const onWebSocketClose = proxyquire('../../../../../services/ewelink/lib/websocket/ewelink.onWebSocketClose', {
'../../../../utils/logger': logger,
});
const EwelinkHandler = proxyquire('../../../../../services/ewelink/lib', {
'./websocket/ewelink.onWebSocketClose': onWebSocketClose,
- './websocket/ewelink.closeWebSocketClient': { closeWebSocketClient },
+ './websocket/ewelink.createWebSocketClient': { createWebSocketClient },
});
const { SERVICE_ID } = require('../constants');
@@ -28,9 +28,17 @@ describe('eWeLinkHandler onWebSocketClose', () => {
sinon.reset();
});
- it('should log info and close websocket', () => {
- eWeLinkHandler.onWebSocketClose();
- assert.calledOnceWithExactly(logger.info, 'eWeLink: WebSocket is closed');
- assert.calledOnceWithExactly(closeWebSocketClient);
+ it('should only log warn', async () => {
+ await eWeLinkHandler.onWebSocketClose();
+ assert.calledOnceWithExactly(logger.warn, 'eWeLink: WebSocket is closed');
+ assert.notCalled(createWebSocketClient);
+ });
+
+ it('should log warn and close websocket', async () => {
+ eWeLinkHandler.ewelinkWebSocketClient = {};
+
+ await eWeLinkHandler.onWebSocketClose();
+ assert.calledOnceWithExactly(logger.warn, 'eWeLink: WebSocket is closed');
+ assert.calledOnceWithExactly(createWebSocketClient);
});
});
diff --git a/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.test.js b/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.test.js
index 1dd8fd6b50..bc096155a9 100644
--- a/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.test.js
+++ b/server/test/services/ewelink/lib/websocket/ewelink.onWebSocketMessage.test.js
@@ -35,8 +35,11 @@ describe('eWeLinkHandler onWebSocketMessage', () => {
it('should do nothing, device is not found', async () => {
gladys.stateManager.get.returns(null);
- const message = { deviceid: 'unknown-device' };
- await eWeLinkHandler.onWebSocketMessage(null, message);
+ const eventMessage = {
+ data: JSON.stringify({ deviceid: 'unknown-device' }),
+ };
+
+ await eWeLinkHandler.onWebSocketMessage(null, eventMessage);
assert.calledOnceWithExactly(gladys.stateManager.get, 'deviceByExternalId', 'ewelink:unknown-device');
assert.notCalled(gladys.event.emit);
@@ -48,8 +51,11 @@ describe('eWeLinkHandler onWebSocketMessage', () => {
it('should do nothing, feature not exists', async () => {
gladys.stateManager.get.onSecondCall().returns(null);
- const message = { deviceid: 'known-device', params: { switch: 'on' } };
- await eWeLinkHandler.onWebSocketMessage(null, message);
+ const eventMessage = {
+ data: JSON.stringify({ deviceid: 'known-device', params: { switch: 'on' } }),
+ };
+
+ await eWeLinkHandler.onWebSocketMessage(null, eventMessage);
assert.callCount(gladys.stateManager.get, 2);
assert.calledWithExactly(gladys.stateManager.get, 'deviceByExternalId', 'ewelink:known-device');
@@ -62,8 +68,14 @@ describe('eWeLinkHandler onWebSocketMessage', () => {
});
it('should emit state event', async () => {
- const message = { deviceid: 'known-device', params: { switch: 'on', currentTemperature: 17, currentHumidity: 23 } };
- await eWeLinkHandler.onWebSocketMessage(null, message);
+ const eventMessage = {
+ data: JSON.stringify({
+ deviceid: 'known-device',
+ params: { switch: 'on', currentTemperature: 17, currentHumidity: 23 },
+ }),
+ };
+
+ await eWeLinkHandler.onWebSocketMessage(null, eventMessage);
assert.callCount(gladys.stateManager.get, 4);
assert.calledWithExactly(gladys.stateManager.get, 'deviceByExternalId', 'ewelink:known-device');
@@ -91,8 +103,11 @@ describe('eWeLinkHandler onWebSocketMessage', () => {
});
it('should update device params', async () => {
- const message = { deviceid: 'known-device', params: { online: true } };
- await eWeLinkHandler.onWebSocketMessage(null, message);
+ const eventMessage = {
+ data: JSON.stringify({ deviceid: 'known-device', params: { online: true } }),
+ };
+
+ await eWeLinkHandler.onWebSocketMessage(null, eventMessage);
assert.calledOnceWithExactly(gladys.stateManager.get, 'deviceByExternalId', 'ewelink:known-device');
@@ -101,4 +116,28 @@ describe('eWeLinkHandler onWebSocketMessage', () => {
assert.calledOnceWithExactly(gladys.device.setParam, device, 'ONLINE', '1');
expect(device).deep.eq({ params: [{ name: 'ONLINE', value: '1' }] });
});
+
+ it('should ignore non JSON data', async () => {
+ const eventMessage = {
+ data: 'pong',
+ };
+
+ await eWeLinkHandler.onWebSocketMessage(null, eventMessage);
+
+ assert.notCalled(gladys.stateManager.get);
+ assert.notCalled(gladys.event.emit);
+ assert.notCalled(gladys.device.setParam);
+ });
+
+ it('should ignore not device oriented data', async () => {
+ const eventMessage = {
+ data: JSON.stringify({}),
+ };
+
+ await eWeLinkHandler.onWebSocketMessage(null, eventMessage);
+
+ assert.notCalled(gladys.stateManager.get);
+ assert.notCalled(gladys.event.emit);
+ assert.notCalled(gladys.device.setParam);
+ });
});