diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs
new file mode 100644
index 00000000..26895114
--- /dev/null
+++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IProjectorScreenLiftControl.cs
@@ -0,0 +1,27 @@
+using Crestron.SimplSharpPro.DeviceSupport;
+using System;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
+{
+ ///
+ /// Defines a class that has warm up and cool down
+ ///
+ public interface IProjectorScreenLiftControl
+ {
+ void Raise();
+ void Lower();
+ BoolFeedback IsInUpPosition { get; }
+ bool InUpPosition { get; }
+ event EventHandler PositionChanged;
+ string DisplayDeviceKey { get; }
+ eScreenLiftControlType Type { get; } // screen/lift
+ }
+
+ public enum eScreenLiftControlType
+ {
+ lift,
+ screen
+ }
+}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs b/src/PepperDash.Essentials.Core/Display/MockDisplay.cs
index 7c9f0446..dcd9e949 100644
--- a/src/PepperDash.Essentials.Core/Display/MockDisplay.cs
+++ b/src/PepperDash.Essentials.Core/Display/MockDisplay.cs
@@ -220,19 +220,5 @@ namespace PepperDash.Essentials.Core
}
- [Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
- public class MockDisplayFactory : EssentialsDeviceFactory
- {
- public MockDisplayFactory()
- {
- TypeNames = new List() { "mockdisplay" };
- }
-
- public override EssentialsDevice BuildDevice(DeviceConfig dc)
- {
- Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device");
- return new MockDisplay(dc.Key, dc.Name);
- }
- }
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs
index 213cb835..225abb76 100644
--- a/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs
+++ b/src/PepperDash.Essentials.Core/PartitionSensor/EssentialsPartitionController.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
+using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
@@ -17,7 +18,7 @@ namespace PepperDash.Essentials.Core
{
private IPartitionStateProvider _partitionSensor;
- private bool isInAutoMode;
+ public bool IsInAutoMode { get; private set; }
private bool _partitionPresent;
@@ -64,7 +65,7 @@ namespace PepperDash.Essentials.Core
SetManualMode();
}
}
- else
+ else
{
SetManualMode();
}
@@ -74,7 +75,7 @@ namespace PepperDash.Essentials.Core
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
- if (isInAutoMode)
+ if (IsInAutoMode)
{
PartitionPresentFeedback.FireUpdate();
}
@@ -86,7 +87,7 @@ namespace PepperDash.Essentials.Core
public void SetAutoMode()
{
- isInAutoMode = true;
+ IsInAutoMode = true;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
@@ -98,13 +99,14 @@ namespace PepperDash.Essentials.Core
if (_partitionSensor != null)
{
+ _partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
_partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
}
}
public void SetManualMode()
{
- isInAutoMode = false;
+ IsInAutoMode = false;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => _partitionPresent);
@@ -123,7 +125,7 @@ namespace PepperDash.Essentials.Core
public void SetPartitionStatePresent()
{
- if (!isInAutoMode)
+ if (!IsInAutoMode)
{
PartitionPresent = true;
PartitionPresentFeedback.FireUpdate();
@@ -132,7 +134,7 @@ namespace PepperDash.Essentials.Core
public void SetPartitionStateNotPresent()
{
- if (!isInAutoMode)
+ if (!IsInAutoMode)
{
PartitionPresent = false;
PartitionPresentFeedback.FireUpdate();
@@ -141,7 +143,10 @@ namespace PepperDash.Essentials.Core
public void ToggglePartitionState()
{
- if (!isInAutoMode)
+ Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Toggling Partition State for {Key}", this);
+ Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"IsInAutoMode: {IsInAutoMode}", this);
+
+ if (!IsInAutoMode)
{
PartitionPresent = !PartitionPresent;
PartitionPresentFeedback.FireUpdate();
diff --git a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs
index 60bd080e..418da80c 100644
--- a/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs
+++ b/src/PepperDash.Essentials.Core/PartitionSensor/IPartitionStateProvider.cs
@@ -24,6 +24,9 @@ namespace PepperDash.Essentials.Core
[JsonProperty("adjacentRoomKeys")]
List AdjacentRoomKeys { get; }
+ [JsonProperty("isInAutoMode")]
+ bool IsInAutoMode { get; }
+
void SetPartitionStatePresent();
void SetPartitionStateNotPresent();
diff --git a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs
index 11b0a3ec..dfc1066a 100644
--- a/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs
+++ b/src/PepperDash.Essentials.Core/Room/Combining/EssentialsRoomCombiner.cs
@@ -137,7 +137,11 @@ namespace PepperDash.Essentials.Core
void StartDebounceTimer()
{
- var time = _scenarioChangeDebounceTimeSeconds * 1000;
+ // default to 500ms for manual mode
+ var time = 500;
+
+ // if in auto mode, debounce the scenario change
+ if(IsInAutoMode) time = _scenarioChangeDebounceTimeSeconds * 1000;
if (_scenarioChangeDebounceTimer == null)
{
@@ -211,7 +215,7 @@ namespace PepperDash.Essentials.Core
{
_currentScenario.Activate();
- Debug.LogMessage(LogEventLevel.Debug, this, "Current Scenario: {0}", _currentScenario.Name);
+ Debug.LogMessage(LogEventLevel.Debug, $"Current Scenario: {_currentScenario.Name}", this);
}
var handler = RoomCombinationScenarioChanged;
@@ -246,7 +250,7 @@ namespace PepperDash.Essentials.Core
public void TogglePartitionState(string partitionKey)
{
- var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)) as IPartitionController;
+ var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey));
if (partition != null)
{
diff --git a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs
index 82693d4c..413e0ffc 100644
--- a/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs
+++ b/src/PepperDash.Essentials.Core/Room/EssentialsRoomBase.cs
@@ -141,6 +141,7 @@ namespace PepperDash.Essentials.Core
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
ShutdownType = eShutdownType.None;
};
+
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
ShutdownPromptSeconds = 60;
diff --git a/src/PepperDash.Essentials.Core/Room/Interfaces.cs b/src/PepperDash.Essentials.Core/Room/Interfaces.cs
index 640dc91f..36e785cd 100644
--- a/src/PepperDash.Essentials.Core/Room/Interfaces.cs
+++ b/src/PepperDash.Essentials.Core/Room/Interfaces.cs
@@ -159,4 +159,13 @@ namespace PepperDash.Essentials.Core
Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; }
}
+ public interface IHasAccessoryDevices : IKeyName
+ {
+ List AccessoryDeviceKeys { get; }
+ }
+
+ public interface IHasCiscoNavigatorTouchpanel
+ {
+ string CiscoNavigatorTouchpanelKey { get; }
+ }
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs b/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs
index 1cac0a50..cbb470d6 100644
--- a/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs
+++ b/src/PepperDash.Essentials.Core/Timers/CountdownTimer.cs
@@ -52,8 +52,8 @@ namespace PepperDash.Essentials.Core
var timeSpan = FinishTime - DateTime.Now;
- Debug.LogMessage(LogEventLevel.Verbose, this,
- "timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}",
+ Debug.LogMessage(LogEventLevel.Verbose,
+ "timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}", this,
timeSpan.Minutes, timeSpan.Seconds, timeSpan.TotalSeconds);
if (Math.Floor(timeSpan.TotalSeconds) < 60 && Math.Floor(timeSpan.TotalSeconds) >= 0) //ignore milliseconds
@@ -103,6 +103,7 @@ namespace PepperDash.Essentials.Core
public void Reset()
{
_isRunning = false;
+ IsRunningFeedback.FireUpdate();
Start();
}
@@ -133,7 +134,11 @@ namespace PepperDash.Essentials.Core
void StopHelper()
{
if (_secondTimer != null)
+ {
_secondTimer.Stop();
+ _secondTimer = null;
+ }
+
_isRunning = false;
IsRunningFeedback.FireUpdate();
}
diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs
index a1241821..ff4c451b 100644
--- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs
+++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplay.cs
@@ -6,6 +6,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
+using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Routing;
using Serilog.Events;
@@ -120,7 +121,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays
// Fake cool-down cycle
CooldownTimer = new CTimer(o =>
{
- Debug.LogMessage(LogEventLevel.Verbose, this, "Cooldown timer ending");
+ Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this);
_IsCoolingDown = false;
IsCoolingDownFeedback.InvokeFireUpdate();
_PowerIsOn = false;
@@ -141,10 +142,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays
{
Debug.LogMessage(LogEventLevel.Verbose, this, "ExecuteSwitch: {0}", selector);
- if (!_PowerIsOn)
- {
- PowerOn();
- }
+ if (!_PowerIsOn)
+ {
+ PowerOn();
+ }
if (!Inputs.Items.TryGetValue(selector.ToString(), out var input))
return;
@@ -152,32 +153,6 @@ namespace PepperDash.Essentials.Devices.Common.Displays
input.Select();
}
- public void SetInput(string selector)
- {
- ISelectableItem currentInput = null;
-
- try
- {
- currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value;
- }
- catch { }
-
-
- if (currentInput != null)
- {
- Debug.LogMessage(LogEventLevel.Verbose, this, "SetInput: {0}", selector);
- currentInput.IsSelected = false;
- }
-
- if (!Inputs.Items.TryGetValue(selector, out var input))
- return;
-
- input.IsSelected = true;
-
- Inputs.CurrentItem = selector;
- }
-
-
#region IBasicVolumeWithFeedback Members
@@ -251,4 +226,17 @@ namespace PepperDash.Essentials.Devices.Common.Displays
}
+ public class MockDisplayFactory : EssentialsDeviceFactory
+ {
+ public MockDisplayFactory()
+ {
+ TypeNames = new List() { "mockdisplay" };
+ }
+
+ public override EssentialsDevice BuildDevice(DeviceConfig dc)
+ {
+ Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device");
+ return new MockDisplay(dc.Key, dc.Name);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs
index 5013913c..0380085f 100644
--- a/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs
+++ b/src/PepperDash.Essentials.Devices.Common/Displays/MockDisplayInputs.cs
@@ -90,7 +90,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays
public void Select()
{
- _parent.SetInput(Key);
+ if (!_parent.PowerIsOnFeedback.BoolValue) _parent.PowerOn();
+
+ foreach(var input in _parent.Inputs.Items)
+ {
+ input.Value.IsSelected = input.Key == this.Key;
+ }
}
}
}
diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs
new file mode 100644
index 00000000..1bb7f503
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs
@@ -0,0 +1,266 @@
+using System;
+using System.Collections.Generic;
+using Crestron.SimplSharp;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.CrestronIO;
+using PepperDash.Essentials.Core.DeviceTypeInterfaces;
+using PepperDash.Essentials.Devices.Common;
+using Serilog.Events;
+
+namespace PepperDash.Essentials.Devices.Common.Shades
+{
+ ///
+ /// Controls a single shade using three relays
+ ///
+ public class ScreenLiftController : EssentialsDevice, IProjectorScreenLiftControl
+ {
+ readonly ScreenLiftControllerConfigProperties Config;
+ readonly ScreenLiftRelaysConfig RaiseRelayConfig;
+ readonly ScreenLiftRelaysConfig LowerRelayConfig;
+ readonly ScreenLiftRelaysConfig LatchedRelayConfig;
+
+ Displays.DisplayBase DisplayDevice;
+ ISwitchedOutput RaiseRelay;
+ ISwitchedOutput LowerRelay;
+ ISwitchedOutput LatchedRelay;
+
+ public bool InUpPosition
+ {
+ get { return _isInUpPosition; }
+ set
+ {
+ if (value == _isInUpPosition) return;
+ _isInUpPosition = value;
+ IsInUpPosition.FireUpdate();
+ PositionChanged?.Invoke(this, new EventArgs());
+ }
+ }
+
+ private bool _isInUpPosition { get; set; }
+ public eScreenLiftControlType Type { get; private set; }
+ public eScreenLiftControlMode Mode { get; private set; }
+
+ public string DisplayDeviceKey { get; private set; }
+ public BoolFeedback IsInUpPosition { get; private set; }
+
+ public event EventHandler PositionChanged;
+
+ public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config)
+ : base(key, name)
+ {
+ Config = config;
+ DisplayDeviceKey = Config.DisplayDeviceKey;
+ Mode = Config.Mode;
+ Type = Config.Type;
+
+ IsInUpPosition = new BoolFeedback(() => _isInUpPosition);
+
+ switch (Mode)
+ {
+ case eScreenLiftControlMode.momentary:
+ {
+ RaiseRelayConfig = Config.Relays["raise"];
+ LowerRelayConfig = Config.Relays["lower"];
+ break;
+ }
+ case eScreenLiftControlMode.latched:
+ {
+ LatchedRelayConfig = Config.Relays["latched"];
+ break;
+ }
+ }
+ }
+
+ private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
+ {
+ if (!DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.lift)
+ {
+ Raise();
+ return;
+ }
+ if (DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.screen)
+ {
+ Raise();
+ return;
+ }
+ }
+
+ private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e)
+ {
+ if (DisplayDevice.IsWarmingUpFeedback.BoolValue)
+ {
+ Lower();
+ }
+ }
+
+ public override bool CustomActivate()
+ {
+ //Create ISwitchedOutput objects based on props
+ switch (Mode)
+ {
+ case eScreenLiftControlMode.momentary:
+ {
+ Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}");
+ RaiseRelay = GetSwitchedOutputFromDevice(RaiseRelayConfig.DeviceKey);
+ LowerRelay = GetSwitchedOutputFromDevice(LowerRelayConfig.DeviceKey);
+ break;
+ }
+ case eScreenLiftControlMode.latched:
+ {
+ Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}");
+ LatchedRelay = GetSwitchedOutputFromDevice(LatchedRelayConfig.DeviceKey);
+ break;
+ }
+ }
+
+ Debug.LogMessage(LogEventLevel.Debug, this, $"Getting display with key {DisplayDeviceKey}");
+ DisplayDevice = GetDisplayBaseFromDevice(DisplayDeviceKey);
+
+ if (DisplayDevice != null)
+ {
+ Debug.LogMessage(LogEventLevel.Debug, this, $"Subscribing to {DisplayDeviceKey} feedbacks");
+
+ DisplayDevice.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
+ DisplayDevice.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
+ }
+
+ return base.CustomActivate();
+ }
+
+ public void Raise()
+ {
+ if (RaiseRelay == null && LatchedRelay == null) return;
+
+ Debug.LogMessage(LogEventLevel.Debug, this, $"Raising {Type}");
+
+ switch (Mode)
+ {
+ case eScreenLiftControlMode.momentary:
+ {
+ PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs);
+ break;
+ }
+ case eScreenLiftControlMode.latched:
+ {
+ LatchedRelay.Off();
+ break;
+ }
+ }
+ InUpPosition = true;
+ }
+
+ public void Lower()
+ {
+ if (LowerRelay == null && LatchedRelay == null) return;
+
+ Debug.LogMessage(LogEventLevel.Debug, this, $"Lowering {Type}");
+
+ switch (Mode)
+ {
+ case eScreenLiftControlMode.momentary:
+ {
+ PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs);
+ break;
+ }
+ case eScreenLiftControlMode.latched:
+ {
+ LatchedRelay.On();
+ break;
+ }
+ }
+ InUpPosition = false;
+ }
+
+ void PulseOutput(ISwitchedOutput output, int pulseTime)
+ {
+ output.On();
+ CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime);
+ }
+
+ ///
+ /// Attempts to get the port on teh specified device from config
+ ///
+ ///
+ ///
+ ISwitchedOutput GetSwitchedOutputFromDevice(string relayKey)
+ {
+ var portDevice = DeviceManager.GetDeviceForKey(relayKey);
+ if (portDevice != null)
+ {
+ return (portDevice as ISwitchedOutput);
+ }
+ else
+ {
+ Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get relay device with key '{0}'", relayKey);
+ return null;
+ }
+ }
+
+ Displays.DisplayBase GetDisplayBaseFromDevice(string displayKey)
+ {
+ var displayDevice = DeviceManager.GetDeviceForKey(displayKey);
+ if (displayDevice != null)
+ {
+ return displayDevice as Displays.DisplayBase;
+ }
+ else
+ {
+ Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get display device with key '{0}'", displayKey);
+ return null;
+ }
+ }
+
+ }
+
+ public class ScreenLiftControllerConfigProperties
+ {
+ [JsonProperty("displayDeviceKey")]
+ public string DisplayDeviceKey { get; set; }
+
+ [JsonProperty("type")]
+ [JsonConverter(typeof(StringEnumConverter))]
+ public eScreenLiftControlType Type { get; set; }
+
+ [JsonProperty("mode")]
+ [JsonConverter(typeof(StringEnumConverter))]
+ public eScreenLiftControlMode Mode { get; set; }
+
+ [JsonProperty("relays")]
+ public Dictionary Relays { get; set; }
+
+ }
+ public class ScreenLiftRelaysConfig
+ {
+ [JsonProperty("deviceKey")]
+ public string DeviceKey { get; set; }
+
+ [JsonProperty("pulseTimeInMs")]
+ public int PulseTimeInMs { get; set; }
+ }
+
+ public class ScreenLiftControllerFactory : EssentialsDeviceFactory
+ {
+ public ScreenLiftControllerFactory()
+ {
+ TypeNames = new List() { "screenliftcontroller" };
+ }
+
+ public override EssentialsDevice BuildDevice(DeviceConfig dc)
+ {
+ Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device");
+ var props = Newtonsoft.Json.JsonConvert.DeserializeObject(dc.Properties.ToString());
+
+ return new ScreenLiftController(dc.Key, dc.Name, props);
+ }
+ }
+
+ public enum eScreenLiftControlMode
+ {
+ momentary,
+ latched
+ }
+}
\ No newline at end of file