Merge pull request #496 from PepperDash/release/1.6.7

Release/1.6.7
This commit is contained in:
Neil Dorin
2020-11-16 12:01:44 -07:00
committed by GitHub
17 changed files with 1343 additions and 1188 deletions

View File

@@ -16,7 +16,6 @@ using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.DM; using PepperDash.Essentials.DM;
using PepperDash.Essentials.Fusion; using PepperDash.Essentials.Fusion;
using PepperDash.Essentials.Room.Config; using PepperDash.Essentials.Room.Config;
//using PepperDash.Essentials.Room.MobileControl;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.DeviceTypeInterfaces;
@@ -290,33 +289,14 @@ namespace PepperDash.Essentials
DeviceManager.ActivateAll(); DeviceManager.ActivateAll();
var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl; var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return; if (mobileControl == null) return;
mobileControl.LinkSystemMonitorToAppServer(); mobileControl.LinkSystemMonitorToAppServer();
//LinkSystemMonitorToAppServer();
} }
//void LinkSystemMonitorToAppServer()
//{
// var sysMon = DeviceManager.GetDeviceForKey("systemMonitor") as PepperDash.Essentials.Core.Monitoring.SystemMonitorController;
// var appServer = DeviceManager.GetDeviceForKey("appServer") as MobileControlSystemController;
// if (sysMon != null && appServer != null)
// {
// var key = sysMon.Key + "-" + appServer.Key;
// var messenger = new PepperDash.Essentials.AppServer.Messengers.SystemMonitorMessenger
// (key, sysMon, "/device/systemMonitor");
// messenger.RegisterWithAppServer(appServer);
// DeviceManager.AddDevice(messenger);
// }
//}
/// <summary> /// <summary>
/// Reads all devices from config and adds them to DeviceManager /// Reads all devices from config and adds them to DeviceManager
/// </summary> /// </summary>
@@ -394,11 +374,6 @@ namespace PepperDash.Essentials
if (newDev == null) if (newDev == null)
newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf); newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf);
//
//if (newDev == null)
// newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf);
//
if (newDev != null) if (newDev != null)
DeviceManager.AddDevice(newDev); DeviceManager.AddDevice(newDev);
else else
@@ -465,10 +440,6 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
// Mobile Control bridge
//var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom);
//AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
//DeviceManager.AddDevice(bridge);
CreateMobileControlBridge(room); CreateMobileControlBridge(room);
} }
@@ -480,10 +451,6 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1)); DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge..."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
// Mobile Control bridge
//var bridge = new MobileConrolEssentialsHuddleSpaceRoomBridge(room);
//AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
//DeviceManager.AddDevice(bridge);
CreateMobileControlBridge(room); CreateMobileControlBridge(room);
} }
@@ -504,34 +471,35 @@ namespace PepperDash.Essentials
private static void CreateMobileControlBridge(EssentialsRoomBase room) private static void CreateMobileControlBridge(EssentialsRoomBase room)
{ {
var mobileControl = DeviceManager.GetDeviceForKey("appServer") as IMobileControl; var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return; if (mobileControl == null) return;
mobileControl.CreateMobileControlRoomBridge(room); mobileControl.CreateMobileControlRoomBridge(room, mobileControl);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added..."); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added...");
} }
/// <summary> private static IMobileControl GetMobileControlDevice()
/// Helps add the post activation steps that link bridges to main controller {
/// </summary> var mobileControlList = DeviceManager.AllDevices.OfType<IMobileControl>().ToList();
/// <param name="bridge"></param>
//void AddBridgePostActivationHelper(MobileControlBridgeBase bridge) if (mobileControlList.Count > 1)
//{ {
// bridge.AddPostActivationAction(() => Debug.Console(0, Debug.ErrorLogLevel.Warning,
// { "Multiple instances of Mobile Control Server found.");
// var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as MobileControlSystemController;
// if (parent == null) return null;
// { }
// Debug.Console(0, bridge, "ERROR: Cannot connect app server room bridge. System controller not present");
// return; if (mobileControlList.Count > 0)
// } {
// Debug.Console(0, bridge, "Linking to parent controller"); return mobileControlList[0];
// bridge.AddParent(parent); }
// parent.AddBridge(bridge);
// }); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control not enabled for this system");
//} return null;
}
/// <summary> /// <summary>
/// Fires up a logo server if not already running /// Fires up a logo server if not already running

View File

