4 Commits
Author SHA1 Message Date
dennis 8ce58709d1 0.3.0 2023-02-24 22:05:30 +01:00
dennis 5cce408839 Trigger Timeout handling updated 2023-02-24 22:04:42 +01:00
dennis 1cd3a8fbf6 Provide identifiers for better identification in Home apps 2023-02-24 22:03:58 +01:00
dennis 2b80dee6b7 Fix UUID handling and removal of unused accessories 2023-02-24 22:02:32 +01:00
6 changed files with 42 additions and 9 deletions

No files matched your search

+3 -1
View File
@@ -41,7 +41,9 @@ The configuration allows the user to add multiple **Multi-Tap-Switches**. The fo
| `devices[].resetAfterSwitchOff` | false | | Reset the switch (like after timeout), when it is turned ```OFF```. | | `devices[].resetAfterSwitchOff` | false | | Reset the switch (like after timeout), when it is turned ```OFF```. |
| `devices[].logging` | false | | Logging of switch/trigger actions. | | `devices[].logging` | false | | Logging of switch/trigger actions. |
The parameter ```triggerTimeout``` can be changed in the configuration during runtime. So, this is just the initial value. The parameter ```triggerTimeout``` can be changed in the configuration during runtime. So, this is just the initial value.<br>
> **NOTE:** If the value is out of sync from the configured value (i.e. updated via Home-App), it will not be updated on later configuration changes.
> It must be set back to the configured value first!
The parameter ```numberConfiguredScenes``` just defines how many **programmable** switches are available. The number of The parameter ```numberConfiguredScenes``` just defines how many **programmable** switches are available. The number of
really **used** switches can configured during runtime, between 0 and the configured number. really **used** switches can configured during runtime, between 0 and the configured number.
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "homebridge-multitap-switch", "name": "homebridge-multitap-switch",
"version": "0.2.0", "version": "0.3.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "homebridge-multitap-switch", "name": "homebridge-multitap-switch",
"version": "0.2.0", "version": "0.3.0",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/node": "^16.10.9", "@types/node": "^16.10.9",
+1 -1
View File
@@ -2,7 +2,7 @@
"private": false, "private": false,
"displayName": "Homebridge Multi-Tap-Switch", "displayName": "Homebridge Multi-Tap-Switch",
"name": "homebridge-multi-tap-switch", "name": "homebridge-multi-tap-switch",
"version": "0.2.0", "version": "0.3.0",
"description": "A configurable multi-tap switch for i.e. switching scenes", "description": "A configurable multi-tap switch for i.e. switching scenes",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
+2
View File
@@ -60,6 +60,7 @@ export interface AccessoryState {
numberConfiguredScenes: number; numberConfiguredScenes: number;
triggerTimeout: number; triggerTimeout: number;
//nextSceneToTrigger: number; //nextSceneToTrigger: number;
triggerTimeoutManuallyChanged: boolean;
} }
export function initializeAccessoryState(initConfig: PluginDeviceConfig | AccessoryState): AccessoryState { export function initializeAccessoryState(initConfig: PluginDeviceConfig | AccessoryState): AccessoryState {
@@ -67,5 +68,6 @@ export function initializeAccessoryState(initConfig: PluginDeviceConfig | Access
numberConfiguredScenes: initConfig.numberConfiguredScenes || DEFAULT_NUM_OF_CONFIGURED_SCENES, numberConfiguredScenes: initConfig.numberConfiguredScenes || DEFAULT_NUM_OF_CONFIGURED_SCENES,
triggerTimeout: initConfig.triggerTimeout || DEFAULT_TRIGGER_TIMEOUT, triggerTimeout: initConfig.triggerTimeout || DEFAULT_TRIGGER_TIMEOUT,
//nextSceneToTrigger: 0, //nextSceneToTrigger: 0,
triggerTimeoutManuallyChanged: false,
}; };
} }
+14 -2
View File
@@ -78,13 +78,15 @@ export class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
* @param serial (optional) Provide an additional number (might be obsolete in future releases) * @param serial (optional) Provide an additional number (might be obsolete in future releases)
*/ */
defineUuid(name: string | undefined, serial = 'UNDEF'): string { defineUuid(name: string | undefined, serial = 'UNDEF'): string {
return this.api.hap.uuid.generate(name + '_' + serial); return this.api.hap.uuid.generate(PLATFORM_NAME + '_' + name + '_' + serial);
} }
/** /**
* Discover new and existing accessories * Discover new and existing accessories
*/ */
discoverDevices() { discoverDevices() {
const knownUuids: string[] = [];
const parsedConfig = new PluginConfig(this.config); const parsedConfig = new PluginConfig(this.config);
for (const device of parsedConfig.Devices) { for (const device of parsedConfig.Devices) {
const uuid = this.defineUuid(device.name, '0'); const uuid = this.defineUuid(device.name, '0');
@@ -100,7 +102,7 @@ export class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.: // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
// existingAccessory.context.device = device; // existingAccessory.context.device = device;
// this.api.updatePlatformAccessories([existingAccessory]); // this.api.updatePlatformAccessories([existingAccessory]);
if (existingAccessory.context.config !== device) { if (JSON.stringify(existingAccessory.context.config) !== JSON.stringify(device)) {
this.log.debug('Update Accessory ->', device.name); this.log.debug('Update Accessory ->', device.name);
existingAccessory.context.config = device; existingAccessory.context.config = device;
this.api.updatePlatformAccessories([existingAccessory]); this.api.updatePlatformAccessories([existingAccessory]);
@@ -109,6 +111,8 @@ export class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
// Create the accessory handler for the restored accessory // Create the accessory handler for the restored accessory
// This is imported from `platformAccessory.ts` // This is imported from `platformAccessory.ts`
new DeviceAccessory(this, existingAccessory); new DeviceAccessory(this, existingAccessory);
knownUuids.push(uuid);
} else { } else {
// Accessory does not yet exist, so we need to create it // Accessory does not yet exist, so we need to create it
this.log.info('Add Device ->', device.name, '/', this.log.info('Add Device ->', device.name, '/',
@@ -130,5 +134,13 @@ export class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
} }
} }
// Unregister unused accessories
for (const device of this.accessories) {
if (!knownUuids.find(id => id === device.UUID)) {
this.log.info('Remove unused device ->', device.displayName, '/', device.UUID);
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [device]);
}
}
} }
} }
+20 -3
View File
@@ -49,9 +49,9 @@ export class DeviceAccessory {
*/ */
this.accessory.getService(this.platform.Service.AccessoryInformation)! this.accessory.getService(this.platform.Service.AccessoryInformation)!
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'HB/dtw') .setCharacteristic(this.platform.Characteristic.Manufacturer, 'HB/dtw')
.setCharacteristic(this.platform.Characteristic.Model, 'SceneSwitch') .setCharacteristic(this.platform.Characteristic.Model, 'Multi-Tap-Switch')
.setCharacteristic(this.platform.Characteristic.Version, VERSION) .setCharacteristic(this.platform.Characteristic.Version, VERSION)
.setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.UUID); .setCharacteristic(this.platform.Characteristic.SerialNumber, this.Config.Name());
/** /**
* Input Service / Switch * Input Service / Switch
@@ -81,6 +81,12 @@ export class DeviceAccessory {
.updateValue(this.State.numberConfiguredScenes); .updateValue(this.State.numberConfiguredScenes);
// Register handlers for the TriggerTimeout characteristic & restore previous value // Register handlers for the TriggerTimeout characteristic & restore previous value
if (!this.State.triggerTimeoutManuallyChanged) {
this.State.triggerTimeout = this.Config.TriggerTimeout();
} else {
this.Log.debug('Current Trigger Timeout [' + this.State.triggerTimeout + '] differs from configured value [' +
this.Config.TriggerTimeout() + ']. It won\'t be updated until it\'s equal again.');
}
(this.serviceIn.getCharacteristic(this.platform.Characteristic.TriggerTimeout) (this.serviceIn.getCharacteristic(this.platform.Characteristic.TriggerTimeout)
|| this.serviceIn.addOptionalCharacteristic(this.platform.Characteristic.TriggerTimeout)) || this.serviceIn.addOptionalCharacteristic(this.platform.Characteristic.TriggerTimeout))
.setProps({ .setProps({
@@ -115,7 +121,9 @@ export class DeviceAccessory {
this.serviceOut.addLinkedService(newButton); this.serviceOut.addLinkedService(newButton);
newButton.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent) newButton.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent)
.setProps(this.singleButtonEvents); .setProps(this.singleButtonEvents);
newButton.setCharacteristic(this.platform.Characteristic.ServiceLabelIndex, i); newButton
.setCharacteristic(this.platform.Characteristic.ServiceLabelIndex, i)
.setCharacteristic(this.platform.Characteristic.Name, 'Scene ' + i);
} }
// Push switches to an internal list for later use // Push switches to an internal list for later use
@@ -249,6 +257,15 @@ export class DeviceAccessory {
'Set Trigger Timeout ->', triggerTimeout, '-> Out-of-Range / Value must be greater or equal to 0'); 'Set Trigger Timeout ->', triggerTimeout, '-> Out-of-Range / Value must be greater or equal to 0');
triggerTimeout = 0; triggerTimeout = 0;
} }
this.State.triggerTimeoutManuallyChanged = (this.Config.TriggerTimeout() !== triggerTimeout);
if (!this.State.triggerTimeoutManuallyChanged) {
this.Log.debug('Trigger Timeout in sync with config.');
} else {
this.Log.warn('Trigger Timeout not in sync with config value [' + this.Config.TriggerTimeout() + '].');
this.Log.warn('It will not be updated by config changes, until it is in sync again!');
}
this.State.triggerTimeout = triggerTimeout; this.State.triggerTimeout = triggerTimeout;
} }