Skip to content

Commit

Permalink
Added device-specific config. Added config options for HmIP-DLD.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc Sowen committed Dec 21, 2021
1 parent ebf9912 commit 1bc9bef
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 125 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## 0.7.1 (2021-12-21)

### Improvements

- **General**: Added per-device config. All devices can be hidden by setting config.json option "hidden": true. See
[GitHub Wiki](https://github.com/marcsowen/homebridge-homematicip/wiki) for details.
- **HmIP-DLD**: New option "openLatch". When set to true, opening the lock will open the door completely by pulling
the door latch.

### Bugfix

- **HmIP-DLD**: Lock target state was not always updated correctly displaying an opening/closing animation in Home app.

## 0.7.0 (2021-12-18)

### New devices
Expand Down
198 changes: 99 additions & 99 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "homebridge-homematicip",
"version": "0.7.0",
"version": "0.7.1",
"description": "Homematic IP plugin for homebridge",
"license": "Apache-2.0",
"author": "Marc Sowen <[email protected]>",
Expand Down Expand Up @@ -30,10 +30,10 @@
"homebridge": ">=1.0.0"
},
"devDependencies": {
"@types/node": "^17.0.0",
"@types/node": "^17.0.2",
"@types/ws": "^8.2.2",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
"@typescript-eslint/eslint-plugin": "^5.8.0",
"@typescript-eslint/parser": "^5.8.0",
"abort-controller": "^3.0.0",
"eslint": "^8.5.0",
"homebridge": "^1.3.8",
Expand All @@ -48,6 +48,6 @@
"moment": "^2.29.1",
"node-fetch": "3.0.0-beta.9",
"semver": "^7.3.5",
"ws": "^8.3.0"
"ws": "^8.4.0"
}
}
31 changes: 25 additions & 6 deletions src/HmIPPlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,21 @@ export class HmIPPlatform implements DynamicPlatformPlugin {
this.updateAccessory(id, device);
}

this.securitySystem = this.createSecuritySystem(hmIPState.home);

// find cached but now removed accessories and unregister them
const accessoriesToBeRemoved: PlatformAccessory[] = [];

if (this.securitySystem.hidden) {
const id = hmIPState.home.id + '_security';
const uuid = this.api.hap.uuid.generate(id);
const cachedAccessory = this.getAccessory(uuid);
if (cachedAccessory !== undefined) {
this.log.info('Removing home security system');
accessoriesToBeRemoved.push(cachedAccessory);
}
}