@@ -393,6 +393,8 @@ namespace PepperDash.Essentials
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room"); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting down room");
RunRouteAction("roomOff"); RunRouteAction("roomOff");
VideoCodec.StopSharing();
VideoCodec.StandbyActivate();
} }
/// <summary> /// <summary>
@@ -590,6 +592,19 @@ namespace PepperDash.Essentials
OnFeedback.FireUpdate(); OnFeedback.FireUpdate();
if (OnFeedback.BoolValue)
{
if (VideoCodec.UsageTracker.InUseTracker.InUseFeedback.BoolValue)
{
Debug.Console(1, this, "Video Codec in use, deactivating standby on codec");
}
if (VideoCodec.StandbyIsOnFeedback.BoolValue)
{
VideoCodec.StandbyDeactivate();
}
}
// report back when done // report back when done
if (successCallback != null) if (successCallback != null)
successCallback(); successCallback();
@@ -652,6 +667,7 @@ namespace PepperDash.Essentials
dest.ReleaseRoute(); dest.ReleaseRoute();
if (dest is IHasPowerControl) if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff(); (dest as IHasPowerControl).PowerOff();
} }
else else
{ {
@@ -703,37 +719,44 @@ namespace PepperDash.Essentials
} }
/// <summary> /// <summary>
/// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch /// Setup the external sources for the Cisco Touch 10 devices that support IHasExternalSourceSwitch
/// </summary> /// </summary>
private void SetCodecExternalSources() private void SetCodecExternalSources()
{ {
var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching; var videoCodecWithExternalSwitching = VideoCodec as IHasExternalSourceSwitching;
if (videoCodecWithExternalSwitching == null) if (videoCodecWithExternalSwitching == null || !videoCodecWithExternalSwitching.ExternalSourceListEnabled)
{ {
return; return;
} }
string codecTieLine = ConfigReader.ConfigObject.TieLines.SingleOrDefault(x => x.DestinationKey == VideoCodec.Key).DestinationPort; try
videoCodecWithExternalSwitching.ClearExternalSources(); {
videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction; // Get the tie line that the external switcher is connected to
var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ; string codecInputConnectorName = ConfigReader.ConfigObject.TieLines.SingleOrDefault(
x => x.DestinationKey == VideoCodec.Key && x.DestinationPort == videoCodecWithExternalSwitching.ExternalSourceInputPort).DestinationPort;
foreach (var kvp in srcList) videoCodecWithExternalSwitching.ClearExternalSources();
{ videoCodecWithExternalSwitching.RunRouteAction = RunRouteAction;
var srcConfig = kvp.Value; var srcList = ConfigReader.ConfigObject.SourceLists.SingleOrDefault(x => x.Key == SourceListKey).Value.OrderBy(kv => kv.Value.Order); ;
if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff") foreach (var kvp in srcList)
{ {
var srcConfig = kvp.Value;
videoCodecWithExternalSwitching.AddExternalSource(codecTieLine, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop); if (kvp.Key != DefaultCodecRouteString && kvp.Key != "roomOff")
videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready); {
videoCodecWithExternalSwitching.AddExternalSource(codecInputConnectorName, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop);
videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready);
} }
} }
} }
catch (Exception e)
{
Debug.Console(2, this, "Error setting codec external sources: {0}", e);
}
}
private void SetCodecBranding() private void SetCodecBranding()
{ {

View File

@@ -1,38 +1,39 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO namespace PepperDash.Essentials.Core.CrestronIO
{ {
[Description("Wrapper class for Digital Input")] [Description("Wrapper class for Digital Input")]
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
{ {
public DigitalInput InputPort { get; private set; } public DigitalInput InputPort { get; private set; }
public BoolFeedback InputStateFeedback { get; private set; } public BoolFeedback InputStateFeedback { get; private set; }
Func<bool> InputStateFeedbackFunc Func<bool> InputStateFeedbackFunc
{ {
get get
{ {
return () => InputPort.State; return () => InputPort.State;
} }
} }
public GenericDigitalInputDevice(string key, string name, Func<IOPortConfig, DigitalInput> postActivationFunc, public GenericDigitalInputDevice(string key, string name, Func<IOPortConfig, DigitalInput> postActivationFunc,
IOPortConfig config) IOPortConfig config)
: base(key, name) : base(key, name)
{ {
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
AddPostActivationAction(() => AddPostActivationAction(() =>
{ {
@@ -40,15 +41,15 @@ namespace PepperDash.Essentials.Core.CrestronIO
InputPort.Register(); InputPort.Register();
InputPort.StateChange += InputPort_StateChange; InputPort.StateChange += InputPort_StateChange;
}); });
} }
#region Events #region Events
void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args) void InputPort_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
{ {
InputStateFeedback.FireUpdate(); InputStateFeedback.FireUpdate();
} }
@@ -81,7 +82,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
} }
if (ioPortDevice == null) if (ioPortDevice == null)
{ {
Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IRelayPorts Device", dc.PortDeviceKey); Debug.Console(0, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey);
return null; return null;
} }
@@ -99,13 +100,13 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Bridge Linking #region Bridge Linking
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{ {
var joinMap = new IDigitalInputJoinMap(joinStart); var joinMap = new IDigitalInputJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized)) if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<IDigitalInputJoinMap>(joinMapSerialized); joinMap = JsonConvert.DeserializeObject<IDigitalInputJoinMap>(joinMapSerialized);
if (bridge != null) if (bridge != null)
@@ -115,19 +116,19 @@ namespace PepperDash.Essentials.Core.CrestronIO
else else
{ {
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
} }
try try
{ {
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state // Link feedback for input state
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]); InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key); Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
Debug.Console(1, this, "Error: {0}", e); Debug.Console(1, this, "Error: {0}", e);
} }
} }
@@ -144,7 +145,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)
{ {
Debug.Console(1, "Factory Attempting to create new Generic Relay Device"); Debug.Console(1, "Factory Attempting to create new Generic Digital Input Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString()); var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
@@ -158,7 +159,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion #endregion
} }
} }

View File

@@ -4,15 +4,21 @@ using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core.CrestronIO namespace PepperDash.Essentials.Core.CrestronIO
{ {
/// <summary> /// <summary>
/// Represents a generic digital input deviced tied to a versiport /// Represents a generic digital input deviced tied to a versiport
/// </summary> /// </summary>
public class GenericVersiportDigitalInputDevice : EssentialsDevice, IDigitalInput public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
{ {
public Versiport InputPort { get; private set; } public Versiport InputPort { get; private set; }
@@ -26,17 +32,29 @@ namespace PepperDash.Essentials.Core.CrestronIO
} }
} }
public GenericVersiportDigitalInputDevice(string key, Versiport inputPort, IOPortConfig props): public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
base(key) base(key, name)
{ {
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
InputPort = inputPort;
InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
if (props.DisablePullUpResistor)
InputPort.DisablePullUpResistor = true;
InputPort.VersiportChange += new VersiportEventHandler(InputPort_VersiportChange);
Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", props.PortNumber, InputPort.DisablePullUpResistor); AddPostActivationAction(() =>
{
InputPort = postActivationFunc(config);
InputPort.Register();
InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
if (config.DisablePullUpResistor)
InputPort.DisablePullUpResistor = true;
InputPort.VersiportChange += InputPort_VersiportChange;
Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
});
} }
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
@@ -46,5 +64,105 @@ namespace PepperDash.Essentials.Core.CrestronIO
if(args.Event == eVersiportEvent.DigitalInChange) if(args.Event == eVersiportEvent.DigitalInChange)
InputStateFeedback.FireUpdate(); InputStateFeedback.FireUpdate();
} }
#region Bridge Linking
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new IDigitalInputJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<IDigitalInputJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
try
{
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
}
catch (Exception e)
{
Debug.Console(1, this, "Unable to link device '{0}'. Input is null", Key);
Debug.Console(1, this, "Error: {0}", e);
}
}
#endregion
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
{
IIOPorts ioPortDevice;
if (dc.PortDeviceKey.Equals("processor"))
{
if (!Global.ControlSystem.SupportsVersiport)
{
Debug.Console(0, "GetVersiportDigitalInput: Processor does not support Versiports");
return null;
}
ioPortDevice = Global.ControlSystem;
}
else
{
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
if (ioPortDev == null)
{
Debug.Console(0, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey);
return null;
}
ioPortDevice = ioPortDev;
}
if (ioPortDevice == null)
{
Debug.Console(0, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey);
return null;
}
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
{
Debug.Console(0, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
}
return ioPortDevice.VersiPorts[dc.PortNumber];
}
}
public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
{
public GenericVersiportDigitalInputDeviceFactory()
{
TypeNames = new List<string>() { "versiportinput" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new Generic Versiport Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());
if (props == null) return null;
var portDevice = new GenericVersiportDigitalInputDevice(dc.Key, dc.Name, GenericVersiportDigitalInputDevice.GetVersiportDigitalInput, props);
return portDevice;
}
} }
} }

View File

