diff --git a/config.schema.json b/config.schema.json index a090787..3c6d4a0 100644 --- a/config.schema.json +++ b/config.schema.json @@ -53,6 +53,16 @@ } } }, + "garageDoorType": { + "title": "Enable publishing a separate \"occupancy\" obstruction sensor for the garage", + "type": "string", + "default": "garage", + "oneOf": [ + { "title": "Garage Door", "enum": ["garage"] }, + { "title": "Window Covering (allows positional control)", "enum": ["cover"] } + ], + "required": true + }, "enableSeparateObstructionSensor": { "title": "Enable publishing a separate \"occupancy\" obstruction sensor for the garage", "type": "boolean", diff --git a/package-lock.json b/package-lock.json index 150c7c5..35bae1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "homebridge-blaq", - "version": "0.2.21", + "version": "0.2.22", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "homebridge-blaq", - "version": "0.2.21", + "version": "0.2.22", "funding": [ { "type": "github", diff --git a/package.json b/package.json index b78fd84..1c4fcda 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": false, "displayName": "Konnected BlaQ", "name": "homebridge-blaq", - "version": "0.2.21", + "version": "0.2.22", "description": "Control and view your garage door(s) remotely with real-time updates using Konnected's BlaQ hardware", "license": "Apache-2.0", "type": "module", diff --git a/src/accessory/garage-door.ts b/src/accessory/garage-door.ts index 2f46774..4f0f040 100644 --- a/src/accessory/garage-door.ts +++ b/src/accessory/garage-door.ts @@ -18,6 +18,10 @@ const BINARY_SENSOR_PREFIX = 'binary_sensor-'; const COVER_PREFIX = 'cover-'; const LOCK_PREFIX = 'lock-'; +type BlaQGarageDoorAccessoryConstructorParams = BaseBlaQAccessoryConstructorParams & { + type: 'garage' | 'cover'; +}; + /** * Platform Accessory * An instance of this class is created for each accessory your platform registers @@ -35,9 +39,11 @@ export class BlaQGarageDoorAccessory extends BaseBlaQAccessory { private coverType?: GarageCoverType = 'garage_door'; private preClosing?: boolean; - constructor(args: BaseBlaQAccessoryConstructorParams) { + constructor(args: BlaQGarageDoorAccessoryConstructorParams) { super(args); - this.garageDoorService = this.getOrAddService(this.platform.service.GarageDoorOpener); + this.garageDoorService = this.getOrAddService( + args.type === 'garage' ? this.platform.service.GarageDoorOpener : this.platform.service.WindowCovering, + ); // Set the service name. This is what is displayed as the name on the Home // app. We use what we stored in `accessory.context` in `discoverDevices`. @@ -46,6 +52,13 @@ export class BlaQGarageDoorAccessory extends BaseBlaQAccessory { this.garageDoorService.getCharacteristic(this.platform.characteristic.CurrentDoorState) .onGet(this.getCurrentDoorState.bind(this)); + this.garageDoorService.getCharacteristic(this.platform.characteristic.PositionState) + .onGet(this.getCurrentPositionState.bind(this)); + + this.garageDoorService.getCharacteristic(this.platform.characteristic.HoldPosition) + .onGet(this.getHoldPositionState.bind(this)) + .onSet(this.setHoldPositionState.bind(this)); + this.garageDoorService.getCharacteristic(this.platform.characteristic.CurrentPosition) .onGet(this.getCurrentPosition.bind(this)); @@ -103,7 +116,12 @@ export class BlaQGarageDoorAccessory extends BaseBlaQAccessory { ); } - getCurrentDoorState(): CharacteristicValue { + getCurrentDoorState(): + typeof this.platform.characteristic.CurrentDoorState.CLOSING | + typeof this.platform.characteristic.CurrentDoorState.OPENING | + typeof this.platform.characteristic.CurrentDoorState.CLOSED | + typeof this.platform.characteristic.CurrentDoorState.OPEN | + typeof this.platform.characteristic.CurrentDoorState.STOPPED { if(this.preClosing || this.currentOperation === 'CLOSING' || ( this.position !== undefined && this.targetPosition !== undefined && this.targetPosition < this.position )){ @@ -125,11 +143,37 @@ export class BlaQGarageDoorAccessory extends BaseBlaQAccessory { this.updateCurrentDoorState(); } + private getHoldPositionState(): CharacteristicValue { + return [ + this.platform.characteristic.CurrentDoorState.STOPPED, + this.platform.characteristic.CurrentDoorState.CLOSED, + this.platform.characteristic.CurrentDoorState.OPEN, + ].includes(this.getCurrentDoorState()); + } + + private getCurrentPositionState(): CharacteristicValue { + return { + [this.platform.characteristic.CurrentDoorState.STOPPED]: this.platform.characteristic.PositionState.STOPPED, + [this.platform.characteristic.CurrentDoorState.CLOSED]: this.platform.characteristic.PositionState.STOPPED, + [this.platform.characteristic.CurrentDoorState.OPEN]: this.platform.characteristic.PositionState.STOPPED, + [this.platform.characteristic.CurrentDoorState.CLOSING]: this.platform.characteristic.PositionState.DECREASING, + [this.platform.characteristic.CurrentDoorState.OPENING]: this.platform.characteristic.PositionState.INCREASING, + }[this.getCurrentDoorState()]; + } + private updateCurrentDoorState(){ this.garageDoorService.setCharacteristic( this.platform.characteristic.CurrentDoorState, this.getCurrentDoorState(), ); + this.garageDoorService.updateCharacteristic( + this.platform.characteristic.PositionState, + this.getCurrentPositionState(), + ); + this.garageDoorService.updateCharacteristic( + this.platform.characteristic.HoldPosition, + this.getHoldPositionState(), + ); this.garageDoorService.updateCharacteristic( this.platform.characteristic.TargetDoorState, this.getTargetDoorState(), @@ -187,6 +231,13 @@ export class BlaQGarageDoorAccessory extends BaseBlaQAccessory { // throw new Error(`Invalid target door state: ${this.currentOperation}`); } + private async setHoldPositionState(target: CharacteristicValue){ + const shouldHold = target; + if(shouldHold){ + await fetch(`${this.apiBaseURL}/cover/${this.coverType}/stop`, {method: 'POST'}); + } + } + private async setTargetDoorState(target: CharacteristicValue){ let apiTarget: string; if (target === this.platform.characteristic.TargetDoorState.CLOSED) { diff --git a/src/hub.ts b/src/hub.ts index 9bfa4a7..6762d46 100644 --- a/src/hub.ts +++ b/src/hub.ts @@ -160,7 +160,7 @@ export class BlaQHub { private initGarageDoorAccessory({ platform, accessory, friendlyName, serialNumber}: InitAccessoryParams){ this.accessories.push(new BlaQGarageDoorAccessory({ - platform, accessory, friendlyName, serialNumber, apiBaseURL: this.getAPIBaseURL(), + platform, accessory, friendlyName, serialNumber, apiBaseURL: this.getAPIBaseURL(), type: this.pluginConfig.garageDoorType, })); }