for (const id in hmIPState.devices) {
if (!this.deviceMap.has(id)) {
const uuid = this.api.hap.uuid.generate(id);
Expand All @@ -172,8 +185,6 @@ export class HmIPPlatform implements DynamicPlatformPlugin {
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, accessoriesToBeRemoved);
}

this.securitySystem = this.createSecuritySystem(hmIPState.home);

// Start websocket immediately and register handlers
await this.connector.connectWs(data => {
const stateChange = <HmIPStateChange>JSON.parse(data.toString());
Expand Down Expand Up @@ -307,8 +318,11 @@ export class HmIPPlatform implements DynamicPlatformPlugin {
this.log.warn(`Device not implemented: ${device.modelType} - ${device.label} via type ${device.type}`);
return;
}
this.deviceMap.set(id, homebridgeDevice);
hmIPAccessory.register();

if (!homebridgeDevice.hidden) {
this.deviceMap.set(id, homebridgeDevice);
hmIPAccessory.register();
}
}

private createAccessory(uuid: string, displayName: string, deviceContext: unknown): HmIPAccessory {
Expand All @@ -333,10 +347,15 @@ export class HmIPPlatform implements DynamicPlatformPlugin {
}

private createSecuritySystem(home: HmIPHome): HmIPSecuritySystem {
const uuid = this.api.hap.uuid.generate(home.id + '_security');
const id = home.id + '_security';
const uuid = this.api.hap.uuid.generate(id);
const hmIPAccessory = this.createAccessory(uuid, 'Home Security System', home);
const securitySystem = new HmIPSecuritySystem(this, hmIPAccessory.accessory);
hmIPAccessory.register();

if (!securitySystem.hidden) {
this.deviceMap.set(id, securitySystem);
hmIPAccessory.register();
}

return securitySystem;
}
Expand Down
3 changes: 3 additions & 0 deletions src/HmIPSecuritySystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class SecuritySystemTarget {
export class HmIPSecuritySystem {
private service: Service;

public hidden = false;
private activationInProgress = false;
private intrusionAlarmActive = false;
private safetyAlarmActive = false;
Expand All @@ -50,6 +51,8 @@ export class HmIPSecuritySystem {
protected platform: HmIPPlatform,
protected accessory: PlatformAccessory,
) {
this.hidden = platform.config['devices']?.['HOME_SECURITY_SYSTEM']?.['hide'] === true;

this.platform.log.debug('Created security system');
const home = <HmIPHome>accessory.context.device;

Expand Down
42 changes: 28 additions & 14 deletions src/devices/HmIPDoorLockDrive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,18 @@ export class HmIPDoorLockDrive extends HmIPGenericDevice implements Updateable {
private lockState: LockState = LockState.UNLOCKED;
private motorState: MotorState = MotorState.STOPPED;
private targetLockState = this.platform.Characteristic.LockTargetState.UNSECURED;
private openLatch = false;
private pin;

constructor(
platform: HmIPPlatform,
accessory: PlatformAccessory,
) {
super(platform, accessory);

this.openLatch = this.accessoryConfig?.['openLatch'] === true;
this.pin = this.accessoryConfig?.['pin'];

this.platform.log.debug(`Created door lock drive ${accessory.context.device.label}`);
this.service = this.accessory.getService(this.platform.Service.LockMechanism)
|| this.accessory.addService(this.platform.Service.LockMechanism);
Expand All @@ -80,11 +85,11 @@ export class HmIPDoorLockDrive extends HmIPGenericDevice implements Updateable {

async handleLockTargetStateSet(value: CharacteristicValue) {
this.targetLockState = <number>value;
this.platform.log.info('Setting door lock drive %s to %s', this.accessory.displayName, this.getLockTargetState(value));
this.platform.log.info('Setting door lock drive %s to %s', this.accessory.displayName, this.getLockTargetStateString(value));
const body = {
channelIndex: 1,
deviceId: this.accessory.context.device.id,
authorizationPin: '',
authorizationPin: this.pin !== undefined ? this.pin : '',
targetLockState: this.getHmIPTargetLockState(value),
};
await this.platform.connector.apiCall('device/control/setLockState', body);
Expand All @@ -101,20 +106,22 @@ export class HmIPDoorLockDrive extends HmIPGenericDevice implements Updateable {
if (doorLockChannel.lockState !== null && doorLockChannel.lockState !== this.lockState) {
this.lockState = doorLockChannel.lockState;
this.platform.log.info('Door lock drive lock state of %s changed to %s', this.accessory.displayName, this.lockState);
this.updateHmKitLockTargetState();
this.service.updateCharacteristic(this.platform.Characteristic.LockCurrentState, this.getHmKitLockCurrentState(this.lockState));
this.service.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.getHmKitLockTargetState());
this.service.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.targetLockState);
}

if (doorLockChannel.motorState !== null && doorLockChannel.motorState !== this.motorState) {
this.motorState = doorLockChannel.motorState;
this.platform.log.info('Door lock drive motor state of %s changed to %s', this.accessory.displayName, this.motorState);
this.service.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.getHmKitLockTargetState());
this.updateHmKitLockTargetState();
this.service.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.targetLockState);
}
}
}
}

private getLockTargetState(lockTargetState: CharacteristicValue): string {
private getLockTargetStateString(lockTargetState: CharacteristicValue): string {
switch (lockTargetState) {
case this.platform.Characteristic.LockTargetState.UNSECURED:
return 'UNSECURED';
Expand All @@ -128,7 +135,11 @@ export class HmIPDoorLockDrive extends HmIPGenericDevice implements Updateable {
private getHmIPTargetLockState(lockTargetState: CharacteristicValue): string {
switch (lockTargetState) {
case this.platform.Characteristic.LockTargetState.UNSECURED:
return LockState.UNLOCKED;
if (this.openLatch) {
return LockState.OPEN;
} else {
return LockState.UNLOCKED;
}
case this.platform.Characteristic.LockTargetState.SECURED:
return LockState.LOCKED;
default:
Expand All @@ -149,22 +160,25 @@ export class HmIPDoorLockDrive extends HmIPGenericDevice implements Updateable {
}
}

private getHmKitLockTargetState(): number {
private updateHmKitLockTargetState() {
switch (this.lockState) {
case LockState.LOCKED:
if (this.motorState === MotorState.STOPPED) {
return this.platform.Characteristic.LockTargetState.SECURED;
this.targetLockState = this.platform.Characteristic.LockTargetState.SECURED;
} else {
this.targetLockState = this.platform.Characteristic.LockTargetState.UNSECURED;
}

return this.platform.Characteristic.LockTargetState.UNSECURED;
break;
case LockState.UNLOCKED:
if (this.motorState === MotorState.CLOSING) {
return this.platform.Characteristic.LockTargetState.SECURED;
this.targetLockState = this.platform.Characteristic.LockTargetState.SECURED;
} else {
this.targetLockState = this.platform.Characteristic.LockTargetState.UNSECURED;
}

return this.platform.Characteristic.LockTargetState.UNSECURED;
break;
case LockState.OPEN:
return this.platform.Characteristic.LockTargetState.UNSECURED;
this.targetLockState = this.platform.Characteristic.LockTargetState.UNSECURED;
break;
}
}
}
6 changes: 6 additions & 0 deletions src/devices/HmIPGenericDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,25 @@ interface DeviceBaseChannel {
*/
export abstract class HmIPGenericDevice {

public hidden = false;
protected unreach = false;
protected lowBat = false;
protected rssiDeviceValue = 0;
protected rssiPeerValue = 0;
protected dutyCycle = false;
protected configPending = false;
protected featureSabotage = false;
protected accessoryConfig;
private readonly batteryService: Service | undefined;

protected constructor(
protected readonly platform: HmIPPlatform,
public readonly accessory: PlatformAccessory,
) {

this.accessoryConfig = platform.config['devices']?.[accessory.context.device.id];
this.hidden = this.accessoryConfig?.['hide'] === true;

this.accessory.getService(this.platform.Service.AccessoryInformation)!
.setCharacteristic(this.platform.Characteristic.Manufacturer, accessory.context.device.oem)
.setCharacteristic(this.platform.Characteristic.Model, accessory.context.device.modelType)
Expand Down
2 changes: 1 addition & 1 deletion src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ export const PLUGIN_NAME = 'homebridge-homematicip';
/**
* Version to be used in protocol communication
*/
export const PLUGIN_VERSION = '0.7.0';
export const PLUGIN_VERSION = '0.7.1';

0 comments on commit 1bc9bef

Please sign in to comment.