generated from homebridge/homebridge-plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
193 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,148 +1,91 @@ | ||
import { | ||
API, | ||
DynamicPlatformPlugin, | ||
Logger, | ||
PlatformAccessory, | ||
PlatformConfig, | ||
Service, | ||
Characteristic, | ||
API, | ||
Characteristic, | ||
DynamicPlatformPlugin, | ||
Logger, | ||
PlatformAccessory, | ||
PlatformConfig, | ||
Service, | ||
} from "homebridge"; | ||
|
||
import { PLATFORM_NAME, PLUGIN_NAME } from "./settings"; | ||
import { ExamplePlatformAccessory } from "./platformAccessory"; | ||
import { authenticate } from "./lib/authenticate"; | ||
import { SOAPRequest } from "./lib/request"; | ||
import { PLATFORM_NAME, PLUGIN_NAME } from "./settings"; | ||
import { BasePlatformAccessory } from "./platforms/index" | ||
Check warning on line 13 in src/platform.ts
|
||
|
||
/** | ||
* HomebridgePlatform | ||
* This class is the main constructor for your plugin, this is where you should | ||
* parse the user config and discover/register accessories with Homebridge. | ||
*/ | ||
export class HomebridgeIHC implements DynamicPlatformPlugin { | ||
public readonly Service: typeof Service = this.api.hap.Service; | ||
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 Service: typeof Service = this.api.hap.Service; | ||
public readonly Characteristic: typeof Characteristic = this.api.hap.Characteristic; | ||
public readonly accessories: PlatformAccessory[] = []; | ||
|
||
constructor( | ||
public readonly log: Logger, | ||
public readonly config: PlatformConfig, | ||
public readonly api: API | ||
) { | ||
const request = new SOAPRequest(config.endpoint) | ||
Check warning on line 25 in src/platform.ts
|
||
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", async () => { | ||
this.api.on("didFinishLaunching", async () => { | ||
log.debug("Executed didFinishLaunching callback"); | ||
|
||
const authenticated = await request.authenticate(config.auth) | ||
Check warning on line 31 in src/platform.ts
|
||
if (authenticated) { | ||
this.discoverDevices(request); | ||
} else { | ||
this.log.warn("Terminating - Invalid user credentials") | ||
Check warning on line 35 in src/platform.ts
|
||
} | ||
}); | ||
} | ||
|
||
/** | ||
* This function is invoked when homebridge restores cached accessories from disk at startup. | ||
* 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); | ||
|
||
// add the restored accessory to the accessories cache so we can track if it has already been registered | ||
this.accessories.push(accessory); | ||
} | ||
|
||
/** | ||
* This is an example method showing how to register discovered accessories. | ||
* Accessories must only be registered once, previously created accessories | ||
* must not be registered again to prevent "duplicate UUID" errors. | ||
*/ | ||
discoverDevices(request: SOAPRequest) { | ||
// 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 = [ | ||
{ | ||
type: "light", | ||
id: "5830162", | ||
name: "Mikkels Værelse", | ||
}, | ||
{ | ||
type: "light", | ||
id: "7905371", | ||
name: "Stue Loftudtag", | ||
}, | ||
{ | ||
type: "light", | ||
id: "2300178", | ||
name: "Stue Vest Vindue", | ||
} | ||
]; | ||
|
||
// 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 | ||
// something globally unique, but constant, for example, the device serial | ||
// number or MAC address | ||
const uuid = this.api.hap.uuid.generate(device.id); | ||
|
||
// 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 | ||
); | ||
|
||
if (existingAccessory) { | ||
// the accessory already exists | ||
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, request); | ||
|
||
// 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); | ||
} else { | ||
// the accessory does not yet exist, so we need to create it | ||
this.log.info("Adding new accessory:", device.name); | ||
|
||
// create a new accessory | ||
const accessory = new this.api.platformAccessory( | ||
device.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; | ||
|
||
// create the accessory handler for the newly create accessory | ||
// this is imported from `platformAccessory.ts` | ||
new ExamplePlatformAccessory(this, accessory, request); | ||
|
||
// link the accessory to your platform | ||
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [ | ||
accessory, | ||
]); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
|
||
configureAccessory(accessory: PlatformAccessory) { | ||
this.log.info("Loading accessory from cache:", accessory.displayName); | ||
|
||
this.accessories.push(accessory); | ||
} | ||
|
||
discoverDevices(request: SOAPRequest) { | ||
const devices = this.config.devices | ||
Check warning on line 47 in src/platform.ts
|
||
|
||
for (const device of devices) { | ||
const uuid = this.api.hap.uuid.generate(device.id); | ||
|
||
const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid); | ||
|
||
if (existingAccessory) { | ||
this.log.info("Restoring existing accessory from cache:", existingAccessory.displayName); | ||
|
||
// switch (existingAccessory.context.device.type) { | ||
// case "light": | ||
// new LightPlatformAccessory(this, existingAccessory, request) | ||
// break | ||
|
||
// case "switch": | ||
// new SwitchPlatformAccessory(this, existingAccessory, request) | ||
// break | ||
// } | ||
|
||
new BasePlatformAccessory(this, existingAccessory, request) | ||
Check warning on line 67 in src/platform.ts
|
||
} else { | ||
this.log.info("Adding new accessory:", device.name); | ||
|
||
const accessory = new this.api.platformAccessory(device.name, uuid); | ||
|
||
accessory.context.device = device; | ||
|
||
// switch (accessory.context.device.type) { | ||
// case "light": | ||
// new LightPlatformAccessory(this, accessory, request) | ||
// break | ||
|
||
// case "switch": | ||
// new SwitchPlatformAccessory(this, accessory, request) | ||
// break | ||
// } | ||
|
||
new BasePlatformAccessory(this, accessory, request) | ||
Check warning on line 85 in src/platform.ts
|
||
|
||
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge'; | ||
import { HomebridgeIHC } from "../platform" | ||
import { SOAPRequest } from '../lib/request'; | ||
|
||
type State = { | ||
value: boolean, | ||
typeString: string, | ||
resourceID: number, | ||
isValueRuntime: boolean | ||
} | ||
|
||
export class BasePlatformAccessory { | ||
service: Service; | ||
state: State = { | ||
value: false, | ||
typeString: "", | ||
resourceID: -1, | ||
isValueRuntime: false | ||
} | ||
|
||
constructor( | ||
private readonly platform: HomebridgeIHC, | ||
private readonly accessory: PlatformAccessory, | ||
private readonly request: SOAPRequest | ||
) { | ||
this.request = request | ||
const accessoryService = this.accessory.getService(this.platform.Service.AccessoryInformation)! | ||
accessoryService.setCharacteristic(this.platform.Characteristic.Manufacturer, this.accessory.context?.metadata?.manufacturer || "LK IHC") | ||
if (this.accessory.context?.metadata?.model) accessoryService.setCharacteristic(this.platform.Characteristic.Model, this.accessory.context?.metadata?.model) | ||
if (this.accessory.context?.metadata?.serial) accessoryService.setCharacteristic(this.platform.Characteristic.SerialNumber, this.accessory.context?.metadata?.serial) | ||
|
||
this.service = this.accessory.getService(this.accessory.context.device.type == "light" ? this.platform.Service.Lightbulb : this.platform.Service.Switch) || this.accessory.addService(this.accessory.context.device.type == "light" ? this.platform.Service.Lightbulb : this.platform.Service.Switch); | ||
this.service.setCharacteristic(this.platform.Characteristic.Name, this.accessory.context.device?.name || "Unknown device"); | ||
|
||
this.service.getCharacteristic(this.platform.Characteristic.On) | ||
.onSet(this.setState.bind(this)) // SET - bind to the `setOn` method below | ||
.onGet(this.getState.bind(this)); // GET - bind to the `getOn` method below | ||
|
||
this.getState() | ||
} | ||
|
||
async setState(value: CharacteristicValue) { | ||
this.state.value = value as boolean; | ||
|
||
await this.request.setResourceValue(this.state, value as boolean) | ||
|
||
this.platform.log.debug('Set Characteristic On ->', value); | ||
} | ||
|
||
async getState() { | ||
this.state = await this.request.getResourceValue(this.accessory.context.device.id) | ||
|
||
this.platform.log.debug("Light ID: ", this.accessory.context.device.id) | ||
|
||
this.platform.log.debug('Get Characteristic On ->', this.state.value); | ||
|
||
return this.state.value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { PlatformAccessory } from 'homebridge'; | ||
import { SOAPRequest } from '../lib/request'; | ||
import { HomebridgeIHC } from "../platform"; | ||
import { BasePlatformAccessory } from "./index"; | ||
|
||
export class LightPlatformAccessory extends BasePlatformAccessory { | ||
constructor( | ||
platform: HomebridgeIHC, | ||
accessory: PlatformAccessory, | ||
request: SOAPRequest | ||
) { | ||
super(platform, accessory, request) | ||
|
||
this.service = accessory.getService(platform.Service.Lightbulb) || accessory.addService(platform.Service.Lightbulb); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { PlatformAccessory } from 'homebridge'; | ||
import { SOAPRequest } from '../lib/request'; | ||
import { HomebridgeIHC } from "../platform"; | ||
import { BasePlatformAccessory } from "./index"; | ||
|
||
export class SwitchPlatformAccessory extends BasePlatformAccessory { | ||
constructor( | ||
platform: HomebridgeIHC, | ||
accessory: PlatformAccessory, | ||
request: SOAPRequest | ||
) { | ||
super(platform, accessory, request) | ||
|
||
this.service = accessory.getService(platform.Service.Switch) || accessory.addService(platform.Service.Switch); | ||
} | ||
} |