@@ -1,25 +1,25 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO namespace PepperDash.Essentials.Core.CrestronIO
{ {
/// <summary> /// <summary>
/// Represents a generic device controlled by relays /// Represents a generic device controlled by relays
/// </summary> /// </summary>
[Description("Wrapper class for a Relay")] [Description("Wrapper class for a Relay")]
public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput public class GenericRelayDevice : EssentialsBridgeableDevice, ISwitchedOutput
{ {
public Relay RelayOutput { get; private set; } public Relay RelayOutput { get; private set; }
public BoolFeedback OutputIsOnFeedback { get; private set; } public BoolFeedback OutputIsOnFeedback { get; private set; }
//Maintained for compatibility with PepperDash.Essentials.Core.Devices.CrestronProcessor //Maintained for compatibility with PepperDash.Essentials.Core.Devices.CrestronProcessor
@@ -94,11 +94,11 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Events #region Events
void RelayOutput_StateChange(Relay relay, RelayEventArgs args) void RelayOutput_StateChange(Relay relay, RelayEventArgs args)
{ {
OutputIsOnFeedback.FireUpdate(); OutputIsOnFeedback.FireUpdate();
} }
#endregion #endregion
#region Methods #region Methods
@@ -119,33 +119,33 @@ namespace PepperDash.Essentials.Core.CrestronIO
OpenRelay(); OpenRelay();
else else
CloseRelay(); CloseRelay();
} }
#endregion #endregion
#region ISwitchedOutput Members #region ISwitchedOutput Members
void ISwitchedOutput.On() void ISwitchedOutput.On()
{ {
CloseRelay(); CloseRelay();
} }
void ISwitchedOutput.Off() void ISwitchedOutput.Off()
{ {
OpenRelay(); OpenRelay();
} }
#endregion #endregion
#region Bridge Linking #region Bridge Linking
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{ {
var joinMap = new GenericRelayControllerJoinMap(joinStart); var joinMap = new GenericRelayControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey); var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized)) if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericRelayControllerJoinMap>(joinMapSerialized); joinMap = JsonConvert.DeserializeObject<GenericRelayControllerJoinMap>(joinMapSerialized);
if (bridge != null) if (bridge != null)
@@ -155,26 +155,26 @@ namespace PepperDash.Essentials.Core.CrestronIO
else else
{ {
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
} }
if (RelayOutput == null) if (RelayOutput == null)
{ {
Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key); Debug.Console(1, this, "Unable to link device '{0}'. Relay is null", Key);
return; return;
} }
Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); Debug.Console(1, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b => trilist.SetBoolSigAction(joinMap.Relay.JoinNumber, b =>
{ {
if (b) if (b)
CloseRelay(); CloseRelay();
else else
OpenRelay(); OpenRelay();
}); });
// feedback for relay state // feedback for relay state
OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay.JoinNumber]); OutputIsOnFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Relay.JoinNumber]);
} }
@@ -202,54 +202,54 @@ namespace PepperDash.Essentials.Core.CrestronIO
return portDevice; return portDevice;
/* /*
if (props.PortDeviceKey == "processor") if (props.PortDeviceKey == "processor")
portDevice = Global.ControlSystem as IRelayPorts; portDevice = Global.ControlSystem as IRelayPorts;
else else
portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts; portDevice = DeviceManager.GetDeviceForKey(props.PortDeviceKey) as IRelayPorts;
if (portDevice == null) if (portDevice == null)
Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key); Debug.Console(0, "Unable to add relay device with key '{0}'. Port Device does not support relays", key);
else else
{ {
var cs = (portDevice as CrestronControlSystem); var cs = (portDevice as CrestronControlSystem);
if (cs != null) if (cs != null)
{ {
// The relay is on a control system processor // The relay is on a control system processor
if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts) if (!cs.SupportsRelay || props.PortNumber > cs.NumberOfRelayPorts)
{ {
Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays"); Debug.Console(0, "Port Device: {0} does not support relays or does not have enough relays");
return null; return null;
} }
} }
else else
{ {
// The relay is on another device type // The relay is on another device type
if (props.PortNumber > portDevice.NumberOfRelayPorts) if (props.PortNumber > portDevice.NumberOfRelayPorts)
{ {
Debug.Console(0, "Port Device: {0} does not have enough relays"); Debug.Console(0, "Port Device: {0} does not have enough relays");
return null; return null;
} }
} }
Relay relay = portDevice.RelayPorts[props.PortNumber]; Relay relay = portDevice.RelayPorts[props.PortNumber];
if (!relay.Registered) if (!relay.Registered)
{ {
if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success) if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success)
return new GenericRelayDevice(key, relay); return new GenericRelayDevice(key, relay);
else else
Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey); Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey);
} }
else else
{ {
return new GenericRelayDevice(key, relay); return new GenericRelayDevice(key, relay);
} }
// Future: Check if portDevice is 3-series card or other non control system that supports versiports // Future: Check if portDevice is 3-series card or other non control system that supports versiports
} }
*/ */
} }
@@ -258,7 +258,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
#endregion #endregion
} }
} }

View File

@@ -8,11 +8,9 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// </summary> /// </summary>
public interface IMobileControl : IKeyed public interface IMobileControl : IKeyed
{ {
void CreateMobileControlRoomBridge(EssentialsRoomBase room); void CreateMobileControlRoomBridge(EssentialsRoomBase room, IMobileControl parent);
void LinkSystemMonitorToAppServer(); void LinkSystemMonitorToAppServer();
} }
/// <summary> /// <summary>
@@ -26,6 +24,8 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
string QrCodeUrl { get; } string QrCodeUrl { get; }
string QrCodeChecksum { get; }
string McServerUrl { get; } string McServerUrl { get; }
string RoomName { get; } string RoomName { get; }

View File

