homebridge-better-miot
Version:
Some xiaomi devices integration
134 lines • 5.08 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenericDevice = void 0;
const miio = __importStar(require("miio-api"));
const DELAY_MS = 250; // 0.25 sec
const API_CALL_OPTIONS = {
attempts: 5,
delay: DELAY_MS,
timeout: 14 * DELAY_MS, // 3 sec
};
class GenericDevice {
constructor({ address, token, properties }) {
this.properties = {};
this.listeners = {};
this.propertiesConfigMap = {};
this.config = { address, token, properties };
this.setProperties(properties);
this.getDevice()
.then(() => this.fetchProperties());
}
async getDevice() {
const { address, token } = this.config;
if (!this.connectedDevice) {
try {
this.connectedDevice = await miio.device({ address, token }, API_CALL_OPTIONS);
this.info = await this.connectedDevice.call('miIO.info');
}
catch (_a) {
throw new Error('Something went wrong while connecting');
}
}
return this.connectedDevice;
}
subscribe(property, cb) {
if (!Array.isArray(this.listeners[property])) {
this.listeners[property] = [];
}
this.listeners[property].push(cb);
}
notifyUpdate(property) {
if (Array.isArray(this.listeners[property])) {
this.listeners[property].forEach((cb) => cb(this.properties[property]));
}
}
setProperties(properties) {
properties.forEach((property) => {
const { name, title, mapper = (value) => value, } = property;
const propertyTitle = title || name;
this.propertiesConfigMap[propertyTitle] = {
name,
mapper,
title: propertyTitle,
};
});
}
// TODO: make 2 requests if properties.length > 15
async loadProperties(config) {
const propertyNameTitleMap = Object.values(config)
.reduce((acc, { name, title }) => {
acc[name] = title;
return acc;
}, {});
const propertyNames = Object.keys(propertyNameTitleMap);
const device = await this.getDevice();
const result = await device.call('get_prop', propertyNames, API_CALL_OPTIONS);
const notifyQueue = [];
result === null || result === void 0 ? void 0 : result.forEach((value, index) => {
const name = propertyNames[index];
const title = propertyNameTitleMap[name];
const mapper = config[title].mapper;
const parsedValue = mapper(value);
if (this.properties[title] !== parsedValue) {
notifyQueue.push(title);
}
this.properties[title] = parsedValue;
});
notifyQueue.forEach((property) => this.notifyUpdate(property));
}
async fetchProperty(propertyTitle) {
const titles = typeof propertyTitle === 'string'
? [propertyTitle]
: propertyTitle;
if (!titles.every((title) => title in this.propertiesConfigMap)) {
return;
}
const propertiesConfig = titles.reduce((acc, propertyTitle) => {
acc[propertyTitle] = this.propertiesConfigMap[propertyTitle];
return acc;
}, {});
return this.loadProperties(propertiesConfig);
}
async fetchProperties() {
return this.loadProperties(this.propertiesConfigMap);
}
async call(method, params, refetch) {
const device = await this.getDevice();
try {
const result = await device.call(method, params, API_CALL_OPTIONS);
if (result && Array.isArray(refetch)) {
return new Promise((resolve) => {
setTimeout(async () => {
await this.fetchProperty(refetch);
resolve(result);
}, DELAY_MS);
});
}
return result;
}
catch (err) {
throw Error(`Can't make ${method} api call`);
}
}
}
exports.GenericDevice = GenericDevice;
//# sourceMappingURL=GenericDevice.js.map