UNPKG

@homebridge-plugins/homebridge-lutron-caseta-leap

Version:
114 lines 6.11 kB
export class SerenaTiltOnlyWoodBlinds { platform; accessory; bridge; service; device; constructor(platform, accessory, bridge) { this.platform = platform; this.accessory = accessory; this.bridge = bridge; this.device = accessory.context.device; this.accessory .getService(this.platform.api.hap.Service.AccessoryInformation) .setCharacteristic(this.platform.api.hap.Characteristic.Manufacturer, 'Lutron Electronics Co., Inc') .setCharacteristic(this.platform.api.hap.Characteristic.Model, this.device.ModelNumber) .setCharacteristic(this.platform.api.hap.Characteristic.Name, this.device.FullyQualifiedName.join(' ')) .setCharacteristic(this.platform.api.hap.Characteristic.ConfiguredName, this.device.FullyQualifiedName.join(' ')) .setCharacteristic(this.platform.api.hap.Characteristic.SerialNumber, this.device.SerialNumber.toString()); this.service = this.accessory.getService(this.platform.api.hap.Service.WindowCovering) || this.accessory.addService(this.platform.api.hap.Service.WindowCovering); this.service.setCharacteristic(this.platform.api.hap.Characteristic.Name, this.device.FullyQualifiedName.join(' ')); // create handlers for required characteristics const getter = (cb) => { this.handleCurrentPositionGet().then((pos) => { cb(null, pos); }, (e) => { cb(e); }); }; const setter = (pos, cb) => { this.handleTargetPositionSet(pos).then(() => { cb(null, pos); }, (e) => { cb(e); }); }; this.service .getCharacteristic(this.platform.api.hap.Characteristic.CurrentPosition) .on("get" /* this.platform.api.hap.CharacteristicEventTypes.GET */, getter); this.service .getCharacteristic(this.platform.api.hap.Characteristic.TargetPosition) .on("get" /* this.platform.api.hap.CharacteristicEventTypes.GET */, getter) .on("set" /* this.platform.api.hap.CharacteristicEventTypes.SET */, setter); this.service .getCharacteristic(this.platform.api.hap.Characteristic.PositionState) .on("get" /* this.platform.api.hap.CharacteristicEventTypes.GET */, this.handlePositionStateGet.bind(this)); this.platform.on('unsolicited', this.handleUnsolicited.bind(this)); } // `value` can range from 0-100, but n.b. 50 is flat. The Homekit // Window Covering's required "Position" characteristic expects 0 to be // "fully closed" and 100 to be "fully open". As such, we constrain the // tilt angle to [-90,0] degrees by scaling `value` after the fact. async handleCurrentPositionGet() { this.platform.log.debug('blinds', this.device.FullyQualifiedName.join(' '), 'were asked for current or target position'); const tilt = await this.bridge.readBlindsTilt(this.device); const adj_val = Math.min(100, tilt * 2); // Per-poll noise — Homebridge re-reads position frequently. Was info // (visible in normal logs); now debug so steady-state operation stays // quiet, with global debug bringing it back when troubleshooting. this.platform.log.debug('Told Homekit that blinds', this.device.FullyQualifiedName.join(' '), 'are at position', adj_val); return adj_val; } async handleTargetPositionSet(value) { const adj_val = Number(value) / 2; // Per-command noise — fires every time HomeKit drives the blind. Was // info; now debug. this.platform.log.debug('Commanded', this.device.FullyQualifiedName.join(' '), 'blinds to (adjusted) value', adj_val); await this.bridge.setBlindsTilt(this.device, adj_val); } handlePositionStateGet(cb) { cb(null, this.platform.api.hap.Characteristic.PositionState.STOPPED); } handleUnsolicited(response) { if (response.Header.MessageBodyType === 'OneZoneStatus') { if (response.Body?.ZoneStatus?.Zone?.href === this.device.LocalZones[0].href) { const adj_val = Math.min(100, response.Body.ZoneStatus.Tilt * 2); // Per state-change noise — fires on every physical blind movement. // Was info; now debug. this.platform.log.debug('Blinds', this.device.FullyQualifiedName.join(' '), 'reported a new position of', adj_val); this.accessory .getService(this.platform.api.hap.Service.WindowCovering) .getCharacteristic(this.platform.api.hap.Characteristic.TargetPosition) .updateValue(adj_val); this.accessory .getService(this.platform.api.hap.Service.WindowCovering) .getCharacteristic(this.platform.api.hap.Characteristic.CurrentPosition) .updateValue(adj_val); const matterApi = this.platform.api.matter; if (matterApi && this.accessory?.UUID) { const tiltPercent100ths = Math.max(0, Math.min(10000, Math.round(adj_val * 100))); void matterApi.updateAccessoryState(this.accessory.UUID, 'windowCovering', { currentPositionTiltPercent100ths: tiltPercent100ths, targetPositionTiltPercent100ths: tiltPercent100ths, }); } } } } /** * Returns a Matter clusters object for this blind. */ static getMatterClusters() { // Tilt-only blinds: Matter §8.3 WindowCovering // 0 = open (horizontal), 10000 = closed (vertical) in hundredths of percent return { windowCovering: { currentPositionTiltPercent100ths: 0, // 0=horizontal/open targetPositionTiltPercent100ths: 0, // 0=horizontal/open }, }; } } //# sourceMappingURL=SerenaTiltOnlyWoodBlinds.js.map