Release v1.8.0 (#23)

* new method to check for device firmware updates

* moved mixin

* generate firmware update payload

* new method to check for devices firmware updates

* removed unused function

* moved firmware tests to own file

* added firmware test cases

* return device id on response

* updated credentials list

* version bump
This commit is contained in:
Martin M
2019-11-02 22:42:55 -03:00
committed by GitHub
parent f883be49a6
commit e6f60724f1
15 changed files with 262 additions and 53 deletions

View File

@@ -0,0 +1,15 @@
const { _get } = require('../../lib/helpers');
const firmwareUpdate = devicesList =>
devicesList.map(device => {
const model = _get(device, 'extra.extra.model', false);
const fwVersion = _get(device, 'params.fwVersion', false);
if (!model || !fwVersion) {
return { error: 500, msg: "Can't get model or firmware version" };
}
return { model, version: fwVersion, deviceid: device.deviceid };
});
module.exports = firmwareUpdate;

View File

@@ -1,8 +1,10 @@
const firmwareUpdate = require('./firmwareUpdate');
const loginPayload = require('./loginPayload');
const wssLoginPayload = require('./wssLoginPayload');
const wssUpdatePayload = require('./wssUpdatePayload');
module.exports = {
firmwareUpdate,
loginPayload,
wssLoginPayload,
wssUpdatePayload,

45
main.js
View File

@@ -28,6 +28,14 @@ class eWeLink {
return `https://${this.region}-api.coolkit.cc:8080/api`;
}
/**
* Generate eWeLink OTA API URL
* @returns {string}
*/
getOtaUrl() {
return `https://${this.region}-ota.coolkit.cc:8080/otaother`;
}
/**
* Generate eWeLink WebSocket URL
*
@@ -41,22 +49,29 @@ class eWeLink {
* Generate http requests helpers
*
* @param method
* @param url
* @param uri
* @param body
* @param qs
*
* @returns {Promise<{msg: string, error: *}>}
*/
async makeRequest({ method = 'GET', uri, body = {}, qs = {} }) {
async makeRequest({ method = 'GET', url, uri, body = {}, qs = {} }) {
const { at } = this;
if (!at) {
await this.login();
}
let apiUrl = this.getApiUrl();
if (url) {
apiUrl = url;
}
const response = await rp({
method,
uri: `${this.getApiUrl()}${uri}`,
uri: `${apiUrl}${uri}`,
headers: { Authorization: `Bearer ${this.at}` },
body,
qs,
@@ -111,16 +126,6 @@ class eWeLink {
return response;
}
/**
* Check if authentication credentials doesn't exists then perform a login
*
* @returns {Promise<void>}
*/
async logIfNeeded() {
if (!this.at) {
await this.login();
}
}
}
/* LOAD MIXINS: power state */
@@ -139,7 +144,11 @@ const getTHMixin = require('./mixins/temphumd/getTHMixin');
const getDevicesMixin = require('./mixins/devices/getDevicesMixin');
const getDeviceMixin = require('./mixins/devices/getDeviceMixin');
const getDeviceChannelCountMixin = require('./mixins/devices/getDeviceChannelCountMixin');
const getFirmwareVersionMixin = require('./mixins/devices/getFirmwareVersionMixin');
/* LOAD MIXINS: firmware */
const getFirmwareVersionMixin = require('./mixins/firmware/getFirmwareVersionMixin');
const checkDeviceUpdateMixin = require('./mixins/firmware/checkDeviceUpdateMixin');
const checkDevicesUpdatesMixin = require('./mixins/firmware/checkDevicesUpdatesMixin');
/* LOAD MIXINS: websocket */
const openWebSocketMixin = require('./mixins/websocket/openWebSocketMixin');
@@ -163,8 +172,14 @@ Object.assign(
eWeLink.prototype,
getDevicesMixin,
getDeviceMixin,
getDeviceChannelCountMixin,
getFirmwareVersionMixin
getDeviceChannelCountMixin
);
Object.assign(
eWeLink.prototype,
getFirmwareVersionMixin,
checkDeviceUpdateMixin,
checkDevicesUpdatesMixin
);
Object.assign(eWeLink.prototype, openWebSocketMixin);

View File

@@ -0,0 +1,48 @@
const { _get } = require('../../lib/helpers');
const payloads = require('../../lib/payloads');
const checkDeviceUpdateMixin = {
/**
* Check device firmware update
*
* @param deviceId
*
* @returns {Promise<{msg: string, version: *}|{msg: string, error: number}|{msg: string, error: *}|Device|{msg: string}>}
*/
async checkDeviceUpdate(deviceId) {
const device = await this.getDevice(deviceId);
const error = _get(device, 'error', false);
if (error) {
return device;
}
const deviceInfoList = payloads.firmwareUpdate([device]);
if (error) {
return deviceInfoList;
}
const update = await this.makeRequest({
method: 'POST',
url: this.getOtaUrl(),
uri: '/app',
body: { deviceInfoList },
});
const isUpdate = _get(update, 'upgradeInfoList.0.version', false);
if (!isUpdate) {
return { status: 'ok', msg: 'No update available' };
}
return {
status: 'ok',
msg: 'Update available',
version: isUpdate,
};
},
};
module.exports = checkDeviceUpdateMixin;

View File

@@ -0,0 +1,54 @@
const { _get } = require('../../lib/helpers');
const payloads = require('../../lib/payloads');
const checkDevicesUpdatesMixin = {
async checkDevicesUpdates() {
const devices = await this.getDevices();
const error = _get(devices, 'error', false);
if (error) {
return devices;
}
const deviceInfoList = payloads.firmwareUpdate(devices);
if (error) {
return deviceInfoList;
}
const updates = await this.makeRequest({
method: 'POST',
url: this.getOtaUrl(),
uri: '/app',
body: { deviceInfoList },
});
const upgradeInfoList = _get(updates, 'upgradeInfoList', false);
if (!upgradeInfoList) {
return { error: "Can't find firmware update information" };
}
return upgradeInfoList.map(device => {
const upd = _get(device, 'version', false);
if (!upd) {
return {
status: 'ok',
deviceId: device.deviceid,
msg: 'No update available',
};
}
return {
status: 'ok',
deviceId: device.deviceid,
msg: 'Update available',
version: upd,
};
});
},
};
module.exports = checkDevicesUpdatesMixin;

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "ewelink-api",
"version": "1.7.0",
"version": "1.8.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "ewelink-api",
"version": "1.7.0",
"version": "1.8.0",
"description": "eWeLink API for Node.js",
"author": "Martín M.",
"license": "MIT",

View File

@@ -6,5 +6,7 @@
"deviceIdWithoutPower": "<your device id>",
"deviceIdWithTempAndHum": "<your device id>",
"deviceIdWithoutTempAndHum": "<your device id>",
"fourChannelsDevice": "<your device id>"
"fourChannelsDevice": "<your device id>",
"outdatedFirmwareDevice": "<your device id>",
"updatedFirmwareDevice": "<your device id>"
}

View File

@@ -44,10 +44,17 @@ const currentMonthPowerUsageExpectations = {
daily: expect.any(Array),
};
const firmwareExpectations = {
status: expect.any(String),
deviceId: expect.any(String),
msg: expect.any(String),
};
module.exports = {
loginExpectations,
allDevicesExpectations,
specificDeviceExpectations,
rawPowerUsageExpectations,
currentMonthPowerUsageExpectations,
firmwareExpectations,
};

101
test/firmware.spec.js Normal file
View File

@@ -0,0 +1,101 @@
const ewelink = require('../main');
const {
email,
password,
singleChannelDeviceId,
outdatedFirmwareDevice,
updatedFirmwareDevice,
} = require('./_setup/credentials.json');
const { firmwareExpectations } = require('./_setup/expectations');
describe('firmware: get version methods', () => {
let connection;
beforeAll(() => {
connection = new ewelink({ email, password });
});
test('get firmware version', async () => {
const device = await connection.getDevice(singleChannelDeviceId);
const currentVersion = device.params.fwVersion;
const firmware = await connection.getFirmwareVersion(singleChannelDeviceId);
expect(typeof firmware).toBe('object');
expect(firmware.status).toBe('ok');
expect(firmware.fwVersion).toBe(currentVersion);
});
test('get device firmware version should be right message', async () => {
const login = await connection.login();
const accessToken = login.at;
const conn = new ewelink({ at: accessToken });
const device = await conn.getDevice(singleChannelDeviceId);
const currentVersion = device.params.fwVersion;
const firmware = await conn.getFirmwareVersion(singleChannelDeviceId);
expect(typeof firmware).toBe('object');
expect(firmware.status).toBe('ok');
expect(firmware.fwVersion).toBe(currentVersion);
});
test('get invalid device firmware version should fail', async () => {
const conn = new ewelink({ email, password });
const firmwareVersion = await conn.getFirmwareVersion('invalid deviceid');
expect(typeof firmwareVersion).toBe('object');
expect(firmwareVersion.msg).toBe('Device does not exist');
expect(firmwareVersion.error).toBe(500);
});
test('get device firmware version using invalid credentials should fail', async () => {
const conn = new ewelink({ email: 'invalid', password: 'credentials' });
const firmware = await conn.getFirmwareVersion(singleChannelDeviceId);
expect(typeof firmware).toBe('object');
expect(firmware.msg).toBe('Authentication error');
expect(firmware.error).toBe(401);
});
});
describe('firmware: check updates methods', () => {
let connection;
beforeAll(() => {
connection = new ewelink({ email, password });
});
test('outdated device firmware should return available version', async () => {
const status = await connection.checkDeviceUpdate(outdatedFirmwareDevice);
expect(typeof status).toBe('object');
expect(typeof status).toBe('object');
expect(status.status).toBe('ok');
expect(status.msg).toBe('Update available');
expect(typeof status.version).toBe('string');
});
test('updated device firmware should return right message', async () => {
const status = await connection.checkDeviceUpdate(updatedFirmwareDevice);
expect(typeof status).toBe('object');
expect(typeof status).toBe('object');
expect(status.status).toBe('ok');
expect(status.msg).toBe('No update available');
});
test('invalid device update check should return error', async () => {
const status = await connection.checkDeviceUpdate('invalid deviceid');
expect(typeof status).toBe('object');
expect(status.error).toBe(500);
});
test('get devices update check should be valid response', async () => {
const status = await connection.checkDevicesUpdates();
expect(typeof status).toBe('object');
expect(status[0]).toMatchObject(firmwareExpectations);
});
test('get devices update check with invalid credentials should fail', async () => {
const conn = new ewelink({ email: 'invalid', password: 'credentials' });
const status = await conn.checkDevicesUpdates();
expect(typeof status).toBe('object');
expect(status.msg).toBe('Authentication error');
expect(status.error).toBe(401);
});
});

View File

@@ -152,13 +152,4 @@ describe('env: node script', () => {
expect(result.status).toBe('ok');
expect(result.switchesAmount).toBe(4);
});
test('get firmware version', async () => {
const device = await conn.getDevice(singleChannelDeviceId);
const currentVersion = device.params.fwVersion;
const firmware = await conn.getFirmwareVersion(singleChannelDeviceId);
expect(typeof firmware).toBe('object');
expect(firmware.status).toBe('ok');
expect(firmware.fwVersion).toBe(currentVersion);
});
});

View File

@@ -108,14 +108,4 @@ describe('env: serverless', () => {
expect(result.status).toBe('ok');
expect(result.switchesAmount).toBe(4);
});
test('get device firmware version', async () => {
const conn = new ewelink({ at: accessToken });
const device = await conn.getDevice(singleChannelDeviceId);
const currentVersion = device.params.fwVersion;
const firmware = await conn.getFirmwareVersion(singleChannelDeviceId);
expect(typeof firmware).toBe('object');
expect(firmware.status).toBe('ok');
expect(firmware.fwVersion).toBe(currentVersion);
});
});

View File

@@ -88,12 +88,4 @@ describe('invalid credentials', () => {
expect(switchesAmount.msg).toBe('Authentication error');
expect(switchesAmount.error).toBe(401);
});
test('get device firmware version should fail', async () => {
const conn = new ewelink({ email: 'invalid', password: 'credentials' });
const firmware = await conn.getFirmwareVersion(singleChannelDeviceId);
expect(typeof firmware).toBe('object');
expect(firmware.msg).toBe('Authentication error');
expect(firmware.error).toBe(401);
});
});

View File

@@ -96,14 +96,6 @@ describe('valid credentials, invalid device', () => {
expect(switchesAmount.msg).toBe('Device does not exist');
expect(switchesAmount.error).toBe(500);
});
test('get device firmware version should fail', async () => {
const conn = new ewelink({ email, password });
const firmwareVersion = await conn.getFirmwareVersion('invalid deviceid');
expect(typeof firmwareVersion).toBe('object');
expect(firmwareVersion.msg).toBe('Device does not exist');
expect(firmwareVersion.error).toBe(500);
});
});
describe('valid credentials, wrong region', () => {