Merge pull request #1377 from PepperDash/feature/circuittype-property-versiport

This commit is contained in:
Neil Dorin
2026-02-09 13:47:36 -07:00
committed by GitHub
8 changed files with 264 additions and 172 deletions

View File

@@ -21,6 +21,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IHasFeedback public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IHasFeedback
{ {
private DigitalInput inputPort; private DigitalInput inputPort;
private readonly bool invertState;
/// <summary> /// <summary>
/// Gets or sets the InputStateFeedback /// Gets or sets the InputStateFeedback
@@ -41,7 +42,9 @@ namespace PepperDash.Essentials.Core.CrestronIO
IOPortConfig config) IOPortConfig config)
: base(key, name) : base(key, name)
{ {
InputStateFeedback = new BoolFeedback("inputState", () => inputPort.State); invertState = string.Equals(config.CircuitType, "NC", StringComparison.OrdinalIgnoreCase);
InputStateFeedback = new BoolFeedback("inputState", () => invertState ? !inputPort.State : inputPort.State);
AddPostActivationAction(() => AddPostActivationAction(() =>
{ {

View File

@@ -18,6 +18,7 @@ namespace PepperDash.Essentials.Core.CrestronIO
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider, IHasFeedback public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider, IHasFeedback
{ {
private Versiport inputPort; private Versiport inputPort;
private readonly bool invertState;
/// <summary> /// <summary>
/// Gets or sets the InputStateFeedback /// Gets or sets the InputStateFeedback
@@ -47,7 +48,10 @@ namespace PepperDash.Essentials.Core.CrestronIO
public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) : public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
base(key, name) base(key, name)
{ {
InputStateFeedback = new BoolFeedback("inputState", () => inputPort.DigitalIn); var circuitType = string.IsNullOrEmpty(config.CircuitType) ? "NO" : config.CircuitType;
invertState = circuitType.Equals("NC", StringComparison.OrdinalIgnoreCase);
InputStateFeedback = new BoolFeedback("inputState", () => invertState ? !inputPort.DigitalIn : inputPort.DigitalIn);
PartitionPresentFeedback = new BoolFeedback("partitionPresent", () => !inputPort.DigitalIn); PartitionPresentFeedback = new BoolFeedback("partitionPresent", () => !inputPort.DigitalIn);
AddPostActivationAction(() => AddPostActivationAction(() =>

View File

@@ -37,5 +37,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// </summary> /// </summary>
[JsonProperty("minimumChange")] [JsonProperty("minimumChange")]
public int MinimumChange { get; set; } public int MinimumChange { get; set; }
/// <summary>
/// Gets or sets the circuit type: "NO" (Normally Open) or "NC" (Normally Closed)
/// If set to "NC", the input state will be inverted. Defaults to "NO" if not specified.
/// </summary>
[JsonProperty("circuitType")]
public string CircuitType { get; set; } = "NO";
} }
} }

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks;
using System.Timers; using System.Timers;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronIO;
@@ -698,18 +699,26 @@ namespace PepperDash.Essentials.Core.Fusion
/// <param name="args"></param> /// <param name="args"></param>
protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) protected void FusionRoom_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{ {
if (args.DeviceOnLine) if (!args.DeviceOnLine)
{ {
CrestronInvoke.BeginInvoke((o) => return;
{ }
CrestronEnvironment.Sleep(200);
// Send Push Notification Action request: if (!_config.EnableSchedulePushNotifications)
{
return;
}
const string requestId = "InitialPushRequest"; Task.Run(() =>
{
// CrestronEnvironment.Sleep(200);
// Send Push Notification Action request:
const string requestId = "InitialPushRequest";
var actionRequest = var actionRequest =
string.Format("<RequestAction>\n<RequestID>{0}</RequestID>\n", requestId) + string.Format("<RequestAction>\n<RequestID>{0}</RequestID>\n", requestId) +
"<ActionID>RegisterPushModel</ActionID>\n" + "<ActionID>RegisterPushModel</ActionID>\n" +
"<Parameters>\n" + "<Parameters>\n" +
@@ -734,27 +743,26 @@ namespace PepperDash.Essentials.Core.Fusion
"</Parameters>\n" + "</Parameters>\n" +
"</RequestAction>\n"; "</RequestAction>\n";
Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ActionRequest: \n{0}", actionRequest); Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ActionRequest: \n{0}", actionRequest);
FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest; FusionRoom.ExtenderFusionRoomDataReservedSigs.ActionQuery.StringValue = actionRequest;
GetCustomProperties(); GetCustomProperties();
// Request current Fusion Server Time // Request current Fusion Server Time
RequestLocalDateTime(null); RequestLocalDateTime(null);
// Setup timer to request time daily // Setup timer to request time daily
if (_dailyTimeRequestTimer != null && !_dailyTimeRequestTimer.Disposed) if (_dailyTimeRequestTimer != null && !_dailyTimeRequestTimer.Disposed)
{ {
_dailyTimeRequestTimer.Stop(); _dailyTimeRequestTimer.Stop();
_dailyTimeRequestTimer.Dispose(); _dailyTimeRequestTimer.Dispose();
} }
_dailyTimeRequestTimer = new CTimer(RequestLocalDateTime, null, 86400000, 86400000); _dailyTimeRequestTimer = new CTimer(RequestLocalDateTime, null, 86400000, 86400000);
_dailyTimeRequestTimer.Reset(86400000, 86400000); _dailyTimeRequestTimer.Reset(86400000, 86400000);
}); });
}
} }
/// <summary> /// <summary>
@@ -785,7 +793,7 @@ namespace PepperDash.Essentials.Core.Fusion
var requestTest = var requestTest =
string.Format( string.Format(
"<RequestSchedule><RequestID>FullSchedleRequest</RequestID><RoomID>{0}</RoomID><Start>{1}</Start><HourSpan>24</HourSpan></RequestSchedule>", "<RequestSchedule><RequestID>FullScheduleRequest</RequestID><RoomID>{0}</RoomID><Start>{1}</Start><HourSpan>24</HourSpan></RequestSchedule>",
RoomGuid, currentTime); RoomGuid, currentTime);
Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest); Debug.LogMessage(LogEventLevel.Verbose, this, "Sending Fusion ScheduleQuery: \n{0}", requestTest);
@@ -960,7 +968,7 @@ namespace PepperDash.Essentials.Core.Fusion
select parameter.Attributes select parameter.Attributes
into attributes into attributes
where attributes["ID"].Value == "Registered" where attributes["ID"].Value == "Registered"
select Int32.Parse(attributes["Value"].Value)) select int.Parse(attributes["Value"].Value))
{ {
switch (isRegistered) switch (isRegistered)
{ {
@@ -1112,7 +1120,7 @@ namespace PepperDash.Essentials.Core.Fusion
protected void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, protected void FusionRoomSchedule_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender,
SigEventArgs args) SigEventArgs args)
{ {
Debug.LogMessage(LogEventLevel.Verbose, this, "Scehdule Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event, Debug.LogMessage(LogEventLevel.Verbose, this, "Schedule Response Event: {0}\n Sig: {1}\nFusionResponse:\n{2}", args.Event,
args.Sig.Name, args.Sig.StringValue); args.Sig.Name, args.Sig.StringValue);

View File

@@ -75,4 +75,11 @@ public class IEssentialsRoomFusionControllerPropertiesConfig
/// </summary> /// </summary>
[JsonProperty("helpRequestTimeoutMs")] [JsonProperty("helpRequestTimeoutMs")]
public int HelpRequestTimeoutMs { get; set; } = 30000; public int HelpRequestTimeoutMs { get; set; } = 30000;
/// <summary>
/// Gets or sets whether to enable schedule push notifications
/// </summary>
/// <remarks>Defaults to false to skip getting schedule unless required</remarks>
[JsonProperty("enableSchedulePushNotifications")]
public bool EnableSchedulePushNotifications { get; set; } = false;
} }

View File

@@ -69,51 +69,61 @@ namespace PepperDash.Essentials.Core
void ProcessStatuses() void ProcessStatuses()
{ {
var InError = Monitors.Where(m => m.Status == MonitorStatus.InError); var InError = Monitors.Where(m => m.Status == MonitorStatus.InError).ToList();
var InWarning = Monitors.Where(m => m.Status == MonitorStatus.InWarning); var InWarning = Monitors.Where(m => m.Status == MonitorStatus.InWarning).ToList();
var IsOk = Monitors.Where(m => m.Status == MonitorStatus.IsOk); var IsOk = Monitors.Where(m => m.Status == MonitorStatus.IsOk).ToList();
MonitorStatus initialStatus; MonitorStatus initialStatus;
string prefix = "0:"; string prefix = "0:";
if (InError.Count() > 0) if (InError.Any())
{ {
initialStatus = MonitorStatus.InError; initialStatus = MonitorStatus.InError;
prefix = "3:"; prefix = "3:";
} }
else if (InWarning.Count() > 0) else if (InWarning.Any())
{ {
initialStatus = MonitorStatus.InWarning; initialStatus = MonitorStatus.InWarning;
prefix = "2:"; prefix = "2:";
} }
else if (IsOk.Count() > 0) else if (IsOk.Any())
initialStatus = MonitorStatus.IsOk; initialStatus = MonitorStatus.IsOk;
else else
initialStatus = MonitorStatus.StatusUnknown; initialStatus = MonitorStatus.StatusUnknown;
// Build the error message string // Build the error message string
if (InError.Count() > 0 || InWarning.Count() > 0) if (InError.Any() || InWarning.Any())
{ {
StringBuilder sb = new StringBuilder(prefix); var errorNames = InError
if (InError.Count() > 0) .Select(mon => mon.Parent is IKeyName keyName ? keyName.Name : mon.Parent.Key)
{ .ToList();
// Do string splits and joins var warningNames = InWarning
sb.Append(string.Format("{0} Errors:", InError.Count())); .Select(mon => mon.Parent is IKeyName keyName ? keyName.Name : mon.Parent.Key)
foreach (var mon in InError) .ToList();
sb.Append(string.Format("{0}, ", mon.Parent.Key));
} var sb = new StringBuilder(prefix);
if (InWarning.Count() > 0)
{ if (errorNames.Count > 0)
sb.Append(string.Format("{0} Warnings:", InWarning.Count())); {
foreach (var mon in InWarning) sb.Append($"{errorNames.Count} Error{(errorNames.Count > 1 ? "s" : "")}: ");
sb.Append(string.Format("{0}, ", mon.Parent.Key)); sb.Append(string.Join(", ", errorNames));
} }
Message = sb.ToString(); if (warningNames.Count > 0)
} {
else if (errorNames.Count > 0)
{ sb.Append("; ");
Message = "Room Ok.";
} sb.Append($"{warningNames.Count} Warning{(warningNames.Count > 1 ? "s" : "")}: ");
sb.Append(string.Join(", ", warningNames));
}
sb.Append(" Offline");
Message = sb.ToString();
}
else
{
Message = "Room Ok.";
}
// Want to fire even if status doesn't change because the message may. // Want to fire even if status doesn't change because the message may.
Status = initialStatus; Status = initialStatus;

View File

@@ -19,7 +19,7 @@ namespace PepperDash.Essentials.Devices.Common.Shades
{ {
None, None,
Raise, Raise,
Lower Lower,
} }
/// <summary> /// <summary>
@@ -50,7 +50,8 @@ namespace PepperDash.Essentials.Devices.Common.Shades
get { return _isInUpPosition; } get { return _isInUpPosition; }
set set
{ {
if (value == _isInUpPosition) return; if (value == _isInUpPosition)
return;
_isInUpPosition = value; _isInUpPosition = value;
IsInUpPosition.FireUpdate(); IsInUpPosition.FireUpdate();
PositionChanged?.Invoke(this, new EventArgs()); PositionChanged?.Invoke(this, new EventArgs());
@@ -87,7 +88,11 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// <summary> /// <summary>
/// Constructor for ScreenLiftController /// Constructor for ScreenLiftController
/// </summary> /// </summary>
public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config) public ScreenLiftController(
string key,
string name,
ScreenLiftControllerConfigProperties config
)
: base(key, name) : base(key, name)
{ {
Config = config; Config = config;
@@ -105,27 +110,60 @@ namespace PepperDash.Essentials.Devices.Common.Shades
switch (Mode) switch (Mode)
{ {
case eScreenLiftControlMode.momentary: case eScreenLiftControlMode.momentary:
{ {
RaiseRelayConfig = Config.Relays["raise"]; RaiseRelayConfig = Config.Relays["raise"];
LowerRelayConfig = Config.Relays["lower"]; LowerRelayConfig = Config.Relays["lower"];
break; break;
} }
case eScreenLiftControlMode.latched: case eScreenLiftControlMode.latched:
{ {
LatchedRelayConfig = Config.Relays["latched"]; LatchedRelayConfig = Config.Relays["latched"];
break; break;
} }
} }
IsInUpPosition.OutputChange += (sender, args) =>
{
this.LogDebug(
"ScreenLiftController '{name}' IsInUpPosition changed to {position}",
Name,
IsInUpPosition.BoolValue ? "Up" : "Down"
);
if (!Config.MuteOnScreenUp)
{
return;
}
if (args.BoolValue)
{
return;
}
if (DisplayDevice is IBasicVideoMuteWithFeedback videoMute)
{
this.LogInformation("Unmuting video because screen is down");
videoMute.VideoMuteOff();
}
};
IsInUpPosition.FireUpdate();
} }
private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
{ {
if (!DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.lift) if (
!DisplayDevice.IsCoolingDownFeedback.BoolValue
&& Type == eScreenLiftControlType.lift
)
{ {
Raise(); Raise();
return; return;
} }
if (DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.screen) if (
DisplayDevice.IsCoolingDownFeedback.BoolValue
&& Type == eScreenLiftControlType.screen
)
{ {
Raise(); Raise();
return; return;
@@ -150,18 +188,18 @@ namespace PepperDash.Essentials.Devices.Common.Shades
switch (Mode) switch (Mode)
{ {
case eScreenLiftControlMode.momentary: case eScreenLiftControlMode.momentary:
{ {
this.LogDebug("Getting relays for {mode}", Mode); this.LogDebug("Getting relays for {mode}", Mode);
RaiseRelay = GetSwitchedOutputFromDevice(RaiseRelayConfig.DeviceKey); RaiseRelay = GetSwitchedOutputFromDevice(RaiseRelayConfig.DeviceKey);
LowerRelay = GetSwitchedOutputFromDevice(LowerRelayConfig.DeviceKey); LowerRelay = GetSwitchedOutputFromDevice(LowerRelayConfig.DeviceKey);
break; break;
} }
case eScreenLiftControlMode.latched: case eScreenLiftControlMode.latched:
{ {
this.LogDebug("Getting relays for {mode}", Mode); this.LogDebug("Getting relays for {mode}", Mode);
LatchedRelay = GetSwitchedOutputFromDevice(LatchedRelayConfig.DeviceKey); LatchedRelay = GetSwitchedOutputFromDevice(LatchedRelayConfig.DeviceKey);
break; break;
} }
} }
this.LogDebug("Getting display with key {displayKey}", DisplayDeviceKey); this.LogDebug("Getting display with key {displayKey}", DisplayDeviceKey);
@@ -172,7 +210,8 @@ namespace PepperDash.Essentials.Devices.Common.Shades
this.LogDebug("Subscribing to {displayKey} feedbacks", DisplayDeviceKey); this.LogDebug("Subscribing to {displayKey} feedbacks", DisplayDeviceKey);
DisplayDevice.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; DisplayDevice.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
DisplayDevice.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; DisplayDevice.IsCoolingDownFeedback.OutputChange +=
IsCoolingDownFeedback_OutputChange;
} }
return base.CustomActivate(); return base.CustomActivate();
@@ -183,10 +222,17 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// </summary> /// </summary>
public void Raise() public void Raise()
{ {
if (RaiseRelay == null && LatchedRelay == null) return; if (RaiseRelay == null && LatchedRelay == null)
return;
this.LogDebug("Raise called for {type}", Type); this.LogDebug("Raise called for {type}", Type);
if (Config.MuteOnScreenUp && DisplayDevice is IBasicVideoMuteWithFeedback videoMute)
{
this.LogInformation("Muting video because screen is going up");
videoMute.VideoMuteOn();
}
// If device is moving, bank the command // If device is moving, bank the command
if (_isMoving) if (_isMoving)
{ {
@@ -200,33 +246,33 @@ namespace PepperDash.Essentials.Devices.Common.Shades
switch (Mode) switch (Mode)
{ {
case eScreenLiftControlMode.momentary: case eScreenLiftControlMode.momentary:
{ {
PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs); PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs);
// Set moving flag and start timer if movement time is configured // Set moving flag and start timer if movement time is configured
if (RaiseRelayConfig.MoveTimeInMs > 0) if (RaiseRelayConfig.MoveTimeInMs > 0)
{
_isMoving = true;
_currentMovement = RequestedState.Raise;
if (_movementTimer.Enabled)
{
_movementTimer.Stop();
}
_movementTimer.Interval = RaiseRelayConfig.MoveTimeInMs;
_movementTimer.Start();
}
else
{
InUpPosition = true;
}
break;
}
case eScreenLiftControlMode.latched:
{ {
LatchedRelay.Off(); _isMoving = true;
InUpPosition = true; _currentMovement = RequestedState.Raise;
break; if (_movementTimer.Enabled)
{
_movementTimer.Stop();
}
_movementTimer.Interval = RaiseRelayConfig.MoveTimeInMs;
_movementTimer.Start();
} }
else
{
InUpPosition = true;
}
break;
}
case eScreenLiftControlMode.latched:
{
LatchedRelay.Off();
InUpPosition = true;
break;
}
} }
} }
@@ -235,7 +281,8 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// </summary> /// </summary>
public void Lower() public void Lower()
{ {
if (LowerRelay == null && LatchedRelay == null) return; if (LowerRelay == null && LatchedRelay == null)
return;
this.LogDebug("Lower called for {type}", Type); this.LogDebug("Lower called for {type}", Type);
@@ -252,33 +299,33 @@ namespace PepperDash.Essentials.Devices.Common.Shades
switch (Mode) switch (Mode)
{ {
case eScreenLiftControlMode.momentary: case eScreenLiftControlMode.momentary:
{ {
PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs); PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs);
// Set moving flag and start timer if movement time is configured // Set moving flag and start timer if movement time is configured
if (LowerRelayConfig.MoveTimeInMs > 0) if (LowerRelayConfig.MoveTimeInMs > 0)
{
_isMoving = true;
_currentMovement = RequestedState.Lower;
if (_movementTimer.Enabled)
{
_movementTimer.Stop();
}
_movementTimer.Interval = LowerRelayConfig.MoveTimeInMs;
_movementTimer.Start();
}
else
{
InUpPosition = false;
}
break;
}
case eScreenLiftControlMode.latched:
{ {
LatchedRelay.On(); _isMoving = true;
InUpPosition = false; _currentMovement = RequestedState.Lower;
break; if (_movementTimer.Enabled)
{
_movementTimer.Stop();
}
_movementTimer.Interval = LowerRelayConfig.MoveTimeInMs;
_movementTimer.Start();
} }
else
{
InUpPosition = false;
}
break;
}
case eScreenLiftControlMode.latched:
{
LatchedRelay.On();
InUpPosition = false;
break;
}
} }
} }
@@ -339,16 +386,13 @@ namespace PepperDash.Essentials.Devices.Common.Shades
{ {
output.On(); output.On();
var timer = new Timer(pulseTime) var timer = new Timer(pulseTime) { AutoReset = false };
{
AutoReset = false
};
timer.Elapsed += (sender, e) => timer.Elapsed += (sender, e) =>
{ {
output.Off(); output.Off();
timer.Dispose(); timer.Dispose();
}; };
timer.Start(); timer.Start();
} }
@@ -361,7 +405,10 @@ namespace PepperDash.Essentials.Devices.Common.Shades
} }
else else
{ {
this.LogWarning("Error: Unable to get relay device with key '{relayKey}'", relayKey); this.LogWarning(
"Error: Unable to get relay device with key '{relayKey}'",
relayKey
);
return null; return null;
} }
} }
@@ -375,11 +422,13 @@ namespace PepperDash.Essentials.Devices.Common.Shades
} }
else else
{ {
this.LogWarning("Error: Unable to get display device with key '{displayKey}'", displayKey); this.LogWarning(
"Error: Unable to get display device with key '{displayKey}'",
displayKey
);
return null; return null;
} }
} }
} }
/// <summary> /// <summary>
@@ -387,7 +436,7 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// </summary> /// </summary>
public class ScreenLiftControllerFactory : EssentialsDeviceFactory<RelayControlledShade> public class ScreenLiftControllerFactory : EssentialsDeviceFactory<RelayControlledShade>
{ {
/// <summary> /// <summary>
/// Constructor for ScreenLiftControllerFactory /// Constructor for ScreenLiftControllerFactory
/// </summary> /// </summary>
public ScreenLiftControllerFactory() public ScreenLiftControllerFactory()
@@ -404,4 +453,4 @@ namespace PepperDash.Essentials.Devices.Common.Shades
return new ScreenLiftController(dc.Key, dc.Name, props); return new ScreenLiftController(dc.Key, dc.Name, props);
} }
} }
} }

