homebridge-tahoma
Version:
Sample Platform plugin for TaHoma and Cozytouch services (Somfy,Atlantic,Thermor,Sauter): https://github.com/dubocr/homebridge-tahoma
232 lines • 9.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Platform_1 = require("./Platform");
const overkiz_client_1 = require("overkiz-client");
const colors_1 = require("./colors");
class Mapper {
constructor(platform, accessory, device) {
this.platform = platform;
this.accessory = accessory;
this.device = device;
this.stateless = false;
this.expectedStates = [];
this.log = this.platform.log;
}
build() {
const config = Object.assign({}, this.platform.devicesConfig[this.device.definition.uiClass], this.platform.devicesConfig[this.device.definition.widgetName], this.platform.devicesConfig[this.device.label], this.platform.devicesConfig[this.device.uuid]);
this.stateless = this.device.states.length === 0 ||
(this.expectedStates.length > 0 && !this.expectedStates.some((state) => this.device.hasState(state)));
this.applyConfig(config);
if (Object.keys(config).length > 0) {
delete config.key;
if (this.platform.config.debug) {
this.log.info(`${colors_1.GREY} Config: `, JSON.stringify(config));
}
else {
this.log.debug(' Config: ', JSON.stringify(config));
}
}
const services = this.registerServices();
const info = this.accessory.getService(Platform_1.Services.AccessoryInformation);
if (info) {
info.setCharacteristic(Platform_1.Characteristics.Manufacturer, this.device.manufacturer);
info.setCharacteristic(Platform_1.Characteristics.Model, this.device.model);
info.setCharacteristic(Platform_1.Characteristics.SerialNumber, this.device.address.substring(0, 64));
services.push(info);
}
this.accessory.services.forEach((service) => {
if (!services.find((s) => s.UUID === service.UUID && s.subtype === service.subtype)) {
this.accessory.removeService(service);
}
});
if (!this.stateless) {
// Init and register states changes
this.onStatesChanged(this.device.states, true);
this.device.on('states', states => this.onStatesChanged(states));
// Init and register sensors states changes
this.device.sensors.forEach((sensor) => {
this.onStatesChanged(sensor.states, true);
sensor.on('states', states => this.onStatesChanged(states));
});
}
// TODO: instanciate mapper for device sensors
// Configure accessory sensors
// this.device.sensors.forEach((sensor) => new mapper(platform, accessory, sensor)))
}
/**
* Helper methods
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
applyConfig(config) {
//
}
registerService(type, subtype) {
let service;
const name = subtype ? this.translate(subtype) : this.device.label;
if (subtype) {
service = this.accessory.getServiceById(type, subtype) || this.accessory.addService(type, name, subtype);
}
else {
service = this.accessory.getService(type) || this.accessory.addService(type);
}
service.setCharacteristic(Platform_1.Characteristics.Name, name);
/*
service.getCharacteristic(Characteristics.Name)
.updateValue(name)
.onSet((value) => {
this.debug('Will rename ' + name + ' to ' + value);
this.platform.client.setDeviceName(this.device.deviceURL, value);
});
*/
return service;
}
translate(value) {
switch (value) {
case 'boost': return 'Boost';
case 'drying': return 'Séchage';
default: return value.charAt(0).toUpperCase() + value.slice(1);
}
}
debounce(task, immediate = []) {
return async (value) => {
if (this.debounceTimer !== null) {
clearTimeout(this.debounceTimer);
}
if (immediate.includes(value)) {
await task.bind(this, value)();
}
else {
this.debounceTimer = setTimeout(async () => {
this.debounceTimer = null;
task.bind(this, value)().catch(() => null);
}, 500);
}
};
}
postpone(task, ...args) {
if (this.postponeTimer !== null) {
clearTimeout(this.postponeTimer);
}
this.postponeTimer = setTimeout(() => {
this.postponeTimer = null;
task.bind(this, ...args)();
}, 500);
}
async executeCommands(commands, standalone = false) {
if (commands === undefined || (Array.isArray(commands) && commands.length === 0)) {
this.error('No target command for', this.device.label);
throw -70409 /* HAPStatus.RESOURCE_DOES_NOT_EXIST */;
}
else if (Array.isArray(commands)) {
for (const c of commands) {
this.info(c.name + JSON.stringify(c.parameters));
}
}
else {
this.info(commands.name + JSON.stringify(commands.parameters));
commands = [commands];
}
const commandName = commands[0].name;
const localizedName = this.platform.translate(commands[0].name + (commands[0].parameters.length > 0 ? '.' + commands[0].parameters[0] : ''));
/*
if (!this.isIdle) {
this.cancelExecution();
}
*/
const highPriority = this.device.hasState('io:PriorityLockLevelState') ? true : false;
const label = this.device.label + ' - ' + localizedName;
if (this.actionPromise) {
this.actionPromise.action.addCommands(commands);
}
else {
this.actionPromise = new Promise((resolve, reject) => {
setTimeout(async () => {
try {
this.executionId = await this.platform.executeAction(label, this.actionPromise.action, highPriority, standalone);
resolve(this.actionPromise.action);
}
catch (error) {
this.error(commandName + ' ' + error.message);
reject(-70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
}
this.actionPromise = null;
}, 100);
});
this.actionPromise.action = new overkiz_client_1.Action(this.device.deviceURL, commands);
this.actionPromise.action.on('update', (state, event) => {
if (state === overkiz_client_1.ExecutionState.FAILED) {
this.error(commandName, event.failureType);
}
else if (state === overkiz_client_1.ExecutionState.COMPLETED) {
this.info(commandName, state);
}
else {
this.debug(commandName, state);
}
});
}
return this.actionPromise;
}
async delay(duration) {
return new Promise(resolve => setTimeout(resolve, duration));
}
async requestStatesUpdate(defer) {
if (defer) {
await this.delay(defer * 1000);
}
await this.platform.client.refreshDeviceStates(this.device.deviceURL);
}
/**
* Logging methods
*/
debug(...args) {
if (this.platform.config.debug) {
this.platform.log.info(`${colors_1.GREY}[${this.device.label}]`, ...args);
}
else {
this.platform.log.debug(`[${this.device.label}]`, ...args);
}
}
info(...args) {
this.platform.log.info(`[${this.device.label}]`, ...args);
}
warn(...args) {
this.platform.log.warn(`[${this.device.label}]`, ...args);
}
error(...args) {
this.platform.log.error(`[${this.device.label}]`, ...args);
}
registerServices() {
if (typeof this.registerMainService === 'function') {
try {
return [this.registerMainService()];
}
catch (error) {
this.log.warn(error.message);
}
}
else {
this.log.warn(this.device.definition.widgetName + ' not supported.');
}
return [];
}
onStatesChanged(states, init = false) {
states.forEach((state) => {
if (!init) {
this.debug(state.name + ' => ' + state.value);
}
if (typeof this.onStateChanged === 'function') {
this.onStateChanged(state.name, state.value);
}
});
}
// OLD
get isIdle() {
return !this.platform.client.hasExecution(this.executionId);
}
async cancelExecution() {
await this.platform.client.cancelExecution(this.executionId);
}
}
exports.default = Mapper;
//# sourceMappingURL=Mapper.js.map