@@ -1,342 +1,355 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharpPro; using Crestron.SimplSharpPro;
using PepperDash.Core; using PepperDash.Core;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
public static class DeviceManager public static class DeviceManager
{ {
private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection(); public static event EventHandler<EventArgs> AllDevicesActivated;
private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
//public static List<Device> Devices { get { return _Devices; } } private static readonly CCriticalSection DeviceCriticalSection = new CCriticalSection();
//static List<Device> _Devices = new List<Device>(); private static readonly CEvent AllowAddDevicesCEvent = new CEvent(false, true);
//public static List<Device> Devices { get { return _Devices; } }
static readonly Dictionary<string, IKeyed> Devices = new Dictionary<string, IKeyed>(StringComparer.OrdinalIgnoreCase); //static List<Device> _Devices = new List<Device>();
/// <summary> static readonly Dictionary<string, IKeyed> Devices = new Dictionary<string, IKeyed>(StringComparer.OrdinalIgnoreCase);
/// Returns a copy of all the devices in a list
/// </summary> /// <summary>
public static List<IKeyed> AllDevices { get { return new List<IKeyed>(Devices.Values); } } /// Returns a copy of all the devices in a list
/// </summary>
public static bool AddDeviceEnabled; public static List<IKeyed> AllDevices { get { return new List<IKeyed>(Devices.Values); } }
public static void Initialize(CrestronControlSystem cs) public static bool AddDeviceEnabled;
{
AddDeviceEnabled = true; public static void Initialize(CrestronControlSystem cs)
CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices", {
ConsoleAccessLevelEnum.AccessOperator); AddDeviceEnabled = true;
CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks", CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices",
ConsoleAccessLevelEnum.AccessOperator); ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices", CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks",
ConsoleAccessLevelEnum.AccessOperator); ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "", CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices",
ConsoleAccessLevelEnum.AccessOperator); ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "",
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator); ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)), "devprops", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive", CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)), "devmethods", "", ConsoleAccessLevelEnum.AccessOperator);
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator); "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
} CrestronConsole.AddNewConsoleCommand(s => SetDeviceStreamDebugging(s), "setdevicestreamdebug", "set comm debug [deviceKey] [off/rx/tx/both] ([minutes])", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => DisableAllDeviceStreamDebugging(), "disableallstreamdebug", "disables stream debugging on all devices", ConsoleAccessLevelEnum.AccessOperator);
/// <summary> }
/// Calls activate steps on all Device class items
/// </summary> /// <summary>
public static void ActivateAll() /// Calls activate steps on all Device class items
{ /// </summary>
try public static void ActivateAll()
{ {
DeviceCriticalSection.Enter(); try
AddDeviceEnabled = false; {
// PreActivate all devices DeviceCriticalSection.Enter();
foreach (var d in Devices.Values) AddDeviceEnabled = false;
{ // PreActivate all devices
try foreach (var d in Devices.Values)
{ {
if (d is Device) try
(d as Device).PreActivate(); {
} if (d is Device)
catch (Exception e) (d as Device).PreActivate();
{ }
Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e); catch (Exception e)
} {
} Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e);
}
// Activate all devices }
foreach (var d in Devices.Values)
{ // Activate all devices
try foreach (var d in Devices.Values)
{ {
if (d is Device) try
(d as Device).Activate(); {
} if (d is Device)
catch (Exception e) (d as Device).Activate();
{ }
Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e); catch (Exception e)
} {
} Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e);
}
// PostActivate all devices }
foreach (var d in Devices.Values)
{ // PostActivate all devices
try foreach (var d in Devices.Values)
{ {
if (d is Device) try
(d as Device).PostActivate(); {
} if (d is Device)
catch (Exception e) (d as Device).PostActivate();
{ }
Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e); catch (Exception e)
} {
} Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e);
} }
finally }
{
DeviceCriticalSection.Leave(); OnAllDevicesActivated();
} }
} finally
{
/// <summary> DeviceCriticalSection.Leave();
/// Calls activate on all Device class items }
/// </summary> }
public static void DeactivateAll()
{ private static void OnAllDevicesActivated()
try {
{ var handler = AllDevicesActivated;
DeviceCriticalSection.Enter(); if (handler != null)
foreach (var d in Devices.Values.OfType<Device>()) {
{ handler(null, new EventArgs());
d.Deactivate(); }
} }
}
finally /// <summary>
{ /// Calls activate on all Device class items
DeviceCriticalSection.Leave(); /// </summary>
} public static void DeactivateAll()
} {
try
//static void ListMethods(string devKey) {
//{ DeviceCriticalSection.Enter();
// var dev = GetDeviceForKey(devKey); foreach (var d in Devices.Values.OfType<Device>())
// if(dev != null) {
// { d.Deactivate();
// var type = dev.GetType().GetCType(); }
// var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance); }
// var sb = new StringBuilder(); finally
// sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length)); {
// foreach (var m in methods) DeviceCriticalSection.Leave();
// { }
// sb.Append(string.Format("{0}(", m.Name)); }
// var pars = m.GetParameters();
// foreach (var p in pars) //static void ListMethods(string devKey)
// sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name)); //{
// sb.AppendLine(")"); // var dev = GetDeviceForKey(devKey);
// } // if(dev != null)
// CrestronConsole.ConsoleCommandResponse(sb.ToString()); // {
// } // var type = dev.GetType().GetCType();
//} // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance);
// var sb = new StringBuilder();
private static void ListDevices(string s) // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length));
{ // foreach (var m in methods)
Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count); // {
var sorted = Devices.Values.ToList(); // sb.Append(string.Format("{0}(", m.Name));
sorted.Sort((a, b) => a.Key.CompareTo(b.Key)); // var pars = m.GetParameters();
// foreach (var p in pars)
foreach (var d in sorted) // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name));
{ // sb.AppendLine(")");
var name = d is IKeyName ? (d as IKeyName).Name : "---"; // }
Debug.Console(0, " [{0}] {1}", d.Key, name); // CrestronConsole.ConsoleCommandResponse(sb.ToString());
} // }
} //}
private static void ListDeviceFeedbacks(string devKey) private static void ListDevices(string s)
{ {
var dev = GetDeviceForKey(devKey); Debug.Console(0, "{0} Devices registered with Device Manager:", Devices.Count);
if (dev == null) var sorted = Devices.Values.ToList();
{ sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
Debug.Console(0, "Device '{0}' not found", devKey);
return; foreach (var d in sorted)
} {
var statusDev = dev as IHasFeedback; var name = d is IKeyName ? (d as IKeyName).Name : "---";
if (statusDev == null) Debug.Console(0, " [{0}] {1}", d.Key, name);
{ }
Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey); }
return;
} private static void ListDeviceFeedbacks(string devKey)
statusDev.DumpFeedbacksToConsole(true); {
} var dev = GetDeviceForKey(devKey);
if (dev == null)
//static void ListDeviceCommands(string devKey) {
//{ Debug.Console(0, "Device '{0}' not found", devKey);
// var dev = GetDeviceForKey(devKey); return;
// if (dev == null) }
// { var statusDev = dev as IHasFeedback;
// Debug.Console(0, "Device '{0}' not found", devKey); if (statusDev == null)
// return; {
// } Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey);
// Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey); return;
//} }
statusDev.DumpFeedbacksToConsole(true);
private static void ListDeviceCommStatuses(string input) }
{
var sb = new StringBuilder(); //static void ListDeviceCommands(string devKey)
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>()) //{
{ // var dev = GetDeviceForKey(devKey);
sb.Append(string.Format("{0}: {1}\r", dev, // if (dev == null)
dev.CommunicationMonitor.Status)); // {
} // Debug.Console(0, "Device '{0}' not found", devKey);
CrestronConsole.ConsoleCommandResponse(sb.ToString()); // return;
} // }
// Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey);
//}
//static void DoDeviceCommand(string command)
//{ private static void ListDeviceCommStatuses(string input)
// Debug.Console(0, "Not yet implemented. Stay tuned"); {
//} var sb = new StringBuilder();
foreach (var dev in Devices.Values.OfType<ICommunicationMonitor>())
public static void AddDevice(IKeyed newDev) {
{ sb.Append(string.Format("{0}: {1}\r", dev,
try dev.CommunicationMonitor.Status));
{ }
if (!DeviceCriticalSection.TryEnter()) CrestronConsole.ConsoleCommandResponse(sb.ToString());
{ }
Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again");
return;
} //static void DoDeviceCommand(string command)
// Check for device with same key //{
//var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase)); // Debug.Console(0, "Not yet implemented. Stay tuned");
////// If it exists, remove or warn?? //}
//if (existingDevice != null)
public static void AddDevice(IKeyed newDev)
if (!AddDeviceEnabled) {
{ try
Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed."); {
return; if (!DeviceCriticalSection.TryEnter())
} {
Debug.Console(0, Debug.ErrorLogLevel.Error, "Currently unable to add devices to Device Manager. Please try again");
if (Devices.ContainsKey(newDev.Key)) return;
{ }
Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager"); // Check for device with same key
return; //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase));
} ////// If it exists, remove or warn??
Devices.Add(newDev.Key, newDev); //if (existingDevice != null)
//if (!(_Devices.Contains(newDev)))
// _Devices.Add(newDev); if (!AddDeviceEnabled)
} {
finally Debug.Console(0, Debug.ErrorLogLevel.Error, "All devices have been activated. Adding new devices is not allowed.");
{ return;
DeviceCriticalSection.Leave(); }
}
} if (Devices.ContainsKey(newDev.Key))
{
public static void AddDevice(IEnumerable<IKeyed> devicesToAdd) Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager");
{ return;
try }
{ Devices.Add(newDev.Key, newDev);
if (!DeviceCriticalSection.TryEnter()) //if (!(_Devices.Contains(newDev)))
{ // _Devices.Add(newDev);
Debug.Console(0, Debug.ErrorLogLevel.Error, }
"Currently unable to add devices to Device Manager. Please try again"); finally
return; {
} DeviceCriticalSection.Leave();
if (!AddDeviceEnabled) }
{ }
Debug.Console(0, Debug.ErrorLogLevel.Error,
"All devices have been activated. Adding new devices is not allowed."); public static void AddDevice(IEnumerable<IKeyed> devicesToAdd)
return; {
} try
{
foreach (var dev in devicesToAdd) if (!DeviceCriticalSection.TryEnter())
{ {
try Debug.Console(0, Debug.ErrorLogLevel.Error,
{ "Currently unable to add devices to Device Manager. Please try again");
Devices.Add(dev.Key, dev); return;
} }
catch (ArgumentException ex) if (!AddDeviceEnabled)
{ {
Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}", Debug.Console(0, Debug.ErrorLogLevel.Error,
dev.Key, ex.Message, ex.StackTrace); "All devices have been activated. Adding new devices is not allowed.");
} return;
} }
}
finally foreach (var dev in devicesToAdd)
{ {
DeviceCriticalSection.Leave(); try
} {
} Devices.Add(dev.Key, dev);
}
public static void RemoveDevice(IKeyed newDev) catch (ArgumentException ex)
{ {
try Debug.Console(0, "Error adding device with key {0} to Device Manager: {1}\r\nStack Trace: {2}",
{ dev.Key, ex.Message, ex.StackTrace);
DeviceCriticalSection.Enter(); }
if (newDev == null) }
return; }
if (Devices.ContainsKey(newDev.Key)) finally
Devices.Remove(newDev.Key); {
//if (_Devices.Contains(newDev)) DeviceCriticalSection.Leave();
// _Devices.Remove(newDev); }
else }
Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
} public static void RemoveDevice(IKeyed newDev)
finally {
{ try
DeviceCriticalSection.Leave(); {
} DeviceCriticalSection.Enter();
} if (newDev == null)
return;
public static IEnumerable<string> GetDeviceKeys() if (Devices.ContainsKey(newDev.Key))
{ Devices.Remove(newDev.Key);
//return _Devices.Select(d => d.Key).ToList(); //if (_Devices.Contains(newDev))
return Devices.Keys; // _Devices.Remove(newDev);
} else
Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key);
public static IEnumerable<IKeyed> GetDevices() }
{ finally
//return _Devices.Select(d => d.Key).ToList(); {
return Devices.Values; DeviceCriticalSection.Leave();
} }
}
public static IKeyed GetDeviceForKey(string key)
{ public static IEnumerable<string> GetDeviceKeys()
//return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); {
if (key != null && Devices.ContainsKey(key)) //return _Devices.Select(d => d.Key).ToList();
return Devices[key]; return Devices.Keys;
}
return null;
} public static IEnumerable<IKeyed> GetDevices()
{
/// <summary> //return _Devices.Select(d => d.Key).ToList();
/// Console handler that simulates com port data receive return Devices.Values;
/// </summary> }
/// <param name="s"></param>
public static void SimulateComReceiveOnDevice(string s) public static IKeyed GetDeviceForKey(string key)
{ {
// devcomsim:1 xyzabc //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
var match = Regex.Match(s, @"(\S*)\s*(.*)"); if (key != null && Devices.ContainsKey(key))
if (match.Groups.Count < 3) return Devices[key];
{
CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P <device key> <string to send>"); return null;
return; }
}
//Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value); /// <summary>
/// Console handler that simulates com port data receive
var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController; /// </summary>
if (com == null) /// <param name="s"></param>
{ public static void SimulateComReceiveOnDevice(string s)
CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value); {
return; // devcomsim:1 xyzabc
} var match = Regex.Match(s, @"(\S*)\s*(.*)");
com.SimulateReceive(match.Groups[2].Value); if (match.Groups.Count < 3)
{
CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P <device key> <string to send>");
return;
}
//Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value);
var com = GetDeviceForKey(match.Groups[1].Value) as ComPortController;
if (com == null)
{
CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value);
return;
}
com.SimulateReceive(match.Groups[2].Value);
} }
/// <summary> /// <summary>
@@ -366,82 +379,82 @@ namespace PepperDash.Essentials.Core
Debug.Console(0, "{0}", routingOutputPort.Key); Debug.Console(0, "{0}", routingOutputPort.Key);
} }
} }
} }
/// <summary> /// <summary>
/// Attempts to set the debug level of a device /// Attempts to set the debug level of a device
/// </summary> /// </summary>
/// <param name="s"></param> /// <param name="s"></param>
public static void SetDeviceStreamDebugging(string s) public static void SetDeviceStreamDebugging(string s)
{ {
var args = s.Split(' '); var args = s.Split(' ');
var deviceKey = args[0]; var deviceKey = args[0];
var setting = args[1]; var setting = args[1];
var timeout= String.Empty; var timeout= String.Empty;
if (args.Length >= 3) if (args.Length >= 3)
{ {
timeout = args[2]; timeout = args[2];
} }
var device = GetDeviceForKey(deviceKey) as IStreamDebugging; var device = GetDeviceForKey(deviceKey) as IStreamDebugging;
if (device == null) if (device == null)
{ {
Debug.Console(0, "Unable to get device with key: {0}", deviceKey); Debug.Console(0, "Unable to get device with key: {0}", deviceKey);
return; return;
} }
eStreamDebuggingSetting debugSetting; eStreamDebuggingSetting debugSetting;
try try
{ {
debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true); debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true);
} }
catch catch
{ {
Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both"); Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both");
return; return;
} }
if (!string.IsNullOrEmpty(timeout)) if (!string.IsNullOrEmpty(timeout))
{ {
try try
{ {
var min = Convert.ToUInt32(timeout); var min = Convert.ToUInt32(timeout);
device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min); device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min);
Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min); Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min);
} }
catch (Exception e) catch (Exception e)
{ {
Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e); Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e);
} }
} }
else else
{ {
device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting); device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting);
Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting); Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting);
} }
} }
/// <summary> /// <summary>
/// Sets stream debugging settings to off for all devices /// Sets stream debugging settings to off for all devices
/// </summary> /// </summary>
public static void DisableAllDeviceStreamDebugging() public static void DisableAllDeviceStreamDebugging()
{ {
foreach (var device in AllDevices) foreach (var device in AllDevices)
{ {
var streamDevice = device as IStreamDebugging; var streamDevice = device as IStreamDebugging;
if (streamDevice != null) if (streamDevice != null)
{ {
streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off); streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
} }
} }
} }
} }
} }

