UNPKG

homebridge-daikin-local-platform

Version:

Homebridge platform plugin providing HomeKit support for Daikin air conditioners with local control

338 lines (336 loc) 21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const const_1 = require("../const"); const daikin_local_1 = require("../daikin-local"); /** * An instance of this class is created for each accessory the platform registers. * Each accessory may expose multiple services of different service types. */ class ClimateAccessory { constructor(platform, accessory) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; this.platform = platform; this.accessory = accessory; this.services = {}; this._lastFanSpeed = 1; // slient accessory.context.device.setCallback(this.updateDeviceStatus.bind(this)); // Accessory Information // https://developers.homebridge.io/#/service/AccessoryInformation (_a = this.accessory.getService(this.platform.Service.AccessoryInformation)) === null || _a === void 0 ? void 0 : _a.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Daikin ' + ((_b = accessory.context.device) === null || _b === void 0 ? void 0 : _b.getDeviceReg())).setCharacteristic(this.platform.Characteristic.Model, ((_c = accessory.context.device) === null || _c === void 0 ? void 0 : _c.getDeviceType()) || 'Unknown').setCharacteristic(this.platform.Characteristic.SerialNumber, ((_d = accessory.context.device) === null || _d === void 0 ? void 0 : _d.getMacAddress()) || 'Unknown').setCharacteristic(this.platform.Characteristic.FirmwareRevision, ((_e = accessory.context.device) === null || _e === void 0 ? void 0 : _e.getFirmwareVersion()) || 'Unknown'); this.services['Climate'] = this.accessory.getService(this.platform.Service.HeaterCooler) || this.accessory.addService(this.platform.Service.HeaterCooler); // This is what is displayed as the default name on the Home app this.services['Climate'].setCharacteristic(this.platform.Characteristic.Name, ((_f = accessory.context.device) === null || _f === void 0 ? void 0 : _f.getDeviceName()) || '空調'); this.services['Climate'] .getCharacteristic(this.platform.Characteristic.Active) .onSet(this.setClimateActive.bind(this)) .onGet(this.getClimateActive.bind(this)); this.services['Climate'] .getCharacteristic(this.platform.Characteristic.CurrentTemperature) .setProps({ minValue: -100, maxValue: 100, minStep: 0.01, }); this.services['Climate'] .getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .onGet(this.getCurrentHeaterCoolerState.bind(this)); this.services['Climate'] .getCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState) .onSet(this.setTargetHeaterCoolerState.bind(this)); // Cooling Threshold Temperature (optional) this.services['Climate'] .getCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature) .setProps({ minValue: ((_g = accessory.context.device) === null || _g === void 0 ? void 0 : _g.getCoolingThresholdTemperatureRange()[0]) || 10, maxValue: ((_h = accessory.context.device) === null || _h === void 0 ? void 0 : _h.getCoolingThresholdTemperatureRange()[1]) || 30, minStep: 0.5, }) .onSet(this.setCoolingThresholdTemperature.bind(this)) .onGet(this.getCoolingThresholdTemperature.bind(this)); // Heating Threshold Temperature (optional) this.services['Climate'] .getCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature) .setProps({ minValue: ((_j = accessory.context.device) === null || _j === void 0 ? void 0 : _j.getHeatingThresholdTemperatureRange()[0]) || 10, maxValue: ((_k = accessory.context.device) === null || _k === void 0 ? void 0 : _k.getHeatingThresholdTemperatureRange()[1]) || 30, minStep: 0.5, }) .onSet(this.setHeatingThresholdTemperature.bind(this)) .onGet(this.getHeatingThresholdTemperature.bind(this)); // Fan control service this.services['Fan'] = this.accessory.getService(this.platform.Service.Fan) || this.accessory.addService(this.platform.Service.Fan); this.services['Fan'].getCharacteristic(this.platform.Characteristic.On) .onGet(this.getFanStatus.bind(this)) .onSet(this.setFanStatus.bind(this)); this.services['Fan'].getCharacteristic(this.platform.Characteristic.RotationSpeed) .setProps({ unit: null, format: "uint8" /* this.platform.Characteristic.Formats.UINT8 */, minValue: 0, maxValue: 6, validValues: [0, 1, 2, 3, 4, 5, 6] }) .onGet(this.getRotationSpeed.bind(this)) .onSet(this.setRotationSpeed.bind(this)); /* // // Motion sensor switch // const buttonName = 'Motion Sensor'; this.services[buttonName] = this.accessory.getServiceById(this.platform.Service.Switch, buttonName) || this.accessory.addService(this.platform.Service.Switch, 'buttonBuzzerName', buttonName); this.services[buttonName].setCharacteristic(this.platform.Characteristic.Name, buttonName); this.services[buttonName].getCharacteristic(this.platform.Characteristic.On) .onGet(this.getMotionDetection.bind(this)) .onSet(this.setMotionDetection.bind(this)); this.services[buttonName].addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.services[buttonName].setCharacteristic(this.platform.Characteristic.ConfiguredName, buttonName); */ //// this.services['HumiditySensor'] = this.accessory.getService(this.platform.Service.HumiditySensor) || this.accessory.addService(this.platform.Service.HumiditySensor); this.services['HumiditySensor'].getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity) .onGet(this.getCurrentRelativeHumidity.bind(this)); // Separate service so it doesn't collide with HeaterCooler's // CurrentTemperature, which reports the indoor value. this.services['OutdoorTemperatureSensor'] = this.accessory.getServiceById(this.platform.Service.TemperatureSensor, 'outdoor') || this.accessory.addService(this.platform.Service.TemperatureSensor, 'Outdoor Temperature', 'outdoor'); this.services['OutdoorTemperatureSensor'] .getCharacteristic(this.platform.Characteristic.CurrentTemperature) .setProps({ minValue: -100, maxValue: 100, minStep: 0.5, }) .onGet(this.getOutdoorTemperature.bind(this)); ////////// // Update characteristic values asynchronously instead of using onGet handlers this.refreshDeviceStatus(); } async refreshDeviceStatus() { this.platform.log.debug(`Accessory: Refresh status for device '${this.accessory.displayName}'`); await this.accessory.context.device.fetchDeviceStatus(); /// // Schedule continuous device updates on the first run if (!this._refreshInterval) { this._refreshInterval = setInterval(this.refreshDeviceStatus.bind(this), const_1.DEVICE_STATUS_REFRESH_INTERVAL); } } // Turn a device command result into a HomeKit-visible outcome: a failed command // must reject the onSet so the Home app doesn't show a stale "success" state. assertCommand(ok) { if (!ok) { throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); } } async setClimateActive(value) { this.platform.log.debug(`Accessory: setClimateActive() for device '${this.accessory.displayName}'`); this.assertCommand(await this.accessory.context.device.setPowerStatus(value === this.platform.Characteristic.Active.ACTIVE)); } async getClimateActive() { this.platform.log.debug(`Accessory: getClimateActive() for device '${this.accessory.displayName}'`); const active = this.accessory.context.device.getPowerStatus() ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE; return active; } async getFanStatus() { this.platform.log.debug(`Accessory: getFanStatus() for device '${this.accessory.displayName}'`); const value = this.accessory.context.device.getFanSpeedNumber() !== 0; return value; } async setFanStatus(value) { this.platform.log.debug(`Accessory: setFanStatus() for device '${this.accessory.displayName}'`); let speed = this._lastFanSpeed; // restore to previous non-zero speed if (value === false) { // turn off fan means turn on auto-speed mode speed = 0; } await this.setRotationSpeed(speed); } async getRotationSpeed() { this.platform.log.debug(`Accessory: getRotationSpeed() for device '${this.accessory.displayName}'`); let value = this.accessory.context.device.getFanSpeedNumber(); if (value === 0) { value = this._lastFanSpeed; } return value; } async setRotationSpeed(value) { this.platform.log.debug(`Accessory: setRotationSpeed() for device '${this.accessory.displayName}'`); const entry = daikin_local_1.FAN_SPEED_TABLE.find(e => e.number === value); if (!entry) { this.platform.log.error(`Unknown RotationSpeed: ${value}`); return; } // Speed 0 = auto; remember the last explicit speed so turning the fan back on restores it. if (value === 0) { const lastFanSpeed = this.accessory.context.device.getFanSpeedNumber(); if (lastFanSpeed !== 0) { this._lastFanSpeed = lastFanSpeed; } } this.assertCommand(await this.accessory.context.device.setFanSpeed(entry.code)); } async getCurrentRelativeHumidity() { try { this.platform.log.debug(`Accessory: getCurrentRelativeHumidity() for device '${this.accessory.displayName}'`); } catch (e) { this.platform.log.error(e); } return this.accessory.context.device.getIndoorHumidity(); } async getOutdoorTemperature() { this.platform.log.debug(`Accessory: getOutdoorTemperature() for device '${this.accessory.displayName}'`); const value = this.accessory.context.device.getOutdoorTemperature(); if (Number.isFinite(value)) { return value; } // Outdoor unit hasn't reported yet (e.g. AC just powered on); keep // whatever HomeKit already has cached rather than spike to 0. const cached = this.services['OutdoorTemperatureSensor'] .getCharacteristic(this.platform.Characteristic.CurrentTemperature).value; return typeof cached === 'number' ? cached : 0; } async getCurrentHeaterCoolerState() { var _a; if (this.accessory.context.device.getPowerStatus()) { const currentTemperature = await this.accessory.context.device.getIndoorTemperature() || 0; const targetTemperature = await this.accessory.context.device.getTargetTemperature() || 0; const currentMode = await this.accessory.context.device.getOperationMode() || daikin_local_1.CLIMATE_MODE_AUTO; switch (currentMode) { // Auto case daikin_local_1.CLIMATE_MODE_AUTO: // Set target state and current state (based on current temperature) this.services['Climate'].updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.AUTO); if (currentTemperature < targetTemperature) { this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING); } else if (currentTemperature > targetTemperature) { this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING); } else { this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE); } break; // Heat case daikin_local_1.CLIMATE_MODE_HEATING: this.services['Climate'].updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.HEAT); if (currentTemperature < targetTemperature) { this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.HEATING); } else { this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE); } break; // Cool case daikin_local_1.CLIMATE_MODE_COOLING: this.services['Climate'].updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.COOL); if (currentTemperature > targetTemperature) { this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.COOLING); } else { this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE); } break; // Dry (Dehumidifier) case daikin_local_1.CLIMATE_MODE_DEHUMIDIFY: this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE); this.services['Climate'].updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.AUTO); break; // Humidifier case daikin_local_1.CLIMATE_MODE_HUMIDIFY: this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE); this.services['Climate'].updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.AUTO); break; // Fan case daikin_local_1.CLIMATE_MODE_FAN: this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState) .updateValue(this.platform.Characteristic.CurrentHeaterCoolerState.IDLE); this.services['Climate'].updateCharacteristic(this.platform.Characteristic.TargetHeaterCoolerState, this.platform.Characteristic.TargetHeaterCoolerState.AUTO); break; default: this.platform.log.error(`Unknown TargetHeaterCoolerState state: '${this.accessory.displayName}' '${currentMode}'`); break; } return (_a = this.services['Climate'].getCharacteristic(this.platform.Characteristic.CurrentHeaterCoolerState).value) !== null && _a !== void 0 ? _a : this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE; } return this.platform.Characteristic.CurrentHeaterCoolerState.INACTIVE; } async getCoolingThresholdTemperature() { this.platform.log.debug(`Accessory: getCoolingThresholdTemperature() for device '${this.accessory.displayName}'`); const value = this.accessory.context.device.getTargetTemperatureWithMode(daikin_local_1.CLIMATE_MODE_COOLING); return value; } async getHeatingThresholdTemperature() { this.platform.log.debug(`Accessory: getHeatingThresholdTemperature() for device '${this.accessory.displayName}'`); const value = this.accessory.context.device.getTargetTemperatureWithMode(daikin_local_1.CLIMATE_MODE_HEATING); return value; } async setCoolingThresholdTemperature(value) { this.platform.log.debug(`Accessory: setCoolingThresholdTemperature() for device '${this.accessory.displayName}'`); const threshold = +value; this.assertCommand(await this.accessory.context.device.setOperationMode(daikin_local_1.CLIMATE_MODE_COOLING)); this.assertCommand(await this.accessory.context.device.setTargetTemperature(threshold)); } async setHeatingThresholdTemperature(value) { this.platform.log.debug(`Accessory: setHeatingThresholdTemperature() for device '${this.accessory.displayName}'`); const threshold = +value; this.assertCommand(await this.accessory.context.device.setOperationMode(daikin_local_1.CLIMATE_MODE_HEATING)); this.assertCommand(await this.accessory.context.device.setTargetTemperature(threshold)); } async setTargetHeaterCoolerState(value) { this.platform.log.debug(`Accessory: setTargetHeaterCoolerState() for device '${this.accessory.displayName}'`); let mode = daikin_local_1.CLIMATE_MODE_AUTO; switch (value) { case this.platform.Characteristic.TargetHeaterCoolerState.AUTO: mode = daikin_local_1.CLIMATE_MODE_AUTO; break; case this.platform.Characteristic.TargetHeaterCoolerState.COOL: mode = daikin_local_1.CLIMATE_MODE_COOLING; break; case this.platform.Characteristic.TargetHeaterCoolerState.HEAT: mode = daikin_local_1.CLIMATE_MODE_HEATING; break; default: this.platform.log.error(`Unknown TargetHeaterCoolerState ${value}`); return; } this.assertCommand(await this.accessory.context.device.setOperationMode(mode)); } async updateDeviceStatus(device) { try { this.platform.log.debug(`Accessory: updateDeviceStatus() for device '${this.accessory.displayName}'`); const active = this.accessory.context.device.getPowerStatus() ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE; this.services['Climate'].updateCharacteristic(this.platform.Characteristic.Active, active); this.services['Climate'].updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.accessory.context.device.getIndoorTemperature()); this.getCurrentHeaterCoolerState(); this.services['Climate'].updateCharacteristic(this.platform.Characteristic.HeatingThresholdTemperature, this.accessory.context.device.getTargetTemperatureWithMode(daikin_local_1.CLIMATE_MODE_HEATING)); this.services['Climate'].updateCharacteristic(this.platform.Characteristic.CoolingThresholdTemperature, this.accessory.context.device.getTargetTemperatureWithMode(daikin_local_1.CLIMATE_MODE_COOLING)); this.services['HumiditySensor'].updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.accessory.context.device.getIndoorHumidity()); const outdoorTemp = this.accessory.context.device.getOutdoorTemperature(); if (Number.isFinite(outdoorTemp)) { this.services['OutdoorTemperatureSensor'] .updateCharacteristic(this.platform.Characteristic.CurrentTemperature, outdoorTemp); } //this.services['MotionSensor'].updateCharacteristic(this.platform.Characteristic.On, this.accessory.context.device.getMotionDetection()); } catch (e) { this.platform.log.error(e); } } } exports.default = ClimateAccessory; //# sourceMappingURL=climate.js.map