Can successfully start an activity on power on.
This commit is contained in:
@ -1,5 +1,275 @@
|
||||
class HarmonyDataProvider {
|
||||
import { Activity } from "../Models/Activity";
|
||||
import { DeviceSetupItem } from "../Models/DeviceSetupItem";
|
||||
import { threadId } from "worker_threads";
|
||||
import { Input, Matrix, Output } from "../Models/Matrix";
|
||||
|
||||
const Harmony = require("harmony-websocket");
|
||||
interface IDevice {
|
||||
id: string,
|
||||
name: string,
|
||||
supportsCommand(commandName: string): boolean,
|
||||
getCommand(commandName: string): string,
|
||||
commands: { [name: string]: string };
|
||||
on: boolean;
|
||||
}
|
||||
|
||||
export default new HarmonyDataProvider();
|
||||
interface IActivityState {
|
||||
currentActivity: Activity
|
||||
}
|
||||
|
||||
interface IHarmonyDataProviderProps {
|
||||
hubAddress: string,
|
||||
log: any,
|
||||
matrix: Matrix
|
||||
}
|
||||
|
||||
class HarmonyDataProvider {
|
||||
private harmony: any;
|
||||
private log: any;
|
||||
private hubAddress: string = "";
|
||||
private connected: boolean = false;
|
||||
|
||||
private devices: { [name: string]: IDevice; } = {};
|
||||
private states: { [controlUnitName: string]: (IActivityState | undefined) } = {};
|
||||
|
||||
private matrix: Matrix;
|
||||
|
||||
constructor(props: IHarmonyDataProviderProps) {
|
||||
this.log = props.log;
|
||||
this.hubAddress = props.hubAddress;
|
||||
this.matrix = props.matrix;
|
||||
|
||||
this.harmony = new Harmony();
|
||||
|
||||
//Listeners
|
||||
this.harmony.on('open', () => {
|
||||
this.log('Hub open');
|
||||
this.connected = true;
|
||||
});
|
||||
this.harmony.on('close', () => {
|
||||
this.log('Hub closed');
|
||||
this.connected = false;
|
||||
});
|
||||
|
||||
this.connect();
|
||||
}
|
||||
|
||||
public powerOn = async (controlUnitName: string, activity: Activity) => {
|
||||
await this.startActivity(controlUnitName, activity);
|
||||
}
|
||||
|
||||
public powerOff = async (controlUnitName: string) => {
|
||||
if (!this.states[controlUnitName]) {
|
||||
return;
|
||||
}
|
||||
//Build potential list of devices to turn off
|
||||
let devicesToTurnOff: Array<IDevice> = this.states[controlUnitName]!.currentActivity.deviceSetupItems
|
||||
.map((value: DeviceSetupItem): IDevice => {
|
||||
return this.getDeviceFromName(value.deviceName);
|
||||
});
|
||||
|
||||
//Resolve device conflicts with other controlUnits
|
||||
devicesToTurnOff = this.sanitizeDeviceList(devicesToTurnOff, controlUnitName);
|
||||
|
||||
//Turn off devices
|
||||
devicesToTurnOff.forEach((device: IDevice) => {
|
||||
this.powerOffDevice(device);
|
||||
});
|
||||
|
||||
this.states[controlUnitName] = undefined;
|
||||
}
|
||||
|
||||
public startActivity = async (controlUnitName: string, activity: Activity) => {
|
||||
let lastActivity: Activity | undefined = undefined;
|
||||
if (this.states[controlUnitName]) {
|
||||
lastActivity = this.states[controlUnitName]!.currentActivity;
|
||||
}
|
||||
|
||||
// this.log(`asdf: ${JSON.stringify(this.devices)}`);
|
||||
//Build potential list of devices to to turn on
|
||||
let devicesToTurnOn: Array<IDevice> = activity.deviceSetupItems.map((value: DeviceSetupItem): IDevice => {
|
||||
return this.getDeviceFromName(value.deviceName);
|
||||
});
|
||||
|
||||
// this.log(`Devices to turn on: ${JSON.stringify(devicesToTurnOn)}`);
|
||||
|
||||
//Resolve device conflicts with other controlUnits
|
||||
devicesToTurnOn = this.sanitizeDeviceList(devicesToTurnOn, controlUnitName);
|
||||
// this.log(`Sanatized devices to turn on: ${JSON.stringify(devicesToTurnOn)}`)
|
||||
|
||||
//Turn on devices
|
||||
await Promise.all(devicesToTurnOn.map(async (device: IDevice) => {
|
||||
this.log(`Turning on device ${device.name}`)
|
||||
await this.powerOnDevice(device);
|
||||
}));
|
||||
|
||||
//Assign correct input
|
||||
await Promise.all(
|
||||
activity.deviceSetupItems.map(async (value: DeviceSetupItem) => {
|
||||
let device: IDevice = this.getDeviceFromName(value.deviceName);
|
||||
|
||||
if (device.supportsCommand(`Input ${value.input}`)) {
|
||||
let command: string = device.getCommand(`Input ${value.input}`);
|
||||
await this.sendCommand(command);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
if (activity.useMatrix) {
|
||||
//get input and output
|
||||
let input: Input = this.matrix.inputs.filter(e => e.inputDevice === activity.controlDeviceId)[0];
|
||||
let output: Output = this.matrix.outputs.filter(e => e.outputDevice === activity.outputDeviceId)[0];
|
||||
|
||||
let inputCommandName: string = `In ${input.inputNumber}`;
|
||||
let outputCommandName: string = `Out ${output.outputLetter}`;
|
||||
|
||||
// this.log(`Matrix input command: ${inputCommandName} Matrix output command: ${outputCommandName}`);
|
||||
|
||||
let matrixDevice: IDevice = this.getDeviceFromName(this.matrix.deviceName);
|
||||
|
||||
//Rout hdmi
|
||||
if (matrixDevice.supportsCommand(inputCommandName) && matrixDevice.supportsCommand(outputCommandName)) {
|
||||
await this.sendCommand(matrixDevice.getCommand(inputCommandName));
|
||||
await this.sendCommand(matrixDevice.getCommand(outputCommandName));
|
||||
}
|
||||
}
|
||||
|
||||
//Build potential list of devices to turn off
|
||||
if (lastActivity) {
|
||||
let devicesToTurnOff: Array<IDevice> = lastActivity.deviceSetupItems.map((value: DeviceSetupItem): IDevice => {
|
||||
return this.getDeviceFromName(value.deviceName);
|
||||
});
|
||||
|
||||
this.log(`Devices to turn off: ${JSON.stringify(devicesToTurnOff)}`);
|
||||
|
||||
//Resolve device conflicts with other controlUnits
|
||||
devicesToTurnOff = this.sanitizeDeviceList(devicesToTurnOff, controlUnitName);
|
||||
|
||||
this.log(`Sanatized devices to turn off: ${JSON.stringify(devicesToTurnOff)}`);
|
||||
|
||||
await Promise.all(
|
||||
//Turn off devices
|
||||
devicesToTurnOff.map(async (device: IDevice) => {
|
||||
await this.powerOffDevice(device);
|
||||
})
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
//Assign current activity
|
||||
this.states[controlUnitName] = { currentActivity: activity };
|
||||
}
|
||||
|
||||
public volumeUp = async (controlUnitName: string) => {
|
||||
|
||||
}
|
||||
|
||||
public volumeDown = async (controlUnitName: string) => {
|
||||
|
||||
}
|
||||
|
||||
public sendKeyPress = async (controlUnitName: string) => {
|
||||
|
||||
}
|
||||
|
||||
public getIsActive(controlUnitName: string): boolean {
|
||||
return this.states[controlUnitName] ? true : false
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to harmony and receive device info
|
||||
*/
|
||||
private connect = async () => {
|
||||
await this.harmony.connect(this.hubAddress);
|
||||
let self = this;
|
||||
|
||||
setTimeout(async function () {
|
||||
if (self.connected) {
|
||||
let devices: any = await self.harmony.getDevices();
|
||||
try {
|
||||
await Promise.all(
|
||||
//Add each to dictionary
|
||||
devices.map(async (dev: any) => {
|
||||
//get commands
|
||||
let commands: { [name: string]: string } = {};
|
||||
let deviceCommands: any = await self.harmony.getDeviceCommands(dev.id);
|
||||
deviceCommands.forEach((command: any) => {
|
||||
commands[command.label] = command.action;
|
||||
});
|
||||
|
||||
self.devices[dev.label] = {
|
||||
id: dev.id,
|
||||
name: dev.label,
|
||||
commands: commands,
|
||||
on: false,
|
||||
//Define device methods
|
||||
supportsCommand(commandName: string): boolean {
|
||||
let command = commands[commandName];
|
||||
return (command) ? true : false;
|
||||
},
|
||||
getCommand(commandName: string): string {
|
||||
return commands[commandName];
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
} catch (err) {
|
||||
self.log(`ERROR - error connecting to harmony: ${err}`);
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
private powerOffDevice = async (device: IDevice) => {
|
||||
let powerOffCommand: string = "Power Off";
|
||||
if (device.supportsCommand(powerOffCommand)) {
|
||||
await this.sendCommand(device.getCommand(powerOffCommand));
|
||||
}
|
||||
}
|
||||
|
||||
private powerOnDevice = async (device: IDevice) => {
|
||||
let powerOnCommand: string = "Power On";
|
||||
if (device.supportsCommand(powerOnCommand)) {
|
||||
await this.sendCommand(device.getCommand(powerOnCommand));
|
||||
}
|
||||
}
|
||||
|
||||
private getDeviceFromName(deviceName: string): IDevice {
|
||||
return this.devices[deviceName];
|
||||
}
|
||||
|
||||
private sanitizeDeviceList(devicesToTurnOn: Array<IDevice>, controlUnitName: string): Array<IDevice> {
|
||||
for (let controlUnitKey in this.states) {
|
||||
//Skip self
|
||||
if (controlUnitKey === controlUnitName) {
|
||||
continue;
|
||||
}
|
||||
let currentOtherState: IActivityState = this.states[controlUnitKey]!;
|
||||
|
||||
if (currentOtherState) {
|
||||
currentOtherState.currentActivity.deviceSetupItems.forEach((value: DeviceSetupItem) => {
|
||||
//there are devices to remove
|
||||
if (devicesToTurnOn.some(e => e.name === value.deviceName)) {
|
||||
let deviceToRemove: IDevice = devicesToTurnOn.filter(i => i.name === value.deviceName)[0];
|
||||
delete devicesToTurnOn[devicesToTurnOn.indexOf(deviceToRemove)];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return devicesToTurnOn;
|
||||
}
|
||||
|
||||
private sendCommand = async (command: string) => {
|
||||
try {
|
||||
let response = await this.harmony.sendCommand(JSON.stringify(command));
|
||||
this.log(`Sent command: ${JSON.stringify(command)} response: ${JSON.stringify(response)}`);
|
||||
} catch (err) {
|
||||
this.log(`ERROR - error sending command to harmony: ${err}`);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default HarmonyDataProvider;
|
Reference in New Issue
Block a user