mirror of
https://github.com/dtwardow/homebridge-multi-tap-switch.git
synced 2026-11-01 20:18:30 +00:00
First test
This commit is contained in:
1 parent
d5961e4464
commit
0637aeb2f3
7 files changed
+103
-64
No files matched your search
@@ -114,7 +114,7 @@ This will launch an instance of Homebridge in debug mode which will restart ever
|
|||||||
You can now start customising the plugin template to suit your requirements.
|
You can now start customising the plugin template to suit your requirements.
|
||||||
|
|
||||||
* [`src/platform.ts`](./src/platform.ts) - this is where your device setup and discovery should go.
|
* [`src/platform.ts`](./src/platform.ts) - this is where your device setup and discovery should go.
|
||||||
* [`src/platformAccessory.ts`](./src/platformAccessory.ts) - this is where your accessory control logic should go, you can rename or create multiple instances of this file for each accessory type you need to implement as part of your platform plugin. You can refer to the [developer documentation](https://developers.homebridge.io/) to see what characteristics you need to implement for each service type.
|
* [`src/accessoryInput.ts`](./src/accessoryInput.ts) - this is where your accessory control logic should go, you can rename or create multiple instances of this file for each accessory type you need to implement as part of your platform plugin. You can refer to the [developer documentation](https://developers.homebridge.io/) to see what characteristics you need to implement for each service type.
|
||||||
* [`config.schema.json`](./config.schema.json) - update the config schema to match the config you expect from the user. See the [Plugin Config Schema Documentation](https://developers.homebridge.io/#/config-schema).
|
* [`config.schema.json`](./config.schema.json) - update the config schema to match the config you expect from the user. See the [Plugin Config Schema Documentation](https://developers.homebridge.io/#/config-schema).
|
||||||
|
|
||||||
## Versioning Your Plugin
|
## Versioning Your Plugin
|
||||||
|
|||||||
+14
-2
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"pluginAlias": "ExampleHomebridgePlugin",
|
"pluginAlias": "MultiTapSwitch",
|
||||||
"pluginType": "platform",
|
"pluginType": "platform",
|
||||||
"singular": true,
|
"singular": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
@@ -9,7 +9,19 @@
|
|||||||
"title": "Name",
|
"title": "Name",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": true,
|
"required": true,
|
||||||
"default": "Example Dynamic Platform"
|
"default": "Scene Switcher"
|
||||||
|
},
|
||||||
|
"numScenes": {
|
||||||
|
"title": "Number of Scenes",
|
||||||
|
"type": "number",
|
||||||
|
"required": true,
|
||||||
|
"default": 4
|
||||||
|
},
|
||||||
|
"secondsToKeep": {
|
||||||
|
"title": "Holding Time",
|
||||||
|
"type": "number",
|
||||||
|
"required": true,
|
||||||
|
"default": 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+3
-3
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "homebridge-plugin-name",
|
"name": "homebridge-multitap-switch",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "homebridge-plugin-name",
|
"name": "homebridge-multitap-switch",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "Apache-2.0",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.10.9",
|
"@types/node": "^16.10.9",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||||
|
|||||||
@@ -1,53 +1,81 @@
|
|||||||
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
||||||
|
|
||||||
import { ExampleHomebridgePlatform } from './platform';
|
import { MultiTapSwitchPlatform } from './platform';
|
||||||
|
import {TIMEOUT} from 'dns';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform Accessory
|
* Platform Accessory
|
||||||
* An instance of this class is created for each accessory your platform registers
|
* An instance of this class is created for each accessory your platform registers
|
||||||
* Each accessory may expose multiple services of different service types.
|
* Each accessory may expose multiple services of different service types.
|
||||||
*/
|
*/
|
||||||
export class ExamplePlatformAccessory {
|
export class DeviceAccessory {
|
||||||
private service: Service;
|
private serviceIn: Service;
|
||||||
|
private serviceOut: Service;
|
||||||
|
|
||||||
/**
|
private readonly singleButtonEvents = {
|
||||||
* These are just used to create a working example
|
minValue: this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
|
||||||
* You should implement your own code to track the state of your accessory
|
maxValue: this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
|
||||||
*/
|
validValues: [
|
||||||
private exampleStates = {
|
this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
|
||||||
On: false,
|
],
|
||||||
Brightness: 100,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private currentState = {
|
||||||
|
"On": Boolean,
|
||||||
|
"NumScenes": Number,
|
||||||
|
"KeepSeconds": Number,
|
||||||
|
"Timeout": TIMEOUT
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly triggerButtons: Service[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly platform: ExampleHomebridgePlatform,
|
private readonly platform: MultiTapSwitchPlatform,
|
||||||
private readonly accessory: PlatformAccessory,
|
private readonly accessory: PlatformAccessory,
|
||||||
|
private readonly numOfButtons: number,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// set accessory information
|
// set accessory information
|
||||||
this.accessory.getService(this.platform.Service.AccessoryInformation)!
|
this.accessory.getService(this.platform.Service.AccessoryInformation)!
|
||||||
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Default-Manufacturer')
|
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'TippyTapper Solutions')
|
||||||
.setCharacteristic(this.platform.Characteristic.Model, 'Default-Model')
|
.setCharacteristic(this.platform.Characteristic.Model, 'SceneButton-000')
|
||||||
.setCharacteristic(this.platform.Characteristic.SerialNumber, 'Default-Serial');
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, 'DE:AD:BE:EF:00:00');
|
||||||
|
|
||||||
// get the LightBulb service if it exists, otherwise create a new LightBulb service
|
|
||||||
// you can create multiple services for each accessory
|
this.serviceIn = this.accessory.getService(this.platform.Service.Switch)
|
||||||
this.service = this.accessory.getService(this.platform.Service.Lightbulb) || this.accessory.addService(this.platform.Service.Lightbulb);
|
|| this.accessory.addService(this.platform.Service.Switch);
|
||||||
|
|
||||||
|
this.serviceOut = this.accessory.getService(this.platform.Service.ServiceLabel)
|
||||||
|
|| this.accessory.addService(this.platform.Service.ServiceLabel);
|
||||||
|
|
||||||
|
this.serviceOut.setCharacteristic(this.platform.Characteristic.ServiceLabelNamespace, '')
|
||||||
|
this.serviceOut.setCharacteristic(this.platform.Characteristic.ServiceLabelIndex, 1);
|
||||||
|
|
||||||
|
// Create configured number of scene buttons
|
||||||
|
for (let i = 1; i <= numOfButtons; i++) {
|
||||||
|
const newButton = this.accessory.addService(this.platform.Service.StatelessProgrammableSwitch);
|
||||||
|
this.serviceOut.addLinkedService(newButton);
|
||||||
|
this.triggerButtons.push(newButton);
|
||||||
|
|
||||||
|
newButton.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent)
|
||||||
|
.setProps(this.singleButtonEvents);
|
||||||
|
newButton.setCharacteristic(this.platform.Characteristic.ServiceLabelIndex, i);
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
||||||
this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.context.device.exampleDisplayName);
|
this.serviceOut.setCharacteristic(this.platform.Characteristic.Name, accessory.context.device.exampleDisplayName);
|
||||||
|
|
||||||
// each service must implement at-minimum the "required characteristics" for the given service type
|
// each service must implement at-minimum the "required characteristics" for the given service type
|
||||||
// see https://developers.homebridge.io/#/service/Lightbulb
|
// see https://developers.homebridge.io/#/service/Lightbulb
|
||||||
|
|
||||||
// register handlers for the On/Off Characteristic
|
// register handlers for the On/Off Characteristic
|
||||||
this.service.getCharacteristic(this.platform.Characteristic.On)
|
this.serviceOut.getCharacteristic(this.platform.Characteristic.On)
|
||||||
.onSet(this.setOn.bind(this)) // SET - bind to the `setOn` method below
|
.onSet(this.setOn.bind(this)) // SET - bind to the `setOn` method below
|
||||||
.onGet(this.getOn.bind(this)); // GET - bind to the `getOn` method below
|
.onGet(this.getOn.bind(this)); // GET - bind to the `getOn` method below
|
||||||
|
|
||||||
// register handlers for the Brightness Characteristic
|
// register handlers for the Brightness Characteristic
|
||||||
this.service.getCharacteristic(this.platform.Characteristic.Brightness)
|
this.serviceOut.getCharacteristic(this.platform.Characteristic.Brightness)
|
||||||
.onSet(this.setBrightness.bind(this)); // SET - bind to the 'setBrightness` method below
|
.onSet(this.setBrightness.bind(this)); // SET - bind to the 'setBrightness` method below
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,11 +90,11 @@ export class ExamplePlatformAccessory {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Example: add two "motion sensor" services to the accessory
|
// Example: add two "motion sensor" services to the accessory
|
||||||
const motionSensorOneService = this.accessory.getService('Motion Sensor One Name') ||
|
const inputService = this.accessory.getService(this.accessory.displayName + ' Trigger') ||
|
||||||
this.accessory.addService(this.platform.Service.MotionSensor, 'Motion Sensor One Name', 'YourUniqueIdentifier-1');
|
this.accessory.addService(this.platform.Service.MotionSensor, this.accessory.displayName + ' Trigger', 'YourUniqueIdentifier-1');
|
||||||
|
|
||||||
const motionSensorTwoService = this.accessory.getService('Motion Sensor Two Name') ||
|
const outputService = this.accessory.getService(this.accessory.displayName + ' SceneSwitch') ||
|
||||||
this.accessory.addService(this.platform.Service.MotionSensor, 'Motion Sensor Two Name', 'YourUniqueIdentifier-2');
|
this.accessory.addService(this.platform.Service.MotionSensor, this.accessory.displayName + ' SceneSwitch', 'YourUniqueIdentifier-2');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updating characteristics values asynchronously.
|
* Updating characteristics values asynchronously.
|
||||||
@@ -83,12 +111,13 @@ export class ExamplePlatformAccessory {
|
|||||||
motionDetected = !motionDetected;
|
motionDetected = !motionDetected;
|
||||||
|
|
||||||
// push the new value to HomeKit
|
// push the new value to HomeKit
|
||||||
motionSensorOneService.updateCharacteristic(this.platform.Characteristic.MotionDetected, motionDetected);
|
inputService.updateCharacteristic(this.platform.Characteristic.MotionDetected, motionDetected);
|
||||||
motionSensorTwoService.updateCharacteristic(this.platform.Characteristic.MotionDetected, !motionDetected);
|
outputService.updateCharacteristic(this.platform.Characteristic.MotionDetected, !motionDetected);
|
||||||
|
|
||||||
this.platform.log.debug('Triggering motionSensorOneService:', motionDetected);
|
this.platform.log.debug('Triggering motionSensorOneService:', motionDetected);
|
||||||
this.platform.log.debug('Triggering motionSensorTwoService:', !motionDetected);
|
this.platform.log.debug('Triggering motionSensorTwoService:', !motionDetected);
|
||||||
}, 10000);
|
}, 10000);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,8 +126,12 @@ export class ExamplePlatformAccessory {
|
|||||||
*/
|
*/
|
||||||
async setOn(value: CharacteristicValue) {
|
async setOn(value: CharacteristicValue) {
|
||||||
// implement your own code to turn your device on/off
|
// implement your own code to turn your device on/off
|
||||||
this.exampleStates.On = value as boolean;
|
this.currentState.On = value as boolean;
|
||||||
|
|
||||||
|
this.currentState.Timeout = setTimeout(() => {
|
||||||
|
this.currentState.On = false;
|
||||||
|
this.setOn(false);
|
||||||
|
}, 1000 * 10);
|
||||||
this.platform.log.debug('Set Characteristic On ->', value);
|
this.platform.log.debug('Set Characteristic On ->', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +150,7 @@ export class ExamplePlatformAccessory {
|
|||||||
*/
|
*/
|
||||||
async getOn(): Promise<CharacteristicValue> {
|
async getOn(): Promise<CharacteristicValue> {
|
||||||
// implement your own code to check if the device is on
|
// implement your own code to check if the device is on
|
||||||
const isOn = this.exampleStates.On;
|
const isOn = this.currentState.On;
|
||||||
|
|
||||||
this.platform.log.debug('Get Characteristic On ->', isOn);
|
this.platform.log.debug('Get Characteristic On ->', isOn);
|
||||||
|
|
||||||
@@ -133,9 +166,9 @@ export class ExamplePlatformAccessory {
|
|||||||
*/
|
*/
|
||||||
async setBrightness(value: CharacteristicValue) {
|
async setBrightness(value: CharacteristicValue) {
|
||||||
// implement your own code to set the brightness
|
// implement your own code to set the brightness
|
||||||
this.exampleStates.Brightness = value as number;
|
//this.currentState.KeepSeconds = value as number;
|
||||||
|
|
||||||
this.platform.log.debug('Set Characteristic Brightness -> ', value);
|
this.platform.log.debug('Set Characteristic KeepSeconds -> ', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
import { API } from 'homebridge';
|
import { API } from 'homebridge';
|
||||||
|
|
||||||
import { PLATFORM_NAME } from './settings';
|
import { PLATFORM_NAME } from './settings';
|
||||||
import { ExampleHomebridgePlatform } from './platform';
|
import { MultiTapSwitchPlatform } from './platform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method registers the platform with Homebridge
|
* This method registers the platform with Homebridge
|
||||||
*/
|
*/
|
||||||
export = (api: API) => {
|
export = (api: API) => {
|
||||||
api.registerPlatform(PLATFORM_NAME, ExampleHomebridgePlatform);
|
api.registerPlatform(PLATFORM_NAME, MultiTapSwitchPlatform);
|
||||||
};
|
};
|
||||||
+18
-24
@@ -1,14 +1,14 @@
|
|||||||
import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service, Characteristic } from 'homebridge';
|
import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service, Characteristic } from 'homebridge';
|
||||||
|
|
||||||
import { PLATFORM_NAME, PLUGIN_NAME } from './settings';
|
import { PLATFORM_NAME, PLUGIN_NAME } from './settings';
|
||||||
import { ExamplePlatformAccessory } from './platformAccessory';
|
import { DeviceAccessory } from './accessory';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HomebridgePlatform
|
* HomebridgePlatform
|
||||||
* This class is the main constructor for your plugin, this is where you should
|
* This class is the main constructor for your plugin, this is where you should
|
||||||
* parse the user config and discover/register accessories with Homebridge.
|
* parse the user config and discover/register accessories with Homebridge.
|
||||||
*/
|
*/
|
||||||
export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
|
export class MultiTapSwitchPlatform implements DynamicPlatformPlugin {
|
||||||
public readonly Service: typeof Service = this.api.hap.Service;
|
public readonly Service: typeof Service = this.api.hap.Service;
|
||||||
public readonly Characteristic: typeof Characteristic = this.api.hap.Characteristic;
|
public readonly Characteristic: typeof Characteristic = this.api.hap.Characteristic;
|
||||||
|
|
||||||
@@ -44,6 +44,10 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
|
|||||||
this.accessories.push(accessory);
|
this.accessories.push(accessory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineUuid(name: string | undefined, serial: string): string {
|
||||||
|
return this.api.hap.uuid.generate(name + '_' + serial);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an example method showing how to register discovered accessories.
|
* This is an example method showing how to register discovered accessories.
|
||||||
* Accessories must only be registered once, previously created accessories
|
* Accessories must only be registered once, previously created accessories
|
||||||
@@ -54,24 +58,12 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
|
|||||||
// EXAMPLE ONLY
|
// EXAMPLE ONLY
|
||||||
// A real plugin you would discover accessories from the local network, cloud services
|
// A real plugin you would discover accessories from the local network, cloud services
|
||||||
// or a user-defined array in the platform config.
|
// or a user-defined array in the platform config.
|
||||||
const exampleDevices = [
|
|
||||||
{
|
|
||||||
exampleUniqueId: 'ABCD',
|
|
||||||
exampleDisplayName: 'Bedroom',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
exampleUniqueId: 'EFGH',
|
|
||||||
exampleDisplayName: 'Kitchen',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// loop over the discovered devices and register each one if it has not already been registered
|
|
||||||
for (const device of exampleDevices) {
|
|
||||||
|
|
||||||
// generate a unique id for the accessory this should be generated from
|
// generate a unique id for the accessory this should be generated from
|
||||||
// something globally unique, but constant, for example, the device serial
|
// something globally unique, but constant, for example, the device serial
|
||||||
// number or MAC address
|
// number or MAC address
|
||||||
const uuid = this.api.hap.uuid.generate(device.exampleUniqueId);
|
//const uuid = this.api.hap.uuid.generate(device.exampleUniqueId);
|
||||||
|
const uuid = this.defineUuid(this.config.name, "0");
|
||||||
|
|
||||||
// see if an accessory with the same uuid has already been registered and restored from
|
// see if an accessory with the same uuid has already been registered and restored from
|
||||||
// the cached devices we stored in the `configureAccessory` method above
|
// the cached devices we stored in the `configureAccessory` method above
|
||||||
@@ -86,8 +78,8 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
|
|||||||
// this.api.updatePlatformAccessories([existingAccessory]);
|
// this.api.updatePlatformAccessories([existingAccessory]);
|
||||||
|
|
||||||
// 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 `accessoryInput.ts`
|
||||||
new ExamplePlatformAccessory(this, existingAccessory);
|
new DeviceAccessory(this, existingAccessory, this.config.numScenes);
|
||||||
|
|
||||||
// it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, eg.:
|
// it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, eg.:
|
||||||
// remove platform accessories when no longer present
|
// remove platform accessories when no longer present
|
||||||
@@ -95,22 +87,24 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
|
|||||||
// this.log.info('Removing existing accessory from cache:', existingAccessory.displayName);
|
// this.log.info('Removing existing accessory from cache:', existingAccessory.displayName);
|
||||||
} else {
|
} else {
|
||||||
// the accessory does not yet exist, so we need to create it
|
// the accessory does not yet exist, so we need to create it
|
||||||
this.log.info('Adding new accessory:', device.exampleDisplayName);
|
this.log.info('Adding INPUT:', this.config.name);
|
||||||
|
|
||||||
// create a new accessory
|
// create a new accessory
|
||||||
const accessory = new this.api.platformAccessory(device.exampleDisplayName, uuid);
|
const accessory = new this.api.platformAccessory(<string>this.config.name, uuid);
|
||||||
|
|
||||||
// store a copy of the device object in the `accessory.context`
|
// store a copy of the device object in the `accessory.context`
|
||||||
// the `context` property can be used to store any data about the accessory you may need
|
// the `context` property can be used to store any data about the accessory you may need
|
||||||
accessory.context.device = device;
|
accessory.context.device = {
|
||||||
|
"numScenes": this.config.numScenes,
|
||||||
|
"keepSeconds": this.config.keepSeconds
|
||||||
|
};
|
||||||
|
|
||||||
// create the accessory handler for the newly create accessory
|
// create the accessory handler for the newly create accessory
|
||||||
// this is imported from `platformAccessory.ts`
|
// this is imported from `accessoryInput.ts`
|
||||||
new ExamplePlatformAccessory(this, accessory);
|
new DeviceAccessory(this, accessory, this.config.numScenes);
|
||||||
|
|
||||||
// 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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
export const PLATFORM_NAME = 'ExampleHomebridgePlugin';
|
export const PLATFORM_NAME = 'MultiTapSwitch';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This must match the name of your plugin as defined the package.json
|
* This must match the name of your plugin as defined the package.json
|
||||||
*/
|
*/
|
||||||
export const PLUGIN_NAME = 'homebridge-plugin-name';
|
export const PLUGIN_NAME = 'homebridge-multitap-switch';
|
||||||
Reference in new issue
Block a user