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
23 changed files with 3856 additions and 3923 deletions

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
{
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended" // uses the recommended rules from the @typescript-eslint/eslint-plugin
],
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"ignorePatterns": [
"dist"
],
"rules": {
"quotes": ["warn", "single"],
"indent": ["warn", 2, { "SwitchCase": 1 }],
"semi": ["off"],
"comma-dangle": ["warn", "always-multiline"],
"dot-notation": "off",
"eqeqeq": "warn",
"curly": ["warn", "all"],
"brace-style": ["warn"],
"prefer-arrow-callback": ["warn"],
"max-len": ["warn", 140],
"no-console": ["warn"], // use the provided Homebridge log method instead
"no-non-null-assertion": ["off"],
"comma-spacing": ["error"],
"no-multi-spaces": ["warn", { "ignoreEOLComments": true }],
"no-trailing-spaces": ["warn"],
"lines-between-class-members": ["warn", "always", {"exceptAfterSingleLine": true}],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/semi": ["warn"],
"@typescript-eslint/member-delimiter-style": ["warn"]
}
}
+1 -1
View File
@@ -41,4 +41,4 @@ Show your Homebridge config.json here, remove any sensitive information.
* **NPM Version**: <!-- npm -v --> * **NPM Version**: <!-- npm -v -->
* **Operating System**: <!-- Raspbian / Ubuntu / Debian / Windows / macOS / Docker / hb-service --> * **Operating System**: <!-- Raspbian / Ubuntu / Debian / Windows / macOS / Docker / hb-service -->
<!-- Click the "Preview" tab before you submit to ensure the formatting is correct. --> <!-- Click the "Preview" tab before you submit to ensure the formatting is correct. -->
+2 -1
View File
@@ -19,4 +19,5 @@ assignees: ''
**Additional context:** **Additional context:**
<!-- Add any other context or screenshots about the feature request here. --> <!-- Add any other context or screenshots about the feature request here. -->
<!-- Click the "Preview" tab before you submit to ensure the formatting is correct. -->
<!-- Click the "Preview" tab before you submit to ensure the formatting is correct. -->
+1 -1
View File
@@ -35,4 +35,4 @@ Show your Homebridge config.json here, remove any sensitive information.
* **NPM Version**: <!-- npm -v --> * **NPM Version**: <!-- npm -v -->
* **Operating System**: <!-- Raspbian / Ubuntu / Debian / Windows / macOS / Docker / hb-service --> * **Operating System**: <!-- Raspbian / Ubuntu / Debian / Windows / macOS / Docker / hb-service -->
<!-- Click the "Preview" tab before you submit to ensure the formatting is correct. --> <!-- Click the "Preview" tab before you submit to ensure the formatting is correct. -->
+7 -13
View File
@@ -7,15 +7,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
node-version: [20.x, 22.x, 24.x] # the Node.js versions to build on
node-version: [12.x, 13.x, 14.x, 15.x, 16.x]
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6 uses: actions/setup-node@v2
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
@@ -27,11 +27,5 @@ jobs:
- name: Build the project - name: Build the project
run: npm run build run: npm run build
env:
- name: List, audit, fix outdated dependencies and build again CI: true
run: |
npm list --outdated
npm audit || true # ignore failures
npm audit fix || true
npm list --outdated
npm run build
+11 -17
View File
@@ -1,24 +1,18 @@
name: Publish Package name: Publish Package to npmjs
on: on:
push: release:
tags: types: [created]
- 'v*'
permissions:
id-token: write # Required for OIDC
contents: read
jobs: jobs:
publish: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: '24' node-version: '16.x'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- run: npm ci - run: npm ci
- run: npm run build --if-present - run: npm publish
- run: npm publish env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+1 -3
View File
@@ -10,7 +10,7 @@ src
.github .github
# eslint # eslint
eslint.config.js .eslintrc
# typescript # typescript
tsconfig.json tsconfig.json
@@ -135,5 +135,3 @@ web_modules/
.yarn/unplugged .yarn/unplugged
.yarn/build-state.yml .yarn/build-state.yml
.pnp.* .pnp.*
test/
+2 -4
View File
@@ -1,10 +1,8 @@
{ {
"files.eol": "\n", "files.eol": "\n",
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit" "source.fixAll.eslint": true
}, },
"editor.rulers": [ "editor.rulers": [ 140 ],
140
],
"eslint.enable": true "eslint.enable": true
} }
+17 -20
View File
@@ -1,5 +1,5 @@
<p> <p align="center">
<img src="https://github.com/homebridge/branding/blob/latest/logos/homebridge-color-round-stylized.png" width="150" alt="Homebridge"> <img src="https://github.com/homebridge/branding/raw/master/logos/homebridge-wordmark-logo-vertical.png" width="150" alt="Homebridge">
</p> </p>
# Homebridge Multi-Tap-Switch # Homebridge Multi-Tap-Switch
@@ -31,22 +31,25 @@ or manually by following these instructions:
The configuration allows the user to add multiple **Multi-Tap-Switches**. The following parameters are available: The configuration allows the user to add multiple **Multi-Tap-Switches**. The following parameters are available:
| Option | Default Value | Characteristic (runtime configuration) | Description | | Option | Default Value | Characteristic (runtime configuration) | Description |
|-------------------------------------|----------------|----------------------------------------|-------------------------------------------------------------------------------------------| |------------------------------------|----------------|----------------------------------------|-------------------------------------------------------------------------------------------|
| `name` | MultiTapSwitch | | Name of the Platform Accessory (primarily shown in logs) | | `name` | MultiTapSwitch | | Name of the Platform Accessory (primarily shown in logs) |
| `devices[]` | | | Array of configured devices | | `devices[]` | | | Array of configured devices |
| `devices[].name` | | | Name of the switch | | `devices[].name` | | | Name of the switch |
| `devices[] .numberConfiguredScenes` | 5 | `Configured Scenes` | Number of **stateless** switches (cannot be changed during runtime) | | `devices[].numberConfiguredScenes` | 5 | `Configured Scenes` | Number of **stateless** switches (cannot be changed during runtime) |
| `devices[] .triggerTimeout` | 10 | `Trigger Timeout` | Seconds, after which the switch is reset (starting from the first **programmable** switch | | `devices[].triggerTimeout` | 10 | `Trigger Timeout` | Seconds, after which the switch is reset (starting from the first **programmable** switch |
| `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 (currently, there is no limit). 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.
> **NOTE:** Additional parameters (also called **Characteristics**) can only be configured via 3rd-party HomeKit apps, but not in the basic Home App! > **NOTE:** Additional parameters (also called **Characteristics**) can only be configured via 3rd-party HomeKit apps (i.e.
> Home+, Controller for HomeKit, etc.), but in the basic Home App!
So, an example **platform** plugin config will look as follows: So, an example **platform** plugin config will look as follows:
@@ -65,9 +68,3 @@ So, an example **platform** plugin config will look as follows:
] ]
} }
```` ````
## Contribution
Contributions are always welcome. You can also use the code for own projects and adapt it to your specific needs.
If you find any bugs or have ideas for optimizations or new features, feel free.
-35
View File
@@ -1,35 +0,0 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
{
ignores: ['dist/**'],
},
{
rules: {
'quotes': ['error', 'single'],
'indent': ['error', 2, { 'SwitchCase': 0 }],
'linebreak-style': ['error', 'unix'],
'semi': ['error', 'always'],
'comma-dangle': ['error', 'always-multiline'],
'dot-notation': 'error',
'eqeqeq': ['error', 'smart'],
'curly': ['error', 'all'],
'brace-style': ['error'],
'prefer-arrow-callback': 'warn',
'max-len': ['warn', 160],
'object-curly-spacing': ['error', 'always'],
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': ['error', { 'classes': false, 'enums': false }],
'@typescript-eslint/no-unused-vars': ['error', { 'caughtErrors': 'none' }],
},
},
{
languageOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
},
eslint.configs.recommended,
...tseslint.configs.recommended,
);
+3663 -3606
View File
File diff suppressed because it is too large. Load diff
+12 -15
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.4.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": {
@@ -13,8 +13,8 @@
"url": "https://github.com/dtwardow/homebridge-multi-tap-switch/issues" "url": "https://github.com/dtwardow/homebridge-multi-tap-switch/issues"
}, },
"engines": { "engines": {
"node": "^20.18.0 || ^22.10.0 || ^24.0.0", "node": ">=14.18.1",
"homebridge": "^1.8.0 || ^2.0.0-beta.0" "homebridge": ">=1.3.5"
}, },
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
@@ -26,19 +26,16 @@
"keywords": [ "keywords": [
"homebridge-plugin" "homebridge-plugin"
], ],
"dependencies": {
"homebridge-lib": "^7.1.12"
},
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.1", "@types/node": "^16.10.9",
"@types/node": "^24.10.1", "@typescript-eslint/eslint-plugin": "^5.0.0",
"eslint": "^9.39.1", "@typescript-eslint/parser": "^5.0.0",
"homebridge": "^2.0.0-beta.55", "eslint": "^8.0.1",
"nodemon": "^3.1.11", "homebridge": "^1.3.5",
"rimraf": "^6.1.0", "nodemon": "^2.0.13",
"ts-node": "^10.9.2", "rimraf": "^3.0.2",
"typescript": "^5.9.3", "ts-node": "^10.3.0",
"typescript-eslint": "^8.46.4" "typescript": "^4.4.4"
}, },
"homepage": "https://github.com/dtwardow/homebridge-multi-tap-switch#readme", "homepage": "https://github.com/dtwardow/homebridge-multi-tap-switch#readme",
"author": "Dennis Twardowsky <twardowsky@gmail.com>" "author": "Dennis Twardowsky <twardowsky@gmail.com>"
+3 -1
View File
@@ -1,4 +1,4 @@
import { PlatformConfig } from 'homebridge'; import {PlatformConfig} from 'homebridge';
const DEFAULT_NUM_OF_CONFIGURED_SCENES = 5; const DEFAULT_NUM_OF_CONFIGURED_SCENES = 5;
const DEFAULT_TRIGGER_TIMEOUT = 10; const DEFAULT_TRIGGER_TIMEOUT = 10;
@@ -59,6 +59,7 @@ export class DeviceConfig {
export interface AccessoryState { export interface AccessoryState {
numberConfiguredScenes: number; numberConfiguredScenes: number;
triggerTimeout: number; triggerTimeout: number;
//nextSceneToTrigger: number;
triggerTimeoutManuallyChanged: boolean; triggerTimeoutManuallyChanged: boolean;
} }
@@ -66,6 +67,7 @@ export function initializeAccessoryState(initConfig: PluginDeviceConfig | Access
return { return {
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,
triggerTimeoutManuallyChanged: false, triggerTimeoutManuallyChanged: false,
}; };
} }
+1 -1
View File
@@ -1,7 +1,7 @@
import { API } from 'homebridge'; import { API } from 'homebridge';
import { PLATFORM_NAME } from './settings'; import { PLATFORM_NAME } from './settings';
import MultiTapSwitchPlatform from './platform'; import { MultiTapSwitchPlatform } from './platform';
/** /**
* This method registers the platform with Homebridge * This method registers the platform with Homebridge
+28 -10
View File
@@ -4,14 +4,24 @@ import { PLATFORM_NAME, PLUGIN_NAME } from './settings';
import { DeviceAccessory } from './platformAccessory'; import { DeviceAccessory } from './platformAccessory';
// Necessary definitions for custom characteristics! // Necessary definitions for custom characteristics!
import { initializeAccessoryState, PluginConfig } from './config'; import ConfiguredScenes from './types/characteristicConfiguredScenes';
let IConfiguredScenes;
import {initializeAccessoryState, PluginConfig} from './config';
let ITriggerTimeout;
import TriggerTimeout from './types/characteristicTimeout';
/** /**
* HomebridgePlatform * HomebridgePlatform
*/ */
class MultiTapSwitchPlatform implements DynamicPlatformPlugin { export class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
public readonly Service: typeof Service; public readonly Service: typeof Service = this.api.hap.Service;
public readonly Characteristic: typeof Characteristic; public readonly Characteristic:
typeof Characteristic &
typeof IConfiguredScenes &
typeof ITriggerTimeout;
private readonly CharacteristicConfiguredScenes;
private readonly CharacteristicTriggerTimeout;
// Track restored cached accessories // Track restored cached accessories
public readonly accessories: PlatformAccessory[] = []; public readonly accessories: PlatformAccessory[] = [];
@@ -30,15 +40,25 @@ class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
public readonly api: API, public readonly api: API,
) { ) {
this.Config = new PluginConfig(this.config); this.Config = new PluginConfig(this.config);
this.Service = api.hap.Service;
this.Characteristic = api.hap.Characteristic;
this.log.debug('Finished initializing platform:', this.Config.Name); this.log.debug('Finished initializing platform:', this.Config.Name);
this.CharacteristicConfiguredScenes = ConfiguredScenes(this.api);
IConfiguredScenes = this.CharacteristicConfiguredScenes;
this.CharacteristicTriggerTimeout = TriggerTimeout(this.api);
ITriggerTimeout = this.CharacteristicTriggerTimeout;
this.api.on('didFinishLaunching', () => { this.api.on('didFinishLaunching', () => {
log.debug('Discover/Register Devices ...'); log.debug('Discover/Register Devices ...');
this.discoverDevices(); this.discoverDevices();
}); });
this.Characteristic = Object.defineProperty(this.api.hap.Characteristic,
'ConfiguredScenes',
{value: this.CharacteristicConfiguredScenes});
this.Characteristic = Object.defineProperty(this.api.hap.Characteristic,
'TriggerTimeout',
{value: this.CharacteristicTriggerTimeout});
} }
/** /**
@@ -90,7 +110,7 @@ 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, this.api, existingAccessory); new DeviceAccessory(this, existingAccessory);
knownUuids.push(uuid); knownUuids.push(uuid);
} else { } else {
@@ -108,7 +128,7 @@ class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
// Create the accessory handler for the new accessory // Create the accessory handler for the new accessory
// This is imported from `platformAccessory.ts` // This is imported from `platformAccessory.ts`
new DeviceAccessory(this, this.api, accessory); new DeviceAccessory(this, accessory);
// link the accessory to your platform // link the accessory to your platform
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
@@ -124,5 +144,3 @@ class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
} }
} }
} }
export default MultiTapSwitchPlatform;
+18 -67
View File
@@ -1,11 +1,8 @@
import { CharacteristicValue, PlatformAccessory, Service, API } from 'homebridge'; import {CharacteristicValue, PlatformAccessory, Service} from 'homebridge';
import MultiTapSwitchPlatform from './platform'; import {MultiTapSwitchPlatform} from './platform';
import { AccessoryState, DeviceConfig } from './config'; import {AccessoryState, DeviceConfig} from './config';
import { Logging } from './helper/logger'; import {Logging} from './helper/logger';
import { VERSION } from './settings'; import {VERSION} from './settings';
import { attachCharacteristic_ConfiguredScenes } from './types/characteristicConfiguredScenes';
import { attachCharacteristic_TriggerTimeout } from './types/characteristicTimeout';
import { attachCharacteristic_CurrentScene } from './types/characteristicCurrentScene';
/** /**
* Platform Accessory * Platform Accessory
@@ -14,37 +11,33 @@ export class DeviceAccessory {
private serviceIn: Service; private serviceIn: Service;
private serviceOut: Service; private serviceOut: Service;
private readonly singleButtonEvents; private readonly singleButtonEvents = {
minValue: this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
maxValue: this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
validValues: [
this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
],
};
private readonly State: AccessoryState; private readonly State: AccessoryState;
private readonly Config: DeviceConfig; private readonly Config: DeviceConfig;
private readonly TriggerButtons: Service[] = []; private readonly TriggerButtons: Service[] = [];
private SwitchResetTimer: NodeJS.Timeout | undefined; private SwitchResetTimer: NodeJS.Timeout | undefined;
private SwitchOn: boolean = false; private SwitchOn = false;
private NextItemToTrigger: number = 0; private NextItemToTrigger = 0;
private Log: Logging; private Log: Logging;
/** /**
* Construct the accessory services * Construct the accessory services
* @param platform Parent Homebridge platform * @param platform Parent Homebridge platform
* @param api Parent platform API
* @param accessory Accessory to which these services will be attached * @param accessory Accessory to which these services will be attached
*/ */
constructor( constructor(
private readonly platform: MultiTapSwitchPlatform, private readonly platform: MultiTapSwitchPlatform,
private readonly api: API,
private readonly accessory: PlatformAccessory, private readonly accessory: PlatformAccessory,
) { ) {
this.singleButtonEvents = {
minValue: this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
maxValue: this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
validValues: [
this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
],
};
this.Config = new DeviceConfig(accessory.context.config); this.Config = new DeviceConfig(accessory.context.config);
this.State = this.accessory.context.persistent; this.State = this.accessory.context.persistent;
@@ -76,7 +69,8 @@ export class DeviceAccessory {
if (this.State.numberConfiguredScenes > this.Config.NumOfScenes()) { if (this.State.numberConfiguredScenes > this.Config.NumOfScenes()) {
this.State.numberConfiguredScenes = this.Config.NumOfScenes(); this.State.numberConfiguredScenes = this.Config.NumOfScenes();
} }
attachCharacteristic_ConfiguredScenes(this.serviceIn, this.api) (this.serviceIn.getCharacteristic(this.platform.Characteristic.ConfiguredScenes)
|| this.serviceIn.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredScenes))
.setProps({ .setProps({
'minValue': 1, 'minValue': 1,
'maxValue': this.Config.NumOfScenes(), 'maxValue': this.Config.NumOfScenes(),
@@ -93,7 +87,8 @@ export class DeviceAccessory {
this.Log.debug('Current Trigger Timeout [' + this.State.triggerTimeout + '] differs from configured value [' + 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.Config.TriggerTimeout() + ']. It won\'t be updated until it\'s equal again.');
} }
attachCharacteristic_TriggerTimeout(this.serviceIn, this.api) (this.serviceIn.getCharacteristic(this.platform.Characteristic.TriggerTimeout)
|| this.serviceIn.addOptionalCharacteristic(this.platform.Characteristic.TriggerTimeout))
.setProps({ .setProps({
'minValue': 0, 'minValue': 0,
'maxValue': 30, 'maxValue': 30,
@@ -103,17 +98,6 @@ export class DeviceAccessory {
.onGet(this.getTriggerTimeout.bind(this)) .onGet(this.getTriggerTimeout.bind(this))
.updateValue(this.State.triggerTimeout); .updateValue(this.State.triggerTimeout);
// Register handlers for the CurrentScene characteristic & restore previous value
attachCharacteristic_CurrentScene(this.serviceIn, this.api)
.setProps({
'minValue': 1,
'maxValue': this.Config.NumOfScenes(),
'minStep': 1,
})
.onSet(this.setCurrentScene.bind(this))
.onGet(this.getCurrentScene.bind(this))
.updateValue(this.NextItemToTrigger);
// Set the service name, this is what is displayed as the default name on the Home app // Set the service name, this is what is displayed as the default name on the Home app
this.serviceIn.setCharacteristic(this.platform.Characteristic.Name, this.Config.Name()); this.serviceIn.setCharacteristic(this.platform.Characteristic.Name, this.Config.Name());
@@ -293,37 +277,4 @@ export class DeviceAccessory {
this.Log.debug('Get Trigger Timeout ->', triggerTimeout); this.Log.debug('Get Trigger Timeout ->', triggerTimeout);
return triggerTimeout; return triggerTimeout;
} }
/**
* Set the number of active switches.
* The final value is limited to the maximum configured number of programmable switches.
* @param value Number of active switches
*/
async setCurrentScene(value: CharacteristicValue) {
let currentScene = value as number;
if ((currentScene > 0) && (currentScene <= this.Config.NumOfScenes())) {
this.Log.log('Set current active scene ->', currentScene);
} else {
this.Log.warn(
'Set current scene ->', currentScene, '-> Out-of-Range / Value must be between 1 and', this.Config.NumOfScenes());
if (currentScene > this.Config.NumOfScenes()) {
currentScene = this.Config.NumOfScenes();
} else {
currentScene = 1;
}
}
// value must be corrected by one, because it's used as array index
this.NextItemToTrigger = currentScene - 1;
}
/**
* Report number of active switches back to HomeKit (for visualization)
*/
async getCurrentScene(): Promise<CharacteristicValue> {
const currentScene = this.NextItemToTrigger + 1;
this.Log.debug('Get Number of current scene ->', currentScene);
return currentScene;
}
} }
+2 -1
View File
@@ -1,4 +1,5 @@
import package_config from '../package.json'; // eslint-disable-next-line @typescript-eslint/no-var-requires
const package_config = require('../package.json');
/** /**
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json * This is the name of the platform that users will use to register the plugin in the Homebridge config.json
+19 -20
View File
@@ -1,23 +1,22 @@
import { API, Characteristic, Formats, Perms, Service } from 'homebridge'; import { Formats, Perms } from 'homebridge';
const DISPLAY_NAME = 'Configured Scenes'; export = (homebridge) => {
const UUID = 'A8E3F4DF-5E5D-6A7F-8FA7-A22FA5AE9F53'; const CustomCharacteristic = homebridge.hap.Characteristic;
const characteristicUUID = 'A8E3F4DF-5E5D-6A7F-8FA7-A22FA5AE9F53';
export function attachCharacteristic_ConfiguredScenes(target: Service, api: API): Characteristic { return class ConfiguredScenes extends CustomCharacteristic {
let result: Characteristic; public static readonly UUID: string = characteristicUUID;
if (target.testCharacteristic(DISPLAY_NAME)) { constructor() {
result = target.getCharacteristic(DISPLAY_NAME)!; // Already tested it exists super('Configured Scenes', ConfiguredScenes.UUID, {
} else { format: Formats.UINT8,
result = target.addCharacteristic(new api.hap.Characteristic(DISPLAY_NAME, UUID, { //unit: '',
format: Formats.UINT8, minValue: 0,
//unit: '', maxValue: 0,
minValue: 0, minStep: 1,
maxValue: 0, perms: [Perms.PAIRED_WRITE, Perms.PAIRED_READ, Perms.NOTIFY],
minStep: 1, });
perms: [Perms.PAIRED_WRITE, Perms.PAIRED_READ, Perms.NOTIFY], this.value = this.getDefaultValue();
})); }
} };
};
return result;
}
-23
View File
@@ -1,23 +0,0 @@
import { API, Characteristic, Formats, Perms, Service } from 'homebridge';
const DISPLAY_NAME = 'Current Scene';
const UUID = '290E9D33-0EFC-4640-891E-CC25AAD740EA';
export function attachCharacteristic_CurrentScene(target: Service, api: API): Characteristic {
let result: Characteristic;
if (target.testCharacteristic(DISPLAY_NAME)) {
result = target.getCharacteristic(DISPLAY_NAME)!; // Already tested it exists
} else {
result = target.addCharacteristic(new api.hap.Characteristic(DISPLAY_NAME, UUID, {
format: Formats.UINT8,
//unit: '',
minValue: 0,
maxValue: 0,
minStep: 1,
perms: [Perms.PAIRED_WRITE, Perms.PAIRED_READ, Perms.NOTIFY],
}));
}
return result;
}
+19 -20
View File
@@ -1,23 +1,22 @@
import { API, Characteristic, Formats, Perms, Service } from 'homebridge'; import { Formats, Perms } from 'homebridge';
const DISPLAY_NAME = 'Trigger Timeout'; export = (homebridge) => {
const UUID = 'E2C19A02-1D2F-F592-A2BF-BF920014FB18'; const CustomCharacteristic = homebridge.hap.Characteristic;
const characteristicUUID = 'E2C19A02-1D2F-F592-A2BF-BF920014FB18';
export function attachCharacteristic_TriggerTimeout(target: Service, api: API): Characteristic { return class TriggerTimeout extends CustomCharacteristic {
let result: Characteristic; public static readonly UUID: string = characteristicUUID;
if (target.testCharacteristic(DISPLAY_NAME)) { constructor() {
result = target.getCharacteristic(DISPLAY_NAME)!; // Already tested it exists super('Trigger Timeout', TriggerTimeout.UUID, {
} else { format: Formats.UINT16,
result = target.addCharacteristic(new api.hap.Characteristic(DISPLAY_NAME, UUID, { //unit: '',
format: Formats.UINT16, minValue: 0,
//unit: '', maxValue: 60,
minValue: 0, minStep: 1,
maxValue: 60, perms: [Perms.PAIRED_WRITE, Perms.PAIRED_READ, Perms.NOTIFY],
minStep: 1, });
perms: [Perms.PAIRED_WRITE, Perms.PAIRED_READ, Perms.NOTIFY], this.value = this.getDefaultValue();
})); }
} };
};
return result;
}
-10
View File
@@ -1,10 +0,0 @@
[
{
"id": 1,
"username": "test",
"name": "test",
"hashedPassword": "df121e72b850a058bd68f3d05b1f94dc985821a3885b5da38e263654f29843f98bb6d8e594f6042ff871a424602a9bff50dffa97f258bdc1dca4c79e87bac20c",
"salt": "64085e70da64670349f042d4c3d3cac75b20233ffeb71db68399973f60da077d",
"admin": true
}
]
-42
View File
@@ -1,42 +0,0 @@
{
"bridge": {
"name": "HomebridgeTest",
"username": "CC:22:3D:E3:CE:30",
"manufacturer": "homebridge.io",
"model": "homebridge",
"port": 51826,
"pin": "031-45-154"
},
"description": "This is an example configuration file with one fake accessory and one fake platform. You can use this as a template for creating your own configuration file containing devices you actually own.",
"ports": {
"start": 52100,
"end": 52150,
"comment": "This section is used to control the range of ports that separate accessory (like camera or television) should be bind to."
},
"accessories": [
],
"platforms": [
{
"platform" : "MultiTapSwitch",
"name" : "MTS",
"devices": [
{
"name": "MTS1",
"numberConfiguredScenes": 5,
"triggerTimeout": 10,
"resetAfterSwitchOff": false,
"logging": true
},
{
"name": "MTS2",
"numberConfiguredScenes": 5,
"triggerTimeout": 10,
"resetAfterSwitchOff": false,
"logging": true
}
]
}
]
}
+11 -12
View File
@@ -1,24 +1,23 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2022", "target": "ES2018", // ~node10
"module": "commonjs",
"lib": [ "lib": [
"DOM", "es2015",
"ES2022" "es2016",
"es2017",
"es2018"
], ],
"rootDir": "src",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"declaration": true, "declaration": true,
"outDir": "dist", "declarationMap": true,
"sourceMap": true, "sourceMap": true,
"allowSyntheticDefaultImports": true, "outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true, "esModuleInterop": true,
"forceConsistentCasingInFileNames": true "noImplicitAny": false
}, },
"include": [ "include": [
"eslint.config.js",
"homebridge-ui",
"src/" "src/"
], ],
"exclude": [ "exclude": [