import type { Service, PlatformAccessory, CharacteristicValue } from 'homebridge'; import type { Device } from './device.js'; import { Platform } from './platform.js'; import { WindLevel } from './device.js'; export class Accessory { private service: Service; constructor( private readonly platform: Platform, private readonly accessory: PlatformAccessory, private readonly device: Device, ) { this.accessory.getService(this.platform.Service.AccessoryInformation)! .setCharacteristic(this.platform.Characteristic.Manufacturer, 'Xiaomi') .setCharacteristic(this.platform.Characteristic.Model, 'xiaomi.aircondition.ma2') .setCharacteristic(this.platform.Characteristic.SerialNumber, this.device.deviceId().toString()); this.service = this.accessory.getService(this.platform.Service.HeaterCooler) || this.accessory.addService(this.platform.Service.HeaterCooler); this.service.setCharacteristic(this.platform.Characteristic.Name, this.accessory.context.config.name); this.service.getCharacteristic(this.platform.Characteristic.Active) .onSet(this.setActive.bind(this)) .onGet(this.getActive.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .onGet(this.getCurrentHeaterCoolerState.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState) .onSet(this.setTargetHeaterCoolerState.bind(this)) .onGet(this.getTargetHeaterCoolerState.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.CurrentTemperature) .onGet(this.getCurrentTemperature.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature) .onSet(this.setTargetTemperature.bind(this)) .onGet(this.getTargetTemperature.bind(this)) .setProps({ minValue: 16, maxValue: 31, minStep: 0.5, }); this.service.getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature) .onSet(this.setTargetTemperature.bind(this)) .onGet(this.getTargetTemperature.bind(this)) .setProps({ minValue: 16, maxValue: 31, minStep: 0.5, }); this.service.getCharacteristic(this.platform.Characteristic.RotationSpeed) .onSet(this.setRotationSpeed.bind(this)) .onGet(this.getRotationSpeed.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.SwingMode) .onSet(this.setSwingMode.bind(this)) .onGet(this.getSwingMode.bind(this)); this.polling(); } async polling() { await this.device.refresh(); this.platform.log.debug('Polling state from device: ', this.device.getRawState()); setTimeout(this.polling.bind(this), 60000); } async setActive(value: CharacteristicValue) { if (value === this.platform.Characteristic.Active.ACTIVE) { await this.device.turnOn(); return; } await this.device.turnOff(); } async getActive(): Promise { return this.device.isOn() ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE; } async getCurrentHeaterCoolerState(): Promise { if (this.device.isOff()) { return this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE; } if (this.device.isCooling()) { return this.device.temperature() > this.device.targetTemperature() ? this.platform.Characteristic.CurrentHeaterCoolerState.COOLING : this.platform.Characteristic.CurrentHeaterCoolerState.IDLE; } if (this.device.isHeating()) { return this.device.temperature() < this.device.targetTemperature() ? this.platform.Characteristic.CurrentHeaterCoolerState.HEATING : this.platform.Characteristic.CurrentHeaterCoolerState.IDLE; } return this.platform.Characteristic.CurrentHeaterCoolerState.COOLING; } async setTargetHeaterCoolerState(value: CharacteristicValue) { switch (value) { case this.platform.Characteristic.TargetHeaterCoolerState.HEAT: await this.device.heating(); break; case this.platform.Characteristic.TargetHeaterCoolerState.COOL: await this.device.cooling(); break; default: await this.device.auto(); break; } } async getTargetHeaterCoolerState(): Promise { if (this.device.isCooling()) { return this.platform.Characteristic.TargetHeaterCoolerState.COOL; } if (this.device.isHeating()) { return this.platform.Characteristic.TargetHeaterCoolerState.HEAT; } return this.platform.Characteristic.TargetHeaterCoolerState.AUTO; } getCurrentTemperature(): CharacteristicValue { return this.device.temperature(); } async setTargetTemperature(value: CharacteristicValue) { await this.device.temperatureSetTo(value as number); } getTargetTemperature(): CharacteristicValue { return this.device.targetTemperature(); } async setRotationSpeed(value: CharacteristicValue) { const level = Math.ceil(value as number / 100 * WindLevel.Level7); await this.device.windLevelSetTo(level); } getRotationSpeed(): CharacteristicValue { const level = this.device.windLevel(); const speed = level * Math.ceil(100 / WindLevel.Level7); return speed > 100 ? 100 : speed; } async setSwingMode(value: CharacteristicValue) { if (value === this.platform.Characteristic.SwingMode.SWING_ENABLED) { await this.device.startSwinging(); } else { await this.device.stopSwinging(); } } getSwingMode() { return this.device.swinging(); } }