View File

@@ -88,8 +88,12 @@ namespace PepperDash.Essentials.Core.Privacy
else else
Debug.Console(0, this, "Unable to add Red LED device"); Debug.Console(0, this, "Unable to add Red LED device");
DeviceManager.AllDevicesActivated += (o, a) =>
{
CheckPrivacyMode();
};
AddPostActivationAction(() => { AddPostActivationAction(() => {
CheckPrivacyMode();
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange;
PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; PrivacyDevice.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange;
}); });

View File

@@ -14,7 +14,7 @@
<tags>crestron 3series 4series</tags> <tags>crestron 3series 4series</tags>
<repository type="git" url="https://github.com/PepperDash/Essentials"/> <repository type="git" url="https://github.com/PepperDash/Essentials"/>
<dependencies> <dependencies>
<dependency id="PepperDashCore" version="[1.0, 1.1)"/> <dependency id="PepperDashCore" version="[1.0.43, 1.1.0)"/>
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

View File

@@ -1,58 +1,58 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler; using Crestron.SimplSharp.Scheduler;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Devices; using PepperDash.Essentials.Core.Devices;
using PepperDash.Essentials.Core.DeviceTypeInterfaces; using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public abstract class EssentialsRoomBase : ReconfigurableDevice public abstract class EssentialsRoomBase : ReconfigurableDevice
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public BoolFeedback OnFeedback { get; private set; } public BoolFeedback OnFeedback { get; private set; }
/// <summary> /// <summary>
/// Fires when the RoomOccupancy object is set /// Fires when the RoomOccupancy object is set
/// </summary> /// </summary>
public event EventHandler<EventArgs> RoomOccupancyIsSet; public event EventHandler<EventArgs> RoomOccupancyIsSet;
public BoolFeedback IsWarmingUpFeedback { get; private set; } public BoolFeedback IsWarmingUpFeedback { get; private set; }
public BoolFeedback IsCoolingDownFeedback { get; private set; } public BoolFeedback IsCoolingDownFeedback { get; private set; }
public IOccupancyStatusProvider RoomOccupancy { get; private set; } public IOccupancyStatusProvider RoomOccupancy { get; private set; }
public bool OccupancyStatusProviderIsRemote { get; private set; } public bool OccupancyStatusProviderIsRemote { get; private set; }
protected abstract Func<bool> IsWarmingFeedbackFunc { get; } protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
protected abstract Func<bool> IsCoolingFeedbackFunc { get; } protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
/// <summary> /// <summary>
/// Indicates if this room is Mobile Control Enabled /// Indicates if this room is Mobile Control Enabled
/// </summary> /// </summary>
public bool IsMobileControlEnabled { get; private set; } public bool IsMobileControlEnabled { get; private set; }
/// <summary> /// <summary>
/// The bridge for this room if Mobile Control is enabled /// The bridge for this room if Mobile Control is enabled
/// </summary> /// </summary>
public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; } public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; }
/// <summary> /// <summary>
/// The config name of the source list /// The config name of the source list
/// </summary> /// </summary>
/// ///
protected string _SourceListKey; protected string _SourceListKey;
public virtual string SourceListKey { public virtual string SourceListKey {
get get
{ {
@@ -63,306 +63,306 @@ namespace PepperDash.Essentials.Core
_SourceListKey = value; _SourceListKey = value;
} }
} }
/// <summary> /// <summary>
/// Timer used for informing the UIs of a shutdown /// Timer used for informing the UIs of a shutdown
/// </summary> /// </summary>
public SecondsCountdownTimer ShutdownPromptTimer { get; private set; } public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public int ShutdownPromptSeconds { get; set; } public int ShutdownPromptSeconds { get; set; }
public int ShutdownVacancySeconds { get; set; } public int ShutdownVacancySeconds { get; set; }
public eShutdownType ShutdownType { get; private set; } public eShutdownType ShutdownType { get; private set; }
public EssentialsRoomEmergencyBase Emergency { get; set; } public EssentialsRoomEmergencyBase Emergency { get; set; }
public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; } public Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; set; }
public string LogoUrlLightBkgnd { get; set; } public string LogoUrlLightBkgnd { get; set; }
public string LogoUrlDarkBkgnd { get; set; } public string LogoUrlDarkBkgnd { get; set; }
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; } protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
public eVacancyMode VacancyMode { get; private set; } public eVacancyMode VacancyMode { get; private set; }
/// <summary> /// <summary>
/// Seconds after vacancy prompt is displayed until shutdown /// Seconds after vacancy prompt is displayed until shutdown
/// </summary> /// </summary>
protected int RoomVacancyShutdownSeconds; protected int RoomVacancyShutdownSeconds;
/// <summary> /// <summary>
/// Seconds after vacancy detected until prompt is displayed /// Seconds after vacancy detected until prompt is displayed
/// </summary> /// </summary>
protected int RoomVacancyShutdownPromptSeconds; protected int RoomVacancyShutdownPromptSeconds;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
protected abstract Func<bool> OnFeedbackFunc { get; } protected abstract Func<bool> OnFeedbackFunc { get; }
protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>(); protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>();
/// <summary> /// <summary>
/// When volume control devices change, should we zero the one that we are leaving? /// When volume control devices change, should we zero the one that we are leaving?
/// </summary> /// </summary>
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; } public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
public EssentialsRoomBase(DeviceConfig config) public EssentialsRoomBase(DeviceConfig config)
: base(config) : base(config)
{ {
// Setup the ShutdownPromptTimer // Setup the ShutdownPromptTimer
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer"); ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) => ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
{ {
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue) if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
ShutdownType = eShutdownType.None; ShutdownType = eShutdownType.None;
}; };
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
ShutdownPromptSeconds = 60; ShutdownPromptSeconds = 60;
ShutdownVacancySeconds = 120; ShutdownVacancySeconds = 120;
ShutdownType = eShutdownType.None; ShutdownType = eShutdownType.None;
RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer"); RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
//RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) => //RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
//{ //{
// if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue) // if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
// ShutdownType = ShutdownType.Vacancy; // ShutdownType = ShutdownType.Vacancy;
//}; //};
RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
VacancyMode = eVacancyMode.None; VacancyMode = eVacancyMode.None;
OnFeedback = new BoolFeedback(OnFeedbackFunc); OnFeedback = new BoolFeedback(OnFeedbackFunc);
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc); IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc); IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
AddPostActivationAction(() => AddPostActivationAction(() =>
{ {
if (RoomOccupancy != null) if (RoomOccupancy != null)
OnRoomOccupancyIsSet(); OnRoomOccupancyIsSet();
}); });
} }
public override bool CustomActivate() public override bool CustomActivate()
{ {
SetUpMobileControl(); SetUpMobileControl();
return base.CustomActivate(); return base.CustomActivate();
} }
/// <summary> /// <summary>
/// If mobile control is enabled, sets the appropriate properties /// If mobile control is enabled, sets the appropriate properties
/// </summary> /// </summary>
void SetUpMobileControl() void SetUpMobileControl()
{ {
var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key); var mcBridgeKey = string.Format("mobileControlBridge-{0}", Key);
var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey); var mcBridge = DeviceManager.GetDeviceForKey(mcBridgeKey);
if (mcBridge == null) if (mcBridge == null)
{ {
Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room."); Debug.Console(1, this, "*********************Mobile Control Bridge Not found for this room.");
IsMobileControlEnabled = false; IsMobileControlEnabled = false;
return; return;
} }
else else
{ {
MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge; MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge;
Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room"); Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room");
IsMobileControlEnabled = true; IsMobileControlEnabled = true;
} }
} }
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e) void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
{ {
switch (VacancyMode) switch (VacancyMode)
{ {
case eVacancyMode.None: case eVacancyMode.None:
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
break; break;
case eVacancyMode.InInitialVacancy: case eVacancyMode.InInitialVacancy:
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning); StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
break; break;
case eVacancyMode.InShutdownWarning: case eVacancyMode.InShutdownWarning:
{ {
StartShutdown(eShutdownType.Vacancy); StartShutdown(eShutdownType.Vacancy);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy."); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Shutting Down due to vacancy.");
break; break;
} }
default: default:
break; break;
} }
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="type"></param>
public void StartShutdown(eShutdownType type) public void StartShutdown(eShutdownType type)
{ {
// Check for shutdowns running. Manual should override other shutdowns // Check for shutdowns running. Manual should override other shutdowns
if (type == eShutdownType.Manual) if (type == eShutdownType.Manual)
ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds; ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
else if (type == eShutdownType.Vacancy) else if (type == eShutdownType.Vacancy)
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds; ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
ShutdownType = type; ShutdownType = type;
ShutdownPromptTimer.Start(); ShutdownPromptTimer.Start();
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "ShutdownPromptTimer Started. Type: {0}. Seconds: {1}", ShutdownType, ShutdownPromptTimer.SecondsToCount);
} }
public void StartRoomVacancyTimer(eVacancyMode mode) public void StartRoomVacancyTimer(eVacancyMode mode)
{ {
if (mode == eVacancyMode.None) if (mode == eVacancyMode.None)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds; RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
else if (mode == eVacancyMode.InInitialVacancy) else if (mode == eVacancyMode.InInitialVacancy)
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds; RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
else if (mode == eVacancyMode.InShutdownWarning) else if (mode == eVacancyMode.InShutdownWarning)
RoomVacancyShutdownTimer.SecondsToCount = 60; RoomVacancyShutdownTimer.SecondsToCount = 60;
VacancyMode = mode; VacancyMode = mode;
RoomVacancyShutdownTimer.Start(); RoomVacancyShutdownTimer.Start();
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Vacancy Timer Started. Mode: {0}. Seconds: {1}", VacancyMode, RoomVacancyShutdownTimer.SecondsToCount);
} }
/// <summary> /// <summary>
/// Resets the vacancy mode and shutsdwon the room /// Resets the vacancy mode and shutsdwon the room
/// </summary> /// </summary>
public void Shutdown() public void Shutdown()
{ {
VacancyMode = eVacancyMode.None; VacancyMode = eVacancyMode.None;
EndShutdown(); EndShutdown();
} }
/// <summary> /// <summary>
/// This method is for the derived class to define it's specific shutdown /// This method is for the derived class to define it's specific shutdown
/// requirements but should not be called directly. It is called by Shutdown() /// requirements but should not be called directly. It is called by Shutdown()
/// </summary> /// </summary>
protected abstract void EndShutdown(); protected abstract void EndShutdown();
/// <summary> /// <summary>
/// Override this to implement a default volume level(s) method /// Override this to implement a default volume level(s) method
/// </summary> /// </summary>
public abstract void SetDefaultLevels(); public abstract void SetDefaultLevels();
/// <summary> /// <summary>
/// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
/// </summary> /// </summary>
/// <param name="statusProvider"></param> /// <param name="statusProvider"></param>
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes) public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
{ {
if (statusProvider == null) if (statusProvider == null)
{ {
Debug.Console(0, this, "ERROR: Occupancy sensor device is null"); Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
return; return;
} }
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Room Occupancy set to device: '{0}'", (statusProvider as Device).Key);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Timeout Minutes from Config is: {0}", timeoutMinutes);
// If status provider is fusion, set flag to remote // If status provider is fusion, set flag to remote
if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase) if (statusProvider is Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
OccupancyStatusProviderIsRemote = true; OccupancyStatusProviderIsRemote = true;
if(timeoutMinutes > 0) if(timeoutMinutes > 0)
RoomVacancyShutdownSeconds = timeoutMinutes * 60; RoomVacancyShutdownSeconds = timeoutMinutes * 60;
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds); Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "RoomVacancyShutdownSeconds set to {0}", RoomVacancyShutdownSeconds);
RoomOccupancy = statusProvider; RoomOccupancy = statusProvider;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange; RoomOccupancy.RoomIsOccupiedFeedback.OutputChange -= RoomIsOccupiedFeedback_OutputChange;
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
OnRoomOccupancyIsSet(); OnRoomOccupancyIsSet();
} }
void OnRoomOccupancyIsSet() void OnRoomOccupancyIsSet()
{ {
var handler = RoomOccupancyIsSet; var handler = RoomOccupancyIsSet;
if (handler != null) if (handler != null)
handler(this, new EventArgs()); handler(this, new EventArgs());
} }
/// <summary> /// <summary>
/// To allow base class to power room on to last source /// To allow base class to power room on to last source
/// </summary> /// </summary>
public abstract void PowerOnToDefaultOrLastSource(); public abstract void PowerOnToDefaultOrLastSource();
/// <summary> /// <summary>
/// To allow base class to power room on to default source /// To allow base class to power room on to default source
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public abstract bool RunDefaultPresentRoute(); public abstract bool RunDefaultPresentRoute();
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e) void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
{ {
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false) if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
{ {
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected"); Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Vacancy Detected");
// Trigger the timer when the room is vacant // Trigger the timer when the room is vacant
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
} }
else else
{ {
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected"); Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Notice: Occupancy Detected");
// Reset the timer when the room is occupied // Reset the timer when the room is occupied
RoomVacancyShutdownTimer.Cancel(); RoomVacancyShutdownTimer.Cancel();
} }
} }
/// <summary> /// <summary>
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed /// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
/// </summary> /// </summary>
/// <param name="o"></param> /// <param name="o"></param>
public abstract void RoomVacatedForTimeoutPeriod(object o); public abstract void RoomVacatedForTimeoutPeriod(object o);
} }
/// <summary> /// <summary>
/// To describe the various ways a room may be shutting down /// To describe the various ways a room may be shutting down
/// </summary> /// </summary>
public enum eShutdownType public enum eShutdownType
{ {
None = 0, None = 0,
External, External,
Manual, Manual,
Vacancy Vacancy
} }
public enum eVacancyMode public enum eVacancyMode
{ {
None = 0, None = 0,
InInitialVacancy, InInitialVacancy,
InShutdownWarning InShutdownWarning
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
public enum eWarmingCoolingMode public enum eWarmingCoolingMode
{ {
None, None,
Warming, Warming,
Cooling Cooling
} }
public abstract class EssentialsRoomEmergencyBase : IKeyed public abstract class EssentialsRoomEmergencyBase : IKeyed
{ {
public string Key { get; private set; } public string Key { get; private set; }
public EssentialsRoomEmergencyBase(string key) public EssentialsRoomEmergencyBase(string key)
{ {
Key = key; Key = key;
} }
} }
} }

View File

@@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core
/// <summary> /// <summary>
/// For fixed-source endpoint devices /// For fixed-source endpoint devices
/// </summary> /// </summary>
[Obsolete] [Obsolete("Please switch to IRoutingSink")]
public interface IRoutingSinkNoSwitching : IRoutingSink public interface IRoutingSinkNoSwitching : IRoutingSink
{ {

View File

@@ -11,6 +11,7 @@ namespace PepperDash.Essentials.Devices.Common.Codec
public interface IHasExternalSourceSwitching public interface IHasExternalSourceSwitching
{ {
bool ExternalSourceListEnabled { get; } bool ExternalSourceListEnabled { get; }
string ExternalSourceInputPort { get; }
void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type); void AddExternalSource(string connectorId, string key, string name, eExternalSourceType type);
void SetExternalSourceState(string key, eExternalSourceMode mode); void SetExternalSourceState(string key, eExternalSourceMode mode);
void ClearExternalSources(); void ClearExternalSources();

View File

@@ -407,6 +407,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
CreateOsdSource(); CreateOsdSource();
ExternalSourceListEnabled = props.ExternalSourceListEnabled; ExternalSourceListEnabled = props.ExternalSourceListEnabled;
ExternalSourceInputPort = props.ExternalSourceInputPort;
if (props.UiBranding == null) if (props.UiBranding == null)
{ {
@@ -416,6 +417,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
props.UiBranding.BrandingUrl); props.UiBranding.BrandingUrl);
BrandingEnabled = props.UiBranding.Enable; BrandingEnabled = props.UiBranding.Enable;
_brandingUrl = props.UiBranding.BrandingUrl; _brandingUrl = props.UiBranding.BrandingUrl;
} }
@@ -1917,7 +1919,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
#region IHasExternalSourceSwitching Members #region IHasExternalSourceSwitching Members
/// <summary> /// <summary>
/// Weather the Cisco supports External Source Lists or not /// Wheather the Cisco supports External Source Lists or not
/// </summary> /// </summary>
public bool ExternalSourceListEnabled public bool ExternalSourceListEnabled
{ {
@@ -1925,6 +1927,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
private set; private set;
} }
/// <summary>
/// The name of the RoutingInputPort to which the upstream external switcher is connected
/// </summary>
public string ExternalSourceInputPort { get; private set; }
public bool BrandingEnabled { get; private set; } public bool BrandingEnabled { get; private set; }
private string _brandingUrl; private string _brandingUrl;
private bool _sendMcUrl; private bool _sendMcUrl;
@@ -2102,7 +2109,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
public CiscoSparkCodecFactory() public CiscoSparkCodecFactory()
{ {
TypeNames = new List<string>() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit" }; TypeNames = new List<string>() { "ciscospark", "ciscowebex", "ciscowebexpro", "ciscoroomkit", "ciscosparkpluscodec" };
} }
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)

View File

@@ -31,9 +31,18 @@ namespace PepperDash.Essentials.Devices.Common.Codec
[JsonProperty("sharing")] [JsonProperty("sharing")]
public SharingProperties Sharing { get; set; } public SharingProperties Sharing { get; set; }
/// <summary>
/// Enables external source switching capability
/// </summary>
[JsonProperty("externalSourceListEnabled")] [JsonProperty("externalSourceListEnabled")]
public bool ExternalSourceListEnabled { get; set; } public bool ExternalSourceListEnabled { get; set; }
/// <summary>
/// The name of the routing input port on the codec to which the external switch is connected
/// </summary>
[JsonProperty("externalSourceInputPort")]
public string ExternalSourceInputPort { get; set; }
/// <summary> /// <summary>
/// Optionsal property to set the limit of any phonebook queries for directory or searching /// Optionsal property to set the limit of any phonebook queries for directory or searching
/// </summary> /// </summary>

View File

@@ -1,131 +1,131 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
/// <summary> /// <summary>
/// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode /// This class exists to capture serialized data sent back by a Cisco codec in JSON output mode
/// </summary> /// </summary>
public class CiscoCodecEvents public class CiscoCodecEvents
{ {
public class CauseValue public class CauseValue
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CauseType public class CauseType
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CauseString public class CauseString
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class OrigCallDirection public class OrigCallDirection
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class RemoteURI public class RemoteURI
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class DisplayName public class DisplayName
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CallId public class CallId
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CauseCode public class CauseCode
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CauseOrigin public class CauseOrigin
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class Protocol public class Protocol
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class Duration public class Duration
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CallType public class CallType
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CallRate public class CallRate
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class Encryption public class Encryption
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class RequestedURI public class RequestedURI
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class PeopleCountAverage public class PeopleCountAverage
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class CallDisconnect public class CallDisconnect
{ {
public string id { get; set; } public string id { get; set; }
public CauseValue CauseValue { get; set; } public CauseValue CauseValue { get; set; }
public CauseType CauseType { get; set; } public CauseType CauseType { get; set; }
public CauseString CauseString { get; set; } public CauseString CauseString { get; set; }
public OrigCallDirection OrigCallDirection { get; set; } public OrigCallDirection OrigCallDirection { get; set; }
public RemoteURI RemoteURI { get; set; } public RemoteURI RemoteURI { get; set; }
public DisplayName DisplayName { get; set; } public DisplayName DisplayName { get; set; }
public CallId CallId { get; set; } public CallId CallId { get; set; }
public CauseCode CauseCode { get; set; } public CauseCode CauseCode { get; set; }
public CauseOrigin CauseOrigin { get; set; } public CauseOrigin CauseOrigin { get; set; }
public Protocol Protocol { get; set; } public Protocol Protocol { get; set; }
public Duration Duration { get; set; } public Duration Duration { get; set; }
public CallType CallType { get; set; } public CallType CallType { get; set; }
public CallRate CallRate { get; set; } public CallRate CallRate { get; set; }
public Encryption Encryption { get; set; } public Encryption Encryption { get; set; }
public RequestedURI RequestedURI { get; set; } public RequestedURI RequestedURI { get; set; }
public PeopleCountAverage PeopleCountAverage { get; set; } public PeopleCountAverage PeopleCountAverage { get; set; }
} }
public class UserInterface public class UserInterface
{ {
@@ -151,16 +151,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
public string id { get; set; } public string id { get; set; }
public string Value { get; set; } public string Value { get; set; }
} }
public class Event public class Event
{ {
public CallDisconnect CallDisconnect { get; set; } public CallDisconnect CallDisconnect { get; set; }
public UserInterface UserInterface { get; set; } public UserInterface UserInterface { get; set; }
} }
public class RootObject public class RootObject
{ {
public Event Event { get; set; } public Event Event { get; set; }
} }
} }
} }

View File

@@ -1368,8 +1368,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
{ {
set set
{ {
// If the incoming value is "Of" it sets the BoolValue true, otherwise sets it false // If the incoming value is "On" it sets the BoolValue true, otherwise sets it false
BoolValue = value == "Off"; BoolValue = value == "On";
OnValueChanged(); OnValueChanged();
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Text;
using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Ssh; using Crestron.SimplSharp.Ssh;
using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharp;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Core.Intersystem; using PepperDash.Core.Intersystem;
using PepperDash.Core.Intersystem.Tokens; using PepperDash.Core.Intersystem.Tokens;
@@ -231,12 +232,22 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
/// </summary> /// </summary>
protected void SetIsReady() protected void SetIsReady()
{ {
IsReady = true; CrestronInvoke.BeginInvoke( (o) =>
var h = IsReadyChange; {
if (h != null) try
{ {
h(this, new EventArgs()); IsReady = true;
} var h = IsReadyChange;
if (h != null)
{
h(this, new EventArgs());
}
}
catch (Exception e)
{
Debug.Console(2, this, "Error in SetIsReady() : {0}", e);
}
});
} }
// **** DEBUGGING THINGS **** // **** DEBUGGING THINGS ****