Successfully added tsyringe to project
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Brandon Watson
2021-12-28 14:48:02 -05:00
parent 503b4c9d59
commit 1a51e4d8c5
6 changed files with 264 additions and 224 deletions

View File

@ -7,6 +7,9 @@ import { IHub } from "../Models/Config/IHub";
import { IDeviceConfig } from "../Models/Config/IDeviceConfig";
import { HarmonyDevice } from "../Models/HarmonyDevice";
import { HarmonyHub } from "../Models/HarmonyHub";
import { IConfig } from "../Models/Config";
import { inject, injectable } from "tsyringe";
import { Logger, Logging } from "homebridge";
const Harmony = require("harmony-websocket");
@ -21,8 +24,8 @@ interface IHarmonyDataProviderProps {
matrix: IMatrix;
}
@injectable()
class HarmonyDataProvider extends EventEmitter {
private _log: any;
private _hubsByDevice: { [deviceName: string]: string } = {};
private _hubs: { [hubName: string]: HarmonyHub } = {};
// private _devicesByHub: { [hubName: string]: { [deviceName: string]: HarmonyDevice } } = {};
@ -32,16 +35,18 @@ class HarmonyDataProvider extends EventEmitter {
private _matrix: IMatrix;
constructor(props: IHarmonyDataProviderProps) {
constructor(
@inject("IConfig") private _config: IConfig,
@inject("log") private _log: Logging
) {
super();
this._log = props.log;
this._matrix = props.matrix;
props.deviceConfigs.forEach((deviceConfig: IDeviceConfig) => {
this._matrix = _config.Matrix;
_config.Devices.forEach((deviceConfig: IDeviceConfig) => {
this._hubsByDevice[deviceConfig.Name] = deviceConfig.Hub;
});
// this._deviceConfigs = props.deviceConfigs;
this.connect(props.hubs);
this.connect(_config.Hubs);
}
// public get devicesByHub(): { [hubName: string]: { [deviceName: string]: HarmonyDevice } } {
@ -104,7 +109,7 @@ class HarmonyDataProvider extends EventEmitter {
controlUnitName: string,
activity: IActivity
) => {
this._log(
this._log.info(
`Starting activity ${activity.DisplayName} for controlUnit: ${controlUnitName}`
);
let lastActivity: IActivity | undefined = undefined;
@ -127,7 +132,7 @@ class HarmonyDataProvider extends EventEmitter {
devicesToTurnOn.map(async (device: HarmonyDevice) => {
if (device && device.name) {
if (!device.on) {
this._log(`Turning on device ${device.name}`);
this._log.info(`Turning on device ${device.name}`);
await device.powerOn();
}
}
@ -175,11 +180,12 @@ class HarmonyDataProvider extends EventEmitter {
//Build potential list of devices to turn off
if (lastActivity) {
let devicesToTurnOff: Array<HarmonyDevice> = lastActivity.DeviceSetupList.map(
(value: IDeviceSetupItem): HarmonyDevice => {
return this.getDeviceFromName(value.DeviceName);
}
);
let devicesToTurnOff: Array<HarmonyDevice> =
lastActivity.DeviceSetupList.map(
(value: IDeviceSetupItem): HarmonyDevice => {
return this.getDeviceFromName(value.DeviceName);
}
);
//remove devices that will be used for next activity from list
//delete array[index] is stupid because it just nulls out the index. But now i have to deal with nulls
@ -201,7 +207,7 @@ class HarmonyDataProvider extends EventEmitter {
controlUnitName
);
this._log(
this._log.info(
`Sanatized devices to turn off: ${JSON.stringify(
devicesToTurnOff.map((e) => (e ? e.name : ""))
)}`
@ -212,7 +218,7 @@ class HarmonyDataProvider extends EventEmitter {
devicesToTurnOff.map(async (device: HarmonyDevice) => {
if (device) {
if (device.on) {
this._log(`Turning off device ${device.name}`);
this._log.info(`Turning off device ${device.name}`);
await device.powerOff();
}
}
@ -323,11 +329,10 @@ class HarmonyDataProvider extends EventEmitter {
public getDeviceFromName(deviceName: string): HarmonyDevice {
let device: HarmonyDevice | undefined;
try {
device = this._hubs[this._hubsByDevice[deviceName]].getDeviceByName(
deviceName
);
device =
this._hubs[this._hubsByDevice[deviceName]].getDeviceByName(deviceName);
} catch (err) {
this._log(`Error retrieving device from hub: ${err}`);
this._log.info(`Error retrieving device from hub: ${err}`);
}
return device!;
@ -350,19 +355,17 @@ class HarmonyDataProvider extends EventEmitter {
private connect = async (hubs: Array<IHub>) => {
let readyCount = 0;
await Promise.all(
hubs.map(
async (hub: IHub): Promise<void> => {
const newHarmonyHub = new HarmonyHub(hub.Name, hub.Ip, this._log);
this._hubs[hub.Name] = newHarmonyHub;
newHarmonyHub.on("Ready", () => {
readyCount++;
if (readyCount === Object.keys(this._hubs).length) {
this.emit("Ready");
}
});
await newHarmonyHub.initialize();
}
)
hubs.map(async (hub: IHub): Promise<void> => {
const newHarmonyHub = new HarmonyHub(hub.Name, hub.Ip, this._log.info);
this._hubs[hub.Name] = newHarmonyHub;
newHarmonyHub.on("Ready", () => {
readyCount++;
if (readyCount === Object.keys(this._hubs).length) {
this.emit("Ready");
}
});
await newHarmonyHub.initialize();
})
);
};

View File

@ -1,3 +1,4 @@
import "reflect-metadata";
import {
API,
Characteristic,
@ -12,9 +13,8 @@ import { Sequence } from "./Accessories/Sequence";
import HarmonyDataProvider from "./DataProviders/HarmonyDataProvider";
import { IConfig, IControlUnit, IDeviceButton } from "./Models/Config";
import { ISequence } from "./Models/Config/ISequence";
import { HarmonyDevice } from "./Models/HarmonyDevice";
import { HarmonyHub } from "./Models/HarmonyHub";
import { PLATFORM_NAME, PLUGIN_NAME } from "./settings";
import { container } from "tsyringe";
export class Platform implements DynamicPlatformPlugin {
constructor(
@ -23,57 +23,58 @@ export class Platform implements DynamicPlatformPlugin {
public readonly api: API
) {
this.log.debug("Finished initializing platform:", config.name);
this.config = config as unknown as IConfig;
this.register();
//construct data provider
const dataProvider = new HarmonyDataProvider({
hubs: this.config.Hubs,
deviceConfigs: this.config.Devices,
matrix: this.config.Matrix,
log: this.log,
});
// const dataProvider = new HarmonyDataProvider({
// hubs: this.config.Hubs,
// deviceConfigs: this.config.Devices,
// matrix: this.config.Matrix,
// log: this.log,
// });
let didFinishLaunching = false;
this.api.on("didFinishLaunching", async () => {
log.debug("Executed didFinishLaunching callback");
this.discoverControlUnitAccessories();
this.discoverDeviceButtonAccessories();
this.discoverSequenceAccessories();
this.pruneAccessories();
didFinishLaunching = true;
});
this.dataProvider = null;
// 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,
});
// 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");
this.discoverControlUnitAccessories(dataProvider);
this.discoverDeviceButtonAccessories(dataProvider);
this.discoverSequenceAccessories(dataProvider);
this.pruneAccessories();
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}`);
});
});
});
}
});
// this.dataProvider.on("Ready", () => {
// this.log.info("All hubs connected");
// this.discoverControlUnitAccessories(dataProvider);
// this.discoverDeviceButtonAccessories(dataProvider);
// this.discoverSequenceAccessories(dataProvider);
// this.pruneAccessories();
// 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}`);
// });
// });
// });
// }
// });
}
}
@ -84,15 +85,12 @@ export class Platform implements DynamicPlatformPlugin {
// this is used to track restored cached accessories
public readonly accessories: PlatformAccessory[] = [];
public config: IConfig;
public dataProvider: HarmonyDataProvider | null;
/**
* Discover new control unit accessories
* @param dataProvider
*/
private discoverControlUnitAccessories(
dataProvider: HarmonyDataProvider
): void {
private discoverControlUnitAccessories(): void {
this.config.ControlUnits.forEach((unit: IControlUnit) => {
const uuid = this.api.hap.uuid.generate(unit.DisplayName);
const existingAccessory = this.accessories.find((e) => e.UUID === uuid);
@ -103,7 +101,12 @@ export class Platform implements DynamicPlatformPlugin {
existingAccessory.displayName
);
new ControlUnit(this, existingAccessory, dataProvider, unit.Activities);
new ControlUnit(
this,
existingAccessory,
container.resolve(HarmonyDataProvider),
unit.Activities
);
this.api.publishExternalAccessories(PLUGIN_NAME, [existingAccessory]);
console.log("Publishing external accessory: " + uuid);
@ -116,7 +119,12 @@ export class Platform implements DynamicPlatformPlugin {
accessory.context["DeviceName"] = unit.DisplayName;
accessory.context["Type"] = typeof ControlUnit.name;
new ControlUnit(this, accessory, dataProvider, unit.Activities);
new ControlUnit(
this,
accessory,
container.resolve(HarmonyDataProvider),
unit.Activities
);
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
console.log("Publishing external accessory: " + uuid);
@ -128,9 +136,7 @@ export class Platform implements DynamicPlatformPlugin {
* Discover new device button accessories
* @param dataProvider
*/
private discoverDeviceButtonAccessories(
dataProvider: HarmonyDataProvider
): void {
private discoverDeviceButtonAccessories(): void {
this.config.DeviceButtons.forEach((button: IDeviceButton) => {
const uuid = this.api.hap.uuid.generate(button.DisplayName);
const existingAccessory = this.accessories.find((e) => e.UUID === uuid);
@ -140,7 +146,12 @@ export class Platform implements DynamicPlatformPlugin {
existingAccessory.displayName
);
new DeviceButton(this, existingAccessory, dataProvider, button);
new DeviceButton(
this,
existingAccessory,
container.resolve(HarmonyDataProvider),
button
);
this.api.updatePlatformAccessories([existingAccessory]);
} else {
this.log.info("Adding new accessory: " + button.DisplayName);
@ -151,7 +162,12 @@ export class Platform implements DynamicPlatformPlugin {
accessory.context["DeviceName"] = button.DisplayName;
accessory.context["Type"] = typeof DeviceButton;
new DeviceButton(this, accessory, dataProvider, button);
new DeviceButton(
this,
accessory,
container.resolve(HarmonyDataProvider),
button
);
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
accessory,
@ -165,7 +181,7 @@ export class Platform implements DynamicPlatformPlugin {
* Discover new sequence accessories
* @param dataProvider
*/
private discoverSequenceAccessories(dataProvider: HarmonyDataProvider): void {
private discoverSequenceAccessories(): void {
this.config.Sequences.forEach((sequence: ISequence) => {
const uuid = this.api.hap.uuid.generate(sequence.DisplayName);
const existingAccessory = this.accessories.find((e) => e.UUID === uuid);
@ -175,7 +191,12 @@ export class Platform implements DynamicPlatformPlugin {
existingAccessory.displayName
);
new Sequence(this, existingAccessory, dataProvider, sequence);
new Sequence(
this,
existingAccessory,
container.resolve(HarmonyDataProvider),
sequence
);
this.api.updatePlatformAccessories([existingAccessory]);
} else {
this.log.info("Adding new accessory: " + sequence.DisplayName);
@ -186,7 +207,12 @@ export class Platform implements DynamicPlatformPlugin {
accessory.context["DeviceName"] = sequence.DisplayName;
accessory.context["Type"] = typeof "Sequence";
new Sequence(this, accessory, dataProvider, sequence);
new Sequence(
this,
accessory,
container.resolve(HarmonyDataProvider),
sequence
);
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
accessory,
@ -222,4 +248,11 @@ export class Platform implements DynamicPlatformPlugin {
// add the restored accessory to the accessories cache so we can track if it has already been registered
this.accessories.push(accessory);
}
private register(): void {
container.register<Platform>(Platform, { useValue: this });
container.register<IConfig>("IConfig", { useValue: this.config });
container.register<Logger>("log", { useValue: this.log });
container.registerSingleton<HarmonyDataProvider>(HarmonyDataProvider);
}
}

View File

@ -6,4 +6,4 @@ export const PLATFORM_NAME = "HarmonyHubMatrix";
/**
* This must match the name of your plugin as defined the package.json
*/
export const PLUGIN_NAME = "homebridge-harmony-control";
export const PLUGIN_NAME = "@watsonb8/homebridge-harmony-control";