diff --git a/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json b/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json new file mode 100644 index 00000000..918fe73f --- /dev/null +++ b/Example Configuration/SIMPLBridging/SIMPLBridgeExample_configurationFile.json @@ -0,0 +1,438 @@ +{ + "system_url": "", + "template": {}, + "template_url": "", + "system": { + "info": { + "comment": "", + "requiredControlSofwareVersion": "", + "systemType": "huddle", + "lastModifiedDate": "2018-07-09T20:00:47.873Z", + "lastUid": 23, + "processorType": "rmc3" + }, + "devices": [ + { + "key": "processor", + "group": "processor", + "uid": 0, + "supportsCompliance": true, + "type": "rmc3", + "properties": {}, + "name": "RMC3" + }, + { + "key": "comm-1", + "uid": 1, + "name": "Generic comm 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "comParams": { + "hardwareHandshake": "None", + "parity": "None", + "protocol": "RS232", + "baudRate": 9600, + "dataBits": 8, + "softwareHandshake": "None", + "stopBits": 1 + }, + "controlPortNumber": 1, + "controlPortDevKey": "processor", + "method": "Com" + } + } + }, + { + "key": "tcp-1", + "uid": 2, + "name": "Generic TCP 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "tcpSshProperties": { + "username": "", + "autoReconnect": true, + "AutoReconnectIntervalMs": 2000, + "port": 23, + "address": "0.0.0.0", + "password": "" + }, + "method": "Tcpip" + } + } + }, + { + "key": "ssh-1", + "uid": 3, + "name": "Generic SSH 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "tcpSshProperties": { + "username": "crestron", + "autoReconnect": true, + "AutoReconnectIntervalMs": 2000, + "port": 22, + "address": "10.11.50.135", + "password": "2H3Zu&OvgXp6" + }, + "method": "Ssh" + } + } + }, + { + "key": "eisc-1A", + "uid": 4, + "type": "eiscApi", + "group": "api", + "properties": { + "control": { + "tcpSshProperties": { + "address": "127.0.0.2", + "port": 0 + }, + "ipId": "1A" + }, + "devices": [ + { + "deviceKey": "comm-1", + "joinStart": 3001 + }, + { + "deviceKey": "tcp-1", + "joinStart": 3011 + }, + { + "deviceKey": "ssh-1", + "joinStart": 3021 + }, + { + "deviceKey": "dmMd8x8-1", + "joinStart": 1 + }, + { + "deviceKey": "dmTx201C-1", + "joinStart": 3051 + }, + { + "deviceKey": "dmRmc4kScalerC-1", + "joinStart": 3061 + }, + { + "deviceKey": "dmRmc200C-1", + "joinStart": 3071 + }, + { + "deviceKey": "dmRmc100C-1", + "joinStart": 3081 + }, + { + "deviceKey": "comm-2", + "joinStart": 2501 + }, + { + "deviceKey": "comm-3", + "joinStart": 2511 + }, + { + "deviceKey": "comm-4", + "joinStart": 2521 + }, + { + "deviceKey": "cec-1", + "joinStart": 2531 + }, + { + "deviceKey": "cec-2", + "joinStart": 2541 + }, + { + "deviceKey": "cec-3", + "joinStart": 2551 + }, + { + "deviceKey": "cec-4", + "joinStart": 2561 + }, + { + "deviceKey": "cec-5", + "joinStart": 2571 + }, + { + "deviceKey": "cec-6", + "joinStart": 2581 + }, + { + "deviceKey": "cec-7", + "joinStart": 2591 + }, + { + "deviceKey": "gls-oir-1", + "joinStart": 2701 + }, + { + "deviceKey": "gls-odt-1", + "joinStart": 2751 + } + ] + } + }, + { + "key": "dmMd8x8-1", + "uid": 5, + "name": "DM-MD8x8 Chassis 1", + "type": "dmMd8x8", + "group": "dmChassis", + "properties": { + "control": { + "method": "ipid", + "ipid": "40", + "params": { + "endOfLineString": "\n", + "deviceReadyResponsePattern": ".*>" + } + }, + "volumeControls": {}, + "inputSlots": { + "1": "dmcHdDsp", + "2": "dmcHdDsp", + "3": "dmcDvi", + "4": "dmcDvi", + "5": "dmcC", + "6": "dmcCDsp" + }, + "outputSlots": { + "1": "dmcCoHd", + "2": "dmcCoHd" + }, + "inputNames": { + "1": "Input 1", + "2": "Input 2", + "3": "Input 3", + "4": "Input 4", + "5": "Input 5", + "6": "Input 6" + }, + "parentDeviceKey": "processor", + "outputNames": { + "1": "Output 1", + "2": "Output 2", + "3": "Output 3", + "4": "Output 4" + } + } + }, + { + "key": "dmTx201C-1", + "uid": 6, + "name": "DM-TX-201C 1", + "type": "dmTx201C", + "group": "dmEndpoint", + "properties": { + "control": { + "method": "ipid", + "ipid": "45", + "params": { + "endOfLineString": "\n", + "deviceReadyResponsePattern": ".*>" + } + }, + "parentDeviceKey": "dmMd8x8-1", + "parentInputNumber": "5" + } + }, + { + "key": "dmRmc4kScalerC-1", + "uid": 7, + "name": "DM-RMC-4K-SCALER-C Out 1", + "type": "dmRmc4kScalerC", + "group": "dmEndpoint", + "properties": { + "control": { + "method": "ipid", + "ipid": "61", + "params": { + "endOfLineString": "\n", + "deviceReadyResponsePattern": ".*>" + } + }, + "parentDeviceKey": "dmMd8x8-1", + "parentOutputNumber": "1" + } + }, + { + "key": "dmRmc200C-1", + "uid": 8, + "name": "DM-RMC-200-C Out 2", + "type": "dmRmc200C", + "group": "dmEndpoint", + "properties": { + "control": { + "method": "ipid", + "ipid": "62", + "params": { + "endOfLineString": "\n", + "deviceReadyResponsePattern": ".*>" + } + }, + "parentDeviceKey": "dmMd8x8-1", + "parentOutputNumber": "2" + } + }, + { + "key": "dmRmc100C-1", + "uid": 9, + "name": "DM-RMC-100-C Out 3", + "type": "dmRmc100C", + "group": "dmEndpoint", + "properties": { + "control": { + "method": "ipid", + "ipid": "63", + "params": { + "endOfLineString": "\n", + "deviceReadyResponsePattern": ".*>" + } + }, + "parentDeviceKey": "dmMd8x8-1", + "parentOutputNumber": "3" + } + }, + { + "key": "comm-2", + "uid": 10, + "name": "Rmc comm 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "comParams": { + "hardwareHandshake": "None", + "parity": "None", + "protocol": "RS232", + "baudRate": 9600, + "dataBits": 8, + "softwareHandshake": "None", + "stopBits": 1 + }, + "controlPortNumber": 1, + "controlPortDevKey": "dmRmc4kScalerC-1", + "method": "Com" + } + } + }, + { + "key": "comm-3", + "uid": 11, + "name": "Rmc comm 2", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "comParams": { + "hardwareHandshake": "None", + "parity": "None", + "protocol": "RS232", + "baudRate": 9600, + "dataBits": 8, + "softwareHandshake": "None", + "stopBits": 1 + }, + "controlPortNumber": 1, + "controlPortDevKey": "dmRmc200C-1", + "method": "Com" + } + } + }, + { + "key": "cec-1", + "uid": 13, + "name": "Tx 5 cec 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "controlPortName": "HdmiIn", + "controlPortDevKey": "dmTx201C-1", + "method": "Cec" + } + } + }, + { + "key": "cec-5", + "uid": 17, + "name": "Rmc 1 cec 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "controlPortName": "HdmiOut", + "controlPortDevKey": "dmRmc4kScalerC-1", + "method": "Cec" + } + } + }, + { + "key": "cec-6", + "uid": 18, + "name": "Dm Chassis In 1 cec 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "controlPortName": "inputCard1--hdmiIn", + "controlPortDevKey": "dmMd8x8-1", + "method": "Cec" + } + } + }, + { + "key": "cec-7", + "uid": 19, + "name": "Dm Chassis Out 1 cec 1", + "type": "genericComm", + "group": "comm", + "properties": { + "control": { + "controlPortName": "outputCard1--hdmiOut1", + "controlPortDevKey": "dmMd8x8-1", + "method": "Cec" + } + } + }, + { + "key": "gls-oir-1", + "uid": 19, + "name": "GLS-OIR-CN 1", + "type": "glsoirccn", + "group": "occupancy", + "properties": { + "control": { + "cresnetId": "41", + "method": "cresnet" + } + } + }, + { + "key": "gls-odt-1", + "uid": 19, + "name": "GLS-ODT-CN 1", + "type": "glsodtccn", + "group": "occupancy", + "properties": { + "control": { + "cresnetId": "42", + "method": "cresnet" + } + } + } + ], + "rooms": [], + "sourceLists": {}, + "tieLines": [] + } +} \ No newline at end of file diff --git a/Example Configuration/SIMPLBridging/configurationFile-dmps3300c-avRouting.json b/Example Configuration/SIMPLBridging/configurationFile-dmps3300c-avRouting.json new file mode 100644 index 00000000..df791e3d --- /dev/null +++ b/Example Configuration/SIMPLBridging/configurationFile-dmps3300c-avRouting.json @@ -0,0 +1,69 @@ +{ + "system_url": "", + "template": { + }, + "template_url": "", + "system": { + "info": { + "comment": "", + "requiredControlSofwareVersion": "", + "systemType": "huddle", + "lastModifiedDate": "2018-07-09T20:00:47.873Z", + "lastUid": 23, + "processorType": "dmps3300c" + }, + "devices": [ + { + "key": "processor", + "group": "processor", + "uid": 0, + "supportsCompliance": true, + "type": "dmps3300c", + "properties": { + }, + "name": "DMPS3-300-C" + }, + { + "key": "eisc-A", + "uid":4, + "type": "eiscApi", + "group":"api", + "properties": { + "control":{ + "tcpSshProperties":{ + "address":"127.0.0.2", + "port":0 + }, + "ipId":"1A" + }, + "devices": [ + { + "deviceKey":"processor-avRouting", + "joinStart":1 + }, + { + "deviceKey":"processor-programAudioOutput", + "joinStart":3001 + }, + { + "deviceKey":"processor-aux1AudioOutput", + "joinStart":3011 + }, + { + "deviceKey":"processor-aux2AudioOutput", + "joinStart":3021 + } + ] + } + } + ], + "rooms": [ + + ], + "sourceLists": { + + }, + "tieLines": [ + ] + } +} \ No newline at end of file diff --git a/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs b/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs deleted file mode 100644 index 10a87dca..00000000 --- a/PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs +++ /dev/null @@ -1,437 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using Crestron.SimplSharp; - -//using PepperDash.Core; -//using PepperDash.Essentials.Core; -//using PepperDash.Essentials.Room.Config; - -//namespace PepperDash.Essentials -//{ -// public class EssentialsPresentationRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange -// { -// public event EventHandler CurrentVolumeDeviceChange; -// public event SourceInfoChangeHandler CurrentSingleSourceChange; -// public event SourceInfoChangeHandler CurrentDisplay1SourceChange; -// public event SourceInfoChangeHandler CurrentDisplay2SourceChange; - -// protected override Func OnFeedbackFunc { get { -// return () => (CurrentSingleSourceInfo != null -// && CurrentSingleSourceInfo.Type != eSourceListItemType.Off) -// || (Display1SourceInfo != null -// && Display1SourceInfo.Type != eSourceListItemType.Off) -// || (Display2SourceInfo != null -// && Display2SourceInfo.Type != eSourceListItemType.Off); } } - -// protected override Func IsWarmingFeedbackFunc { get { return () =>false;; } } -// protected override Func IsCoolingFeedbackFunc { get { return () => false; } } - -// public EssentialsPresentationRoomPropertiesConfig Config { get; private set; } - -// public Dictionary Displays { get; private set; } - -// public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; } -// public IBasicVolumeControls DefaultVolumeControls { get; private set; }C:\Working Directories\PD\essentials\PepperDashEssentials\Room\Types\EssentialsPresentationRoom.cs - -// /// -// /// The config name of the source list -// /// -// public string SourceListKey { get; set; } - -// /// -// /// If room is off, enables power on to last source. Default true -// /// -// public bool EnablePowerOnToLastSource { get; set; } -// string LastSourceKey; - -// public enum eVideoRoutingMode -// { -// SelectSourceSelectDisplay, SourceToAllDisplays -// } - -// public eVideoRoutingMode VideoRoutingMode { get; set; } - -// public enum eAudioRoutingMode -// { -// AudioFollowsLastVideo, SelectAudioFromDisplay -// } - -// /// -// /// -// /// -// public IBasicVolumeControls CurrentVolumeControls -// { -// get { return _CurrentAudioDevice; } -// set -// { -// if (value == _CurrentAudioDevice) return; - -// var oldDev = _CurrentAudioDevice; -// // derigister this room from the device, if it can -// if (oldDev is IInUseTracking) -// (oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio"); -// var handler = CurrentVolumeDeviceChange; -// if (handler != null) -// CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange)); -// _CurrentAudioDevice = value; -// if (handler != null) -// CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange)); -// // register this room with new device, if it can -// if (_CurrentAudioDevice is IInUseTracking) -// (_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio"); -// } -// } -// IBasicVolumeControls _CurrentAudioDevice; - -// /// -// /// The SourceListItem last run - containing names and icons. The complex setter is -// /// to add/remove this room to the source's InUseTracking, if it is capable -// /// -// public SourceListItem CurrentSingleSourceInfo -// { -// get { return _CurrentSingleSourceInfo; } -// private set -// { -// if (value == _CurrentSingleSourceInfo) return; - -// var handler = CurrentSingleSourceChange; -// // remove from in-use tracker, if so equipped -// if(_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking) -// (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control"); - -// if (handler != null) -// handler(this, _CurrentSingleSourceInfo, ChangeType.WillChange); - -// _CurrentSingleSourceInfo = value; - -// // add to in-use tracking -// if (_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking) -// (_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control"); -// if (handler != null) -// handler(this, _CurrentSingleSourceInfo, ChangeType.DidChange); -// } -// } -// SourceListItem _CurrentSingleSourceInfo; - -// public SourceListItem Display1SourceInfo -// { -// get { return _Display1SourceInfo; } -// set -// { -// if (value == _Display1SourceInfo) return; - -// var handler = CurrentDisplay1SourceChange; -// if (handler != null) -// handler(this, _Display1SourceInfo, ChangeType.WillChange); - -// _Display1SourceInfo = value; - -// if (handler != null) -// handler(this, _Display1SourceInfo, ChangeType.DidChange); -// } -// } -// SourceListItem _Display1SourceInfo; - -// public SourceListItem Display2SourceInfo -// { -// get { return _Display2SourceInfo; } -// set -// { -// if (value == _Display2SourceInfo) return; - -// var handler = CurrentDisplay2SourceChange; -// if (handler != null) -// handler(this, _Display2SourceInfo, ChangeType.WillChange); - -// _Display2SourceInfo = value; - -// if (handler != null) -// handler(this, _Display2SourceInfo, ChangeType.DidChange); -// } -// } -// SourceListItem _Display2SourceInfo; - -// /// -// /// If an audio dialer is available for this room -// /// -// public bool HasAudioDialer { get { return false; } } -// /// -// /// -// /// -// /// -// /// -// public EssentialsPresentationRoom(string key, string name, -// Dictionary displays, -// IBasicVolumeWithFeedback defaultVolume, EssentialsPresentationRoomPropertiesConfig config) -// : base(key, name) -// { -// Config = config; -// Displays = displays; - -// DefaultVolumeControls = defaultVolume; -// CurrentVolumeControls = defaultVolume; - -// //DefaultAudioDevice = defaultAudio; -// //if (defaultAudio is IBasicVolumeControls) -// // DefaultVolumeControls = defaultAudio as IBasicVolumeControls; -// //else if (defaultAudio is IHasVolumeDevice) -// // DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice; - - -// SourceListKey = "default"; -// EnablePowerOnToLastSource = true; -// } - -// /// -// /// Run the same source to all destinations -// /// -// /// -// public void RouteSourceToAllDestinations(SourceListItem sourceItem) -// { -// if (Config.Volumes.Master != null) -// { -// var audioDev = DeviceManager.GetDeviceForKey(Config.Volumes.Master.DeviceKey); -// if (audioDev is IBasicVolumeWithFeedback) -// { - -// } -// } - -// foreach (var display in Displays.Values) -// { -// if (sourceItem != null) -// DoVideoRoute(sourceItem.SourceKey, display.Key); -// else -// DoVideoRoute("$off", display.Key); -// } -// Display1SourceInfo = sourceItem; -// Display2SourceInfo = sourceItem; -// CurrentSingleSourceInfo = sourceItem; -// OnFeedback.FireUpdate(); -// } - -// public void SourceToDisplay1(SourceListItem sourceItem) -// { -// DoVideoRoute(sourceItem.SourceKey, Displays[1].Key); -// Display1SourceInfo = sourceItem; -// OnFeedback.FireUpdate(); -// } - -// public void SourceToDisplay2(SourceListItem sourceItem) -// { -// DoVideoRoute(sourceItem.SourceKey, Displays[2].Key); -// Display2SourceInfo = sourceItem; -// OnFeedback.FireUpdate(); -// } - - -// /// -// /// Basic source -> destination routing -// /// -// void DoVideoRoute(string sourceKey, string destinationKey) -// { -// new CTimer(o => -// { -// var dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSinkNoSwitching; -// if (dest == null) -// { -// Debug.Console(1, this, "Cannot route. Destination '{0}' not found", destinationKey); -// return; -// } -// // off is special case -// if (sourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) -// { -// dest.ReleaseRoute(); -// if (dest is IPower) -// (dest as IPower).PowerOff(); -// return; -// } - -// var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs; -// if (source == null) -// { -// Debug.Console(1, this, "Cannot route. Source '{0}' not found", sourceKey); -// return; -// } -// dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video); -// }, 0); -// } - -// /// -// /// -// /// -// protected override void EndShutdown() -// { -// RunRouteAction("roomoff"); -// } - -// /// -// /// -// /// -// /// -// public void RunRouteAction(string routeKey) -// { -// RunRouteAction(routeKey, null); -// } - -// /// -// /// Gets a source from config list SourceListKey and dynamically build and executes the -// /// route or commands -// /// -// /// -// public void RunRouteAction(string routeKey, Action successCallback) -// { -// // Run this on a separate thread -// new CTimer(o => -// { -// Debug.Console(1, this, "Run room action '{0}'", routeKey); -// var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey); -// if(dict == null) -// { -// Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey); -// return; -// } - -// // Try to get the list item by it's string key -// if (!dict.ContainsKey(routeKey)) -// { -// Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'", -// routeKey, SourceListKey); -// return; -// } - -// var item = dict[routeKey]; -// //Debug.Console(2, this, "Action {0} has {1} steps", -// // item.SourceKey, item.RouteList.Count); - -// // Let's run it -// if (routeKey.ToLower() != "roomoff") -// LastSourceKey = routeKey; - -// foreach (var route in item.RouteList) -// { -// // if there is a $defaultAll on route, run two separate -// if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase)) -// { -// var tempAudio = new SourceRouteListItem -// { -// DestinationKey = "$defaultDisplay", -// SourceKey = route.SourceKey, -// Type = eRoutingSignalType.Video -// }; -// DoRoute(tempAudio); - -// var tempVideo = new SourceRouteListItem -// { -// DestinationKey = "$defaultAudio", -// SourceKey = route.SourceKey, -// Type = eRoutingSignalType.Audio -// }; -// DoRoute(tempVideo); -// continue; -// } -// else -// DoRoute(route); -// } - -// // Set volume control on room, using default if non provided -// IBasicVolumeControls volDev = null; -// // Handle special cases for volume control -// if (string.IsNullOrEmpty(item.VolumeControlKey) -// || item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase)) -// volDev = DefaultVolumeControls; -// //else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) -// // volDev = DefaultDisplay as IBasicVolumeControls; -// // Or a specific device, probably rarely used. -// else -// { -// var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey); -// if (dev is IBasicVolumeControls) -// volDev = dev as IBasicVolumeControls; -// else if (dev is IHasVolumeDevice) -// volDev = (dev as IHasVolumeDevice).VolumeDevice; -// } -// CurrentVolumeControls = volDev; - -// // store the name and UI info for routes -// if (item.SourceKey != null) -// CurrentSingleSourceInfo = item; -// // And finally, set the "control". This will trigger event -// //CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device; - -// OnFeedback.FireUpdate(); - -// // report back when done -// if (successCallback != null) -// successCallback(); -// }, 0); // end of CTimer -// } - -// /// -// /// Will power the room on with the last-used source -// /// -// public void PowerOnToDefaultOrLastSource() -// { -// if (!EnablePowerOnToLastSource || LastSourceKey == null) -// return; -// RunRouteAction(LastSourceKey); -// } - -// /// -// /// Does what it says -// /// -// public override void SetDefaultLevels() -// { -// Debug.Console(0, this, "SetDefaultLevels not implemented"); -// } - -// /// -// /// -// /// -// /// -// /// -// bool DoRoute(SourceRouteListItem route) -// { -// IRoutingSinkNoSwitching dest = null; - -// if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase)) -// dest = DefaultAudioDevice; -// //else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase)) -// // dest = DefaultDisplay; -// else -// dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching; - -// if (dest == null) -// { -// Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey); -// return false; -// } - -// if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase)) -// { -// dest.ReleaseRoute(); -// if (dest is IPower) -// (dest as IPower).PowerOff(); -// } -// else -// { -// var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs; -// if (source == null) -// { -// Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey); -// return false; -// } -// dest.ReleaseAndMakeRoute(source, route.Type); -// } -// return true; -// } - -// public override void RoomVacatedForTimeoutPeriod(object o) -// { -// //Implement this -// } - -// } -//} \ No newline at end of file diff --git a/docs/Plugin Load Sequence.png b/docs/Plugin Load Sequence.png new file mode 100644 index 00000000..d7c4732c Binary files /dev/null and b/docs/Plugin Load Sequence.png differ