Skip to content

Commit

Permalink
First version
Browse files Browse the repository at this point in the history
  • Loading branch information
rvetere committed Jan 21, 2024
1 parent ae59bc8 commit 4fce65b
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 139 deletions.
12 changes: 6 additions & 6 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@
"ecmaVersion": 2018,
"sourceType": "module"
},
"ignorePatterns": [
"dist"
],
"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"],
Expand All @@ -28,7 +24,11 @@
"comma-spacing": ["error"],
"no-multi-spaces": ["warn", { "ignoreEOLComments": true }],
"no-trailing-spaces": ["warn"],
"lines-between-class-members": ["warn", "always", {"exceptAfterSingleLine": true}],
"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",
Expand Down
6 changes: 3 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"files.eol": "\n",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"editor.rulers": [ 140 ],
"editor.rulers": [140],
"eslint.enable": true
}
}
24 changes: 17 additions & 7 deletions config.schema.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
{
"pluginAlias": "ExampleHomebridgePlugin",
"pluginAlias": "HomebridgeVirtualButton",
"pluginType": "platform",
"singular": true,
"schema": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"title": "Name",
"type": "string",
"required": true,
"default": "Example Dynamic Platform"
"switches": {
"type": "array",
"additionalItems": true,
"items": {
"type": "object",
"additionalProperties": true,
"properties": {
"name": {
"title": "Disply name for homekit",
"type": "string",
"required": true
}
}
}
}
}
}
}
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
{
"private": true,
"displayName": "Plugin Name",
"name": "homebridge-plugin-name",
"displayName": "Homebridge Virtual Button",
"name": "homebridge-virtual-button",
"version": "1.0.0",
"description": "A short description about what your plugin does.",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/USERNAME/GITHUB_PROJECT_NAME.git"
"url": "https://github.com/rocket-monkey/homebridge-virtual-button.git"
},
"bugs": {
"url": "https://github.com/USERNAME/GITHUB_PROJECT_NAME/issues"
"url": "https://github.com/rocket-monkey/homebridge-virtual-button/issues"
},
"engines": {
"node": "^18.17.0 || ^20.9.0",
Expand Down
86 changes: 48 additions & 38 deletions src/platform.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service, Characteristic } from 'homebridge';

import { PLATFORM_NAME, PLUGIN_NAME } from './settings';
import { ExamplePlatformAccessory } from './platformAccessory';
import {
API,
DynamicPlatformPlugin,
Logger,
PlatformAccessory,
PlatformConfig,
Service,
Characteristic,
} from "homebridge";

import { PLATFORM_NAME, PLUGIN_NAME } from "./settings";
import { PlatformSwitchAccessory } from "./platformAccessory";

/**
* HomebridgePlatform
Expand All @@ -10,24 +18,25 @@ import { ExamplePlatformAccessory } from './platformAccessory';
*/
export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
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;

// this is used to track restored cached accessories
public readonly accessories: PlatformAccessory[] = [];

constructor(
public readonly log: Logger,
public readonly config: PlatformConfig,
public readonly api: API,
public readonly api: API
) {
this.log.debug('Finished initializing platform:', this.config.name);
this.log.debug("Finished initializing platform:", this.config.name);

// When this event is fired it means Homebridge has restored all cached accessories from disk.
// Dynamic Platform plugins should only register new accessories after this event was fired,
// in order to ensure they weren't added to homebridge already. This event can also be used
// to start discovery of new accessories.
this.api.on('didFinishLaunching', () => {
log.debug('Executed didFinishLaunching callback');
this.api.on("didFinishLaunching", () => {
log.debug("Executed didFinishLaunching callback");
// run the method to discover / register your devices as accessories
this.discoverDevices();
});
Expand All @@ -38,7 +47,7 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
* It should be used to setup event handlers for characteristics and update respective values.
*/
configureAccessory(accessory: PlatformAccessory) {
this.log.info('Loading accessory from cache:', accessory.displayName);
this.log.info("Loading accessory from cache:", accessory.displayName);

// add the restored accessory to the accessories cache so we can track if it has already been registered
this.accessories.push(accessory);
Expand All @@ -50,66 +59,67 @@ export class ExampleHomebridgePlatform implements DynamicPlatformPlugin {
* must not be registered again to prevent "duplicate UUID" errors.
*/
discoverDevices() {
if (!this.config.switches) {
return;
}
const switches = this.config.switches;

// EXAMPLE ONLY
// A real plugin you would discover accessories from the local network, cloud services
// 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) {

// loop over the discovered switches and register each one if it has not already been registered
for (const button of switches) {
// generate a unique id for the accessory this should be generated from
// something globally unique, but constant, for example, the device serial
// number or MAC address
const uuid = this.api.hap.uuid.generate(device.exampleUniqueId);
const uuid = this.api.hap.uuid.generate(button.name);

// 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
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
const existingAccessory = this.accessories.find(
(accessory) => accessory.UUID === uuid
);

if (existingAccessory) {
// the accessory already exists
this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
this.log.info(
"Restoring existing accessory from cache:",
existingAccessory.displayName
);

// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
// existingAccessory.context.device = device;
// this.api.updatePlatformAccessories([existingAccessory]);

// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
new ExamplePlatformAccessory(this, existingAccessory);
new PlatformSwitchAccessory(this, existingAccessory);

// it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, eg.:
// remove platform accessories when no longer present
// this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
// this.log.info('Removing existing accessory from cache:', existingAccessory.displayName);
// this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
// existingAccessory,
// ]);
// this.log.info(
// "Removing existing accessory from cache:",
// existingAccessory.displayName
// );
} else {
// the accessory does not yet exist, so we need to create it
this.log.info('Adding new accessory:', device.exampleDisplayName);
this.log.info("Adding new accessory:", button.name);

// create a new accessory
const accessory = new this.api.platformAccessory(device.exampleDisplayName, uuid);
const accessory = new this.api.platformAccessory(button.name, uuid);

// 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
accessory.context.device = device;
accessory.context.switch = button;

// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new ExamplePlatformAccessory(this, accessory);
new PlatformSwitchAccessory(this, accessory);

// link the accessory to your platform
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
accessory,
]);
}
}
}
Expand Down
Loading

0 comments on commit 4fce65b

Please sign in to comment.