homebridge-miot
Version:
Homebridge plugin for devices supporting the miot protocol
133 lines (119 loc) • 3.99 kB
JavaScript
const {
HomebridgePluginUiServer
} = require('@homebridge/plugin-ui-utils');
const MiCloud = require('../lib/protocol/MiCloud');
const Errors = require("../lib/utils/Errors.js");
const MiotSpecClassGenerator = require('../lib/tools/MiotSpecClassGenerator');
const MiotSpecFetcher = require('../lib/protocol/MiotSpecFetcher');
const Logger = require("../lib/utils/Logger");
class UiServer extends HomebridgePluginUiServer {
constructor() {
// super must be called first
super();
this.onRequest('/get-all-devices', this.getAllDevices.bind(this));
this.onRequest('/generate-device-class', this.generateDeviceClass.bind(this));
this.onRequest('/get-device-metadata', this.getDeviceMetadata.bind(this));
// this.ready() must be called to let the UI know you are ready to accept api calls
this.ready();
}
async getAllDevices(params) {
const miCloud = new MiCloud(new Logger());
miCloud.setRequestTimeout(10000); // timeout 10 seconds
var devices = [];
// try to login
try {
await miCloud.login(params.username, params.password);
} catch (err) {
if (err instanceof Errors.TwoFactorRequired) {
return {
success: false,
error: 'Two factor authentication required, please visit the specified url and retry login.',
url: err.notificationUrl
}
}
return {
success: false,
error: err.message + `! The specified MiCloud login credentials might be incorrect or the account does not exist...`
};
}
let warningMsg = null;
const isShowAll = !!params.isShowAll;
// list all device from all available countries
for (const country of miCloud.availableCountries) {
try {
miCloud.setCountry(country);
// prevent duplicate devices
const allList = (await miCloud.getDevices()).filter(device => !devices.find(d => d.did === device.did));
let validList = allList;
if (!isShowAll) {
// filter out device without an local ip and without ssid (most probably bluetooth devices)
validList = allList.filter(device => device.localip && device.localip.length > 0 && device.ssid && device.ssid.length > 0);
}
validList.map(device => device.country = country);
devices.push(...validList);
} catch (err) {
warningMsg = `Warning - Could not retrive device list from ${country} server. Message: ${err.message}`
}
}
return {
success: true,
warning: warningMsg,
devices: devices.map(device => {
return {
name: device.name,
ip: device.localip,
token: device.token,
model: device.model,
deviceId: device.did,
country: device.country
}
})
}
}
async generateDeviceClass(params) {
const storagePath = this.homebridgeStoragePath + '/miotSpecClassGenerator/devices/';
const miotSpecClassGenerator = new MiotSpecClassGenerator(params.deviceModel, null, params.deviceName, null, params.isMiCloudRequired, storagePath);
try {
await miotSpecClassGenerator.generate();
return {
success: true,
filePath: miotSpecClassGenerator.getOutputFilePath(),
devType: miotSpecClassGenerator.getDeviceType()
}
} catch (err) {
return {
success: false,
error: err.message
}
}
}
async getDeviceMetadata(params) {
try {
const result = await MiotSpecFetcher.fetchMiotSpecByModel(params.deviceModel, true);
const {
description,
properties,
actions,
events
} = result;
return {
success: true,
metadata: {
description,
properties,
actions,
events
}
}
} catch (err) {
return {
success: false,
error: err.message
}
}
}
}
// start the instance of the class
(() => {
return new UiServer;
})();