145 lines
4.8 KiB
TypeScript
145 lines
4.8 KiB
TypeScript
import {
|
|
API,
|
|
Characteristic,
|
|
DynamicPlatformPlugin,
|
|
Logger,
|
|
PlatformAccessory,
|
|
PlatformConfig,
|
|
Service,
|
|
} from "homebridge";
|
|
import { ControlUnit, DeviceButton } from "./Accessories";
|
|
import HarmonyDataProvider from "./DataProviders/HarmonyDataProvider";
|
|
import { IConfig, IControlUnit, IDeviceButton } from "./Models/Config";
|
|
import { HarmonyDevice } from "./Models/HarmonyDevice";
|
|
import { HarmonyHub } from "./Models/HarmonyHub";
|
|
import { PLATFORM_NAME, PLUGIN_NAME } from "./settings";
|
|
|
|
export class Platform implements DynamicPlatformPlugin {
|
|
constructor(
|
|
public readonly log: Logger,
|
|
config: PlatformConfig,
|
|
public readonly api: API
|
|
) {
|
|
this.log.debug("Finished initializing platform:", config.name);
|
|
|
|
this.config = (config as unknown) as IConfig;
|
|
//construct data provider
|
|
const dataProvider = new HarmonyDataProvider({
|
|
hubs: this.config.Hubs,
|
|
deviceConfigs: this.config.Devices,
|
|
matrix: this.config.Matrix,
|
|
log: this.log,
|
|
});
|
|
|
|
this.api.on("didFinishLaunching", async () => {
|
|
log.debug("Executed didFinishLaunching callback");
|
|
this.discoverDevices(dataProvider);
|
|
});
|
|
|
|
this.dataProvider = null;
|
|
|
|
if (this.config) {
|
|
//construct data provider
|
|
this.dataProvider = new HarmonyDataProvider({
|
|
hubs: this.config.Hubs,
|
|
deviceConfigs: this.config.Devices,
|
|
matrix: this.config.Matrix,
|
|
log: this.log,
|
|
});
|
|
|
|
//Emit devices if requested
|
|
|
|
this.dataProvider.on("Ready", () => {
|
|
this.log.info("All hubs connected");
|
|
if (this.config.EmitDevicesOnStartup) {
|
|
const hubs = this.dataProvider!.hubs;
|
|
Object.values(hubs).forEach((hub: HarmonyHub) => {
|
|
const deviceDictionary = hub.devices;
|
|
this.log.info(`${hub.hubName}`);
|
|
|
|
Object.values(deviceDictionary).forEach((device: HarmonyDevice) => {
|
|
this.log.info(` ${device.name} : ${device.id}`);
|
|
Object.keys(device.commands).forEach((command: string) => {
|
|
this.log.info(` ${command}`);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
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[] = [];
|
|
public config: IConfig;
|
|
public dataProvider: HarmonyDataProvider | null;
|
|
|
|
public discoverDevices(dataProvider: HarmonyDataProvider) {
|
|
this.config.ControlUnits.forEach((unit: IControlUnit) => {
|
|
const uuid = this.api.hap.uuid.generate(unit.DisplayName);
|
|
const existingAccessory = this.accessories.find((e) => e.UUID === uuid);
|
|
if (existingAccessory) {
|
|
this.log.info(
|
|
"Restoring existing accessory from cache: " +
|
|
existingAccessory.displayName
|
|
);
|
|
|
|
new ControlUnit(this, existingAccessory, dataProvider, unit.Activities);
|
|
|
|
this.api.publishExternalAccessories(PLUGIN_NAME, [existingAccessory]);
|
|
console.log("Publishing external accessory: " + uuid);
|
|
} else {
|
|
this.log.info("Adding new accessory: " + unit.DisplayName);
|
|
const accessory = new this.api.platformAccessory(
|
|
unit.DisplayName,
|
|
uuid
|
|
);
|
|
accessory.context["DeviceName"] = unit.DisplayName;
|
|
|
|
new ControlUnit(this, accessory, dataProvider, unit.Activities);
|
|
|
|
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
console.log("Publishing external accessory: " + uuid);
|
|
}
|
|
});
|
|
|
|
this.config.DeviceButtons.forEach((button: IDeviceButton) => {
|
|
const uuid = this.api.hap.uuid.generate(button.DisplayName);
|
|
const existingAccessory = this.accessories.find((e) => e.UUID === uuid);
|
|
if (existingAccessory) {
|
|
this.log.info(
|
|
"Restoring existing accessory from cache: " +
|
|
existingAccessory.displayName
|
|
);
|
|
|
|
new DeviceButton(this, existingAccessory, dataProvider, button);
|
|
this.api.updatePlatformAccessories([existingAccessory]);
|
|
} else {
|
|
this.log.info("Adding new accessory: " + button.DisplayName);
|
|
const accessory = new this.api.platformAccessory(
|
|
button.DisplayName,
|
|
uuid
|
|
);
|
|
accessory.context["DeviceName"] = button.DisplayName;
|
|
|
|
new DeviceButton(this, accessory, dataProvider, button);
|
|
|
|
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
|
|
accessory,
|
|
]);
|
|
}
|
|
});
|
|
}
|
|
|
|
configureAccessory(accessory: PlatformAccessory<Record<string, any>>): void {
|
|
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);
|
|
}
|
|
}
|