This commit is contained in:
209
src/services/activityService.ts
Normal file
209
src/services/activityService.ts
Normal file
@ -0,0 +1,209 @@
|
||||
import { Logging } from "homebridge";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { HarmonyDataProvider2 } from "../dataProviders/harmonyDataProvider2";
|
||||
import { StateDataProvider } from "../dataProviders/stateDataProvider";
|
||||
import { IActivityState } from "../models/activityState";
|
||||
import {
|
||||
IActivity,
|
||||
IConfig,
|
||||
IDeviceSetupItem,
|
||||
IInput,
|
||||
IOutput,
|
||||
} from "../models/config";
|
||||
import { HarmonyDevice } from "../models/harmonyDevice";
|
||||
|
||||
@injectable()
|
||||
export class ActivityService {
|
||||
constructor(
|
||||
@inject(HarmonyDataProvider2)
|
||||
private _harmonyDataProvider: HarmonyDataProvider2,
|
||||
@inject(StateDataProvider) private _stateDataProvider: StateDataProvider,
|
||||
@inject("IConfig") private _config: IConfig,
|
||||
@inject("log") private _log: Logging
|
||||
) {}
|
||||
|
||||
public startActivity = async (
|
||||
controlUnitName: string,
|
||||
activity: IActivity
|
||||
) => {
|
||||
this._log.info(
|
||||
`Starting activity ${activity.DisplayName} for controlUnit: ${controlUnitName}`
|
||||
);
|
||||
let devicesToTurnOn: Array<HarmonyDevice> = this.getDevicesToTurnOn(
|
||||
activity,
|
||||
controlUnitName
|
||||
);
|
||||
|
||||
await this._harmonyDataProvider.turnOnDevices(devicesToTurnOn);
|
||||
|
||||
await this.assignDeviceInput(activity);
|
||||
|
||||
await this.routeInputsToOutputs(activity);
|
||||
|
||||
let lastActivity = this.getCurrentActivity(controlUnitName);
|
||||
|
||||
let devicesToTurnOff: Array<HarmonyDevice> = this.getDevicesToTurnOff(
|
||||
controlUnitName,
|
||||
lastActivity,
|
||||
activity
|
||||
);
|
||||
await this._harmonyDataProvider.turnOffDevices(devicesToTurnOff);
|
||||
|
||||
this._stateDataProvider.updateState(activity, controlUnitName);
|
||||
};
|
||||
|
||||
public stopCurrentActivity = async (
|
||||
controlUnitName: string
|
||||
): Promise<void> => {
|
||||
if (!this.getCurrentActivity(controlUnitName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let lastActivity: IActivity | undefined =
|
||||
this.getCurrentActivity(controlUnitName);
|
||||
|
||||
let devicesToTurnOff: Array<HarmonyDevice> = this.getDevicesToTurnOff(
|
||||
controlUnitName,
|
||||
lastActivity
|
||||
);
|
||||
await this._harmonyDataProvider.turnOffDevices(devicesToTurnOff);
|
||||
|
||||
this._stateDataProvider.removeState(controlUnitName);
|
||||
};
|
||||
|
||||
public getCurrentActivity(controlUnitName: string): IActivity | undefined {
|
||||
return this._stateDataProvider.getState(controlUnitName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if a control unit is active
|
||||
* @param controlUnitName
|
||||
*/
|
||||
public getIsActive(controlUnitName: string): IActivity | undefined {
|
||||
return this._stateDataProvider.getState(controlUnitName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to make sure no control unit depends on device list.
|
||||
* @param devicesToTurnOn The list of devices to modify.
|
||||
* @param controlUnitName The name of the control unit in question.
|
||||
*/
|
||||
private sanitizeDeviceList(
|
||||
devicesToTurnOn: Array<HarmonyDevice>,
|
||||
controlUnitName: string
|
||||
): Array<HarmonyDevice> {
|
||||
for (let controlUnitKey in this._stateDataProvider.states) {
|
||||
//Skip self
|
||||
if (controlUnitKey === controlUnitName) {
|
||||
continue;
|
||||
}
|
||||
let currentOtherState: IActivityState =
|
||||
this._stateDataProvider.states[controlUnitKey]!;
|
||||
|
||||
if (currentOtherState) {
|
||||
currentOtherState.currentActivity.DeviceSetupList.forEach(
|
||||
(value: IDeviceSetupItem) => {
|
||||
//there are devices to remove
|
||||
if (devicesToTurnOn.some((e) => e && e.name === value.DeviceName)) {
|
||||
let deviceToRemove: HarmonyDevice = devicesToTurnOn.filter(
|
||||
(i) => i.name === value.DeviceName
|
||||
)[0];
|
||||
delete devicesToTurnOn[devicesToTurnOn.indexOf(deviceToRemove)];
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return devicesToTurnOn;
|
||||
}
|
||||
|
||||
private getDevicesToTurnOn(
|
||||
activity: IActivity,
|
||||
controlUnitName: string
|
||||
): Array<HarmonyDevice> {
|
||||
let potentialDevices = this.buildPotentialDeviceList(activity);
|
||||
return this.sanitizeDeviceList(potentialDevices, controlUnitName);
|
||||
}
|
||||
|
||||
private getDevicesToTurnOff(
|
||||
controlUnitName: string,
|
||||
lastActivity?: IActivity,
|
||||
nextActivity?: IActivity
|
||||
) {
|
||||
let potentialDevices = lastActivity
|
||||
? this.buildPotentialDeviceList(lastActivity)
|
||||
: [];
|
||||
|
||||
//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
|
||||
if (nextActivity) {
|
||||
potentialDevices.forEach((device: HarmonyDevice, index: number) => {
|
||||
if (
|
||||
device &&
|
||||
device.name &&
|
||||
nextActivity.DeviceSetupList.some((e) => {
|
||||
return e && e.DeviceName === device.name;
|
||||
})
|
||||
) {
|
||||
delete potentialDevices[index];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return this.sanitizeDeviceList(potentialDevices, controlUnitName);
|
||||
}
|
||||
|
||||
private buildPotentialDeviceList(activity: IActivity): HarmonyDevice[] {
|
||||
return activity.DeviceSetupList.map(
|
||||
(value: IDeviceSetupItem): HarmonyDevice => {
|
||||
return this._harmonyDataProvider.getDeviceFromName(value.DeviceName);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async assignDeviceInput(activity: IActivity): Promise<void> {
|
||||
await Promise.all(
|
||||
activity.DeviceSetupList.map(async (value: IDeviceSetupItem) => {
|
||||
let device: HarmonyDevice = this._harmonyDataProvider.getDeviceFromName(
|
||||
value.DeviceName
|
||||
);
|
||||
|
||||
if (device && device.supportsCommand(`Input${value.Input}`)) {
|
||||
await device.sendCommand(`Input${value.Input}`);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private async routeInputsToOutputs(activity: IActivity) {
|
||||
if (activity.UseMatrix) {
|
||||
//get input and output
|
||||
let input: IInput = this._config.Matrix.Inputs.filter(
|
||||
(e) => e.InputDevice === activity.ControlDevice
|
||||
)[0];
|
||||
let output: IOutput = this._config.Matrix.Outputs.filter(
|
||||
(e) => e.OutputDevice === activity.OutputDevice
|
||||
)[0];
|
||||
|
||||
let inputCommandName: string = `In ${input.InputNumber}`;
|
||||
let outputCommandName: string = `Out ${output.OutputLetter}`;
|
||||
|
||||
let matrixDevice: HarmonyDevice =
|
||||
this._harmonyDataProvider.getDeviceFromName(
|
||||
this._config.Matrix.DeviceName
|
||||
);
|
||||
|
||||
//Route hdmi
|
||||
if (
|
||||
matrixDevice.supportsCommand(inputCommandName) &&
|
||||
matrixDevice.supportsCommand(outputCommandName)
|
||||
) {
|
||||
await matrixDevice.sendCommand(outputCommandName);
|
||||
await matrixDevice.sendCommand(inputCommandName);
|
||||
await matrixDevice.sendCommand(outputCommandName);
|
||||
await matrixDevice.sendCommand(inputCommandName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
src/services/commandService.ts
Normal file
71
src/services/commandService.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { inject } from "tsyringe";
|
||||
import { RemoteKey } from "../accessories/controlUnit";
|
||||
import { HarmonyDataProvider2 } from "../dataProviders/harmonyDataProvider2";
|
||||
import { StateDataProvider } from "../dataProviders/stateDataProvider";
|
||||
import { IConfig } from "../models/config";
|
||||
import { HarmonyDevice } from "../models/harmonyDevice";
|
||||
|
||||
export class CommandService {
|
||||
constructor(
|
||||
@inject(StateDataProvider) private _stateDataProvider: StateDataProvider,
|
||||
@inject(HarmonyDataProvider2)
|
||||
private _harmonyDataProvider: HarmonyDataProvider2
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Send key press for current activity.
|
||||
*
|
||||
* @param controlUnitName The name of the control unit to act on.
|
||||
* @param key The key to send.
|
||||
*/
|
||||
public sendKeyPress = async (controlUnitName: string, key: any) => {
|
||||
let currentActivity = this._stateDataProvider.getState(controlUnitName);
|
||||
if (currentActivity) {
|
||||
let commandName: string = "";
|
||||
|
||||
let device: HarmonyDevice = this._harmonyDataProvider.getDeviceFromName(
|
||||
currentActivity.ControlDevice
|
||||
);
|
||||
switch (key) {
|
||||
case RemoteKey.ARROW_UP: {
|
||||
commandName = "Direction Up";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.ARROW_DOWN: {
|
||||
commandName = "Direction Down";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.ARROW_LEFT: {
|
||||
commandName = "Direction Left";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.ARROW_RIGHT: {
|
||||
commandName = "Direction Right";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.SELECT: {
|
||||
commandName = "Select";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.PLAY_PAUSE: {
|
||||
commandName = "Pause";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.INFORMATION: {
|
||||
commandName = "Menu";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.BACK: {
|
||||
commandName = "Back";
|
||||
break;
|
||||
}
|
||||
case RemoteKey.EXIT: {
|
||||
commandName = "Back";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await device.sendCommand(commandName);
|
||||
}
|
||||
};
|
||||
}
|
44
src/services/volumeService.ts
Normal file
44
src/services/volumeService.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { Logging } from "homebridge";
|
||||
import { inject } from "tsyringe";
|
||||
import { HarmonyDataProvider2 } from "../dataProviders/harmonyDataProvider2";
|
||||
import { StateDataProvider } from "../dataProviders/stateDataProvider";
|
||||
import { IConfig } from "../models/config";
|
||||
import { HarmonyDevice } from "../models/harmonyDevice";
|
||||
|
||||
export class VolumeService {
|
||||
constructor(
|
||||
@inject(StateDataProvider) private _stateDataProvider: StateDataProvider,
|
||||
@inject(HarmonyDataProvider2)
|
||||
private _harmonyDataProvider: HarmonyDataProvider2
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Turn the volume up for the current running activity.
|
||||
*/
|
||||
public volumeUp = async (controlUnitName: string) => {
|
||||
let volumeUpCommand: string = "Volume Up";
|
||||
let currentActivity = this._stateDataProvider.getState(controlUnitName);
|
||||
if (currentActivity) {
|
||||
let volumeDevice: HarmonyDevice =
|
||||
this._harmonyDataProvider.getDeviceFromName(
|
||||
currentActivity.VolumeDevice
|
||||
);
|
||||
await volumeDevice.sendCommand(volumeUpCommand);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Volume down for current running activity.
|
||||
*/
|
||||
public volumeDown = async (controlUnitName: string) => {
|
||||
let volumeDownCommand: string = "Volume Down";
|
||||
let currentActivity = this._stateDataProvider.getState(controlUnitName);
|
||||
if (currentActivity) {
|
||||
let volumeDevice: HarmonyDevice =
|
||||
this._harmonyDataProvider.getDeviceFromName(
|
||||
currentActivity.VolumeDevice
|
||||
);
|
||||
await volumeDevice.sendCommand(volumeDownCommand);
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user