View File

@@ -5,37 +5,41 @@ using PepperDash.Essentials.Core.DeviceTypeInterfaces;
namespace PepperDash.Essentials.Devices.Common.Shades namespace PepperDash.Essentials.Devices.Common.Shades
{ {
/// <summary>
/// Represents a ScreenLiftControllerConfigProperties
/// </summary>
public class ScreenLiftControllerConfigProperties
{
/// <summary> /// <summary>
/// Gets or sets the DisplayDeviceKey /// Represents a ScreenLiftControllerConfigProperties
/// </summary> /// </summary>
[JsonProperty("displayDeviceKey")] public class ScreenLiftControllerConfigProperties
public string DisplayDeviceKey { get; set; } {
/// <summary>
/// Gets or sets the DisplayDeviceKey
/// </summary>
[JsonProperty("displayDeviceKey")]
public string DisplayDeviceKey { get; set; }
/// <summary> /// <summary>
/// Gets or sets the Type /// Gets or sets the Type
/// </summary> /// </summary>
[JsonProperty("type")] [JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public eScreenLiftControlType Type { get; set; } public eScreenLiftControlType Type { get; set; }
/// <summary> /// <summary>
/// Gets or sets the Mode /// Gets or sets the Mode
/// </summary> /// </summary>
[JsonProperty("mode")] [JsonProperty("mode")]
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public eScreenLiftControlMode Mode { get; set; } public eScreenLiftControlMode Mode { get; set; }
/// <summary> /// <summary>
/// Gets or sets the Relays /// Gets or sets the Relays
/// </summary> /// </summary>
[JsonProperty("relays")] [JsonProperty("relays")]
public Dictionary<string, ScreenLiftRelaysConfig> Relays { get; set; } public Dictionary<string, ScreenLiftRelaysConfig> Relays { get; set; }
} /// <summary>
} /// Mutes the display when the screen is in the up position
/// </summary>
[JsonProperty("muteOnScreenUp")]
public bool MuteOnScreenUp { get; set; }
}
}