Merge branch 'main' into mc-connect-logging

This commit is contained in:
Andrew Welker
2025-09-29 10:37:26 -05:00
14 changed files with 322 additions and 347 deletions

View File

@@ -2,59 +2,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Core.CrestronIO
{
[Description("Wrapper class for Digital Input")]
/// <summary>
/// Represents a GenericDigitalInputDevice
/// </summary>
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput
/// [Description("Wrapper class for Digital Input")]
public class GenericDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IHasFeedback
{
/// <summary>
/// Gets or sets the InputPort
/// </summary>
public DigitalInput InputPort { get; private set; }
private DigitalInput inputPort;
/// <summary>
/// Gets or sets the InputStateFeedback
/// </summary>
public BoolFeedback InputStateFeedback { get; private set; }
Func<bool> InputStateFeedbackFunc
{
get
{
return () => InputPort.State;
}
}
/// <inheritdoc />
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
/// <summary>
/// Initializes a new instance of the <see cref="GenericDigitalInputDevice"/> class.
/// </summary>
/// <param name="key">key for device</param>
/// <param name="name">name for device</param>
/// <param name="postActivationFunc">function to call after activation. Should return the DigitalInput</param>
/// <param name="config">config for device</param>
public GenericDigitalInputDevice(string key, string name, Func<IOPortConfig, DigitalInput> postActivationFunc,
IOPortConfig config)
: base(key, name)
{
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
InputStateFeedback = new BoolFeedback("inputState", () => inputPort.State);
AddPostActivationAction(() =>
{
InputPort = postActivationFunc(config);
inputPort = postActivationFunc(config);
InputPort.Register();
InputPort.StateChange += InputPort_StateChange;
inputPort.Register();
inputPort.StateChange += InputPort_StateChange;
});
}
@@ -71,41 +66,31 @@ namespace PepperDash.Essentials.Core.CrestronIO
private static DigitalInput GetDigitalInput(IOPortConfig dc)
{
IDigitalInputPorts ioPortDevice;
if (dc.PortDeviceKey.Equals("processor"))
{
if (!Global.ControlSystem.SupportsDigitalInput)
{
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Processor does not support Digital Inputs");
Debug.LogError("GetDigitalInput: Processor does not support Digital Inputs");
return null;
}
ioPortDevice = Global.ControlSystem;
return Global.ControlSystem.DigitalInputPorts[dc.PortNumber];
}
else
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IDigitalInputPorts ioPortDevice))
{
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IDigitalInputPorts;
if (ioPortDev == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey);
return null;
}
ioPortDevice = ioPortDev;
}
if (ioPortDevice == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device '0' is not a valid IDigitalInputPorts Device", dc.PortDeviceKey);
Debug.LogError("GetDigitalInput: Device {key} is not a valid device", dc.PortDeviceKey);
return null;
}
if (dc.PortNumber > ioPortDevice.NumberOfDigitalInputPorts)
{
Debug.LogMessage(LogEventLevel.Information, "GetDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
Debug.LogError("GetDigitalInput: Device {key} does not contain a digital input port {port}", dc.PortDeviceKey, dc.PortNumber);
return null;
}
return ioPortDevice.DigitalInputPorts[dc.PortNumber];
}
#endregion
@@ -131,20 +116,20 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
try
{
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
this.LogError("Unable to link device {key}. {message}", Key, e.Message);
this.LogDebug(e, "Stack Trace: ");
}
}
@@ -153,22 +138,22 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Factory
/// <summary>
/// Represents a GenericDigitalInputDeviceFactory
/// Factory for creating GenericDigitalInputDevice devices
/// </summary>
public class GenericDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericDigitalInputDevice>
{
/// <summary>
/// Constructor for GenericDigitalInputDeviceFactory
/// </summary>
public GenericDigitalInputDeviceFactory()
{
TypeNames = new List<string>() { "digitalinput" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Digital Input Device");
Debug.LogDebug("Factory Attempting to create new Generic Digital Input Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());

View File

@@ -2,66 +2,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using Newtonsoft.Json;
using Serilog.Events;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
/// <summary>
/// Represents a generic digital input deviced tied to a versiport
/// </summary>
public class GenericVersiportAnalogInputDevice : EssentialsBridgeableDevice, IAnalogInput
public class GenericVersiportAnalogInputDevice : EssentialsBridgeableDevice, IAnalogInput, IHasFeedback
{
public Versiport InputPort { get; private set; }
private Versiport inputPort;
/// <inheritdoc />
public IntFeedback InputValueFeedback { get; private set; }
/// <summary>
/// Get the InputMinimumChangeFeedback
/// </summary>
/// <remarks>
/// Updates when the analog input minimum change value changes
/// </remarks>
public IntFeedback InputMinimumChangeFeedback { get; private set; }
Func<int> InputValueFeedbackFunc
{
get
{
return () => InputPort.AnalogIn;
}
}
Func<int> InputMinimumChangeFeedbackFunc
{
get { return () => InputPort.AnalogMinChange; }
}
/// <inheritdoc />
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
/// <summary>
/// Initializes a new instance of the <see cref="GenericVersiportAnalogInputDevice"/> class.
/// </summary>
/// <param name="key">key for the device</param>
/// <param name="name">name for the device</param>
/// <param name="postActivationFunc">function to call after activation</param>
/// <param name="config">IO port configuration</param>
public GenericVersiportAnalogInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
base(key, name)
{
InputValueFeedback = new IntFeedback(InputValueFeedbackFunc);
InputMinimumChangeFeedback = new IntFeedback(InputMinimumChangeFeedbackFunc);
InputValueFeedback = new IntFeedback("inputValue", () => inputPort.AnalogIn);
InputMinimumChangeFeedback = new IntFeedback("inputMinimumChange", () => inputPort.AnalogMinChange);
AddPostActivationAction(() =>
{
InputPort = postActivationFunc(config);
inputPort = postActivationFunc(config);
InputPort.Register();
inputPort.Register();
InputPort.SetVersiportConfiguration(eVersiportConfiguration.AnalogInput);
InputPort.AnalogMinChange = (ushort)(config.MinimumChange > 0 ? config.MinimumChange : 655);
inputPort.SetVersiportConfiguration(eVersiportConfiguration.AnalogInput);
inputPort.AnalogMinChange = (ushort)(config.MinimumChange > 0 ? config.MinimumChange : 655);
if (config.DisablePullUpResistor)
InputPort.DisablePullUpResistor = true;
inputPort.DisablePullUpResistor = true;
InputPort.VersiportChange += InputPort_VersiportChange;
Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportAnalogInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
inputPort.VersiportChange += InputPort_VersiportChange;
this.LogDebug("Created GenericVersiportAnalogInputDevice on port {port}. DisablePullUpResistor: {pullUpResistorDisabled}", config.PortNumber, inputPort.DisablePullUpResistor);
});
}
@@ -69,20 +67,17 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// <summary>
/// Set minimum voltage change for device to update voltage changed method
/// </summary>
/// <param name="value">valid values range from 0 - 65535, representing the full 100% range of the processor voltage source. Check processor documentation for details</param>
/// <summary>
/// SetMinimumChange method
/// </summary>
/// <param name="value">valid values range from 0 - 65535, representing the full 100% range of the processor voltage source. Check processor documentation for details</param>
public void SetMinimumChange(ushort value)
{
InputPort.AnalogMinChange = value;
inputPort.AnalogMinChange = value;
}
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
this.LogDebug("Versiport change: {event}", args.Event);
if(args.Event == eVersiportEvent.AnalogInChange)
if (args.Event == eVersiportEvent.AnalogInChange)
InputValueFeedback.FireUpdate();
if (args.Event == eVersiportEvent.AnalogMinChangeChange)
InputMinimumChangeFeedback.FireUpdate();
@@ -91,9 +86,6 @@ namespace PepperDash.Essentials.Core.CrestronIO
#region Bridge Linking
/// <summary>
/// LinkToApi method
/// </summary>
/// <inheritdoc />
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
@@ -110,12 +102,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
try
{
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
this.LogDebug("Linking to Trilist '{trilistId}'", trilist.ID.ToString("X"));
// Link feedback for input state
InputValueFeedback.LinkInputSig(trilist.UShortInput[joinMap.InputValue.JoinNumber]);
@@ -125,8 +117,8 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
this.LogError("Unable to link device {key}: {message}", Key, e.Message);
this.LogDebug(e, "Stack Trace: ");
}
trilist.OnlineStatusChange += (d, args) =>
@@ -138,11 +130,6 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
void trilist_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args)
{
throw new NotImplementedException();
}
#endregion
@@ -151,70 +138,55 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// </summary>
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
{
IIOPorts ioPortDevice;
if (dc.PortDeviceKey.Equals("processor"))
{
if (!Global.ControlSystem.SupportsVersiport)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Processor does not support Versiports");
Debug.LogError("GetVersiportAnalogInput: Processor does not support Versiports");
return null;
}
ioPortDevice = Global.ControlSystem;
return Global.ControlSystem.VersiPorts[dc.PortNumber];
}
else
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IIOPorts ioPortDevice))
{
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
if (ioPortDev == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} is not a valid device", dc.PortDeviceKey);
return null;
}
ioPortDevice = ioPortDev;
}
if (ioPortDevice == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey);
Debug.LogError("GetVersiportAnalogInput: Device {key} is not a valid device", dc.PortDeviceKey);
return null;
}
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
Debug.LogError("GetVersiportAnalogInput: Device {key} does not contain a port {port}", dc.PortDeviceKey, dc.PortNumber);
return null;
}
if(!ioPortDevice.VersiPorts[dc.PortNumber].SupportsAnalogInput)
if (!ioPortDevice.VersiPorts[dc.PortNumber].SupportsAnalogInput)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportAnalogInput: Device {0} does not support AnalogInput on port {1}", dc.PortDeviceKey, dc.PortNumber);
Debug.LogError("GetVersiportAnalogInput: Device {key} does not support AnalogInput on port {port}", dc.PortDeviceKey, dc.PortNumber);
return null;
}
return ioPortDevice.VersiPorts[dc.PortNumber];
}
}
/// <summary>
/// Represents a GenericVersiportAbalogInputDeviceFactory
/// Factory for creating GenericVersiportAnalogInputDevice devices
/// </summary>
public class GenericVersiportAbalogInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportAnalogInputDevice>
public class GenericVersiportAnalogInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportAnalogInputDevice>
{
public GenericVersiportAbalogInputDeviceFactory()
/// <summary>
/// Constructor for GenericVersiportAnalogInputDeviceFactory
/// </summary>
public GenericVersiportAnalogInputDeviceFactory()
{
TypeNames = new List<string>() { "versiportanaloginput" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device");
Debug.LogDebug("Factory Attempting to create new Generic Versiport Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());

View File

@@ -2,78 +2,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using Newtonsoft.Json;
using Serilog.Events;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
/// <summary>
/// Represents a generic digital input deviced tied to a versiport
/// </summary>
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider
public class GenericVersiportDigitalInputDevice : EssentialsBridgeableDevice, IDigitalInput, IPartitionStateProvider, IHasFeedback
{
public Versiport InputPort { get; private set; }
private Versiport inputPort;
/// <summary>
/// Gets or sets the InputStateFeedback
/// </summary>
public BoolFeedback InputStateFeedback { get; private set; }
Func<bool> InputStateFeedbackFunc
{
get
{
return () => InputPort.DigitalIn;
}
}
/// <inheritdoc />
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
/// <summary>
/// Gets or sets the PartitionPresentFeedback
/// </summary>
public BoolFeedback PartitionPresentFeedback { get; }
public bool PartitionPresent => !InputStateFeedbackFunc();
/// <summary>
/// Get partition state
/// </summary>
public bool PartitionPresent => !inputPort.DigitalIn;
/// <summary>
/// Initializes a new instance of the <see cref="GenericVersiportDigitalInputDevice"/> class.
/// </summary>
/// <param name="key">key for device</param>
/// <param name="name">name for device</param>
/// <param name="postActivationFunc">function to call after activation. Should return the Versiport</param>
/// <param name="config">config for device</param>
public GenericVersiportDigitalInputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
base(key, name)
{
InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc);
PartitionPresentFeedback = new BoolFeedback(() => !InputStateFeedbackFunc());
InputStateFeedback = new BoolFeedback("inputState", () => inputPort.DigitalIn);
PartitionPresentFeedback = new BoolFeedback("partitionPresent", () => !inputPort.DigitalIn);
AddPostActivationAction(() =>
{
InputPort = postActivationFunc(config);
inputPort = postActivationFunc(config);
InputPort.Register();
inputPort.Register();
InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
inputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput);
if (config.DisablePullUpResistor)
InputPort.DisablePullUpResistor = true;
inputPort.DisablePullUpResistor = true;
InputPort.VersiportChange += InputPort_VersiportChange;
inputPort.VersiportChange += InputPort_VersiportChange;
InputStateFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate();
Debug.LogMessage(LogEventLevel.Debug, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", config.PortNumber, InputPort.DisablePullUpResistor);
this.LogDebug("Created GenericVersiportDigitalInputDevice for port {port}. DisablePullUpResistor: {pullUpResistorDisable}", config.PortNumber, inputPort.DisablePullUpResistor);
});
Feedbacks.Add(InputStateFeedback);
Feedbacks.Add(PartitionPresentFeedback);
}
void InputPort_VersiportChange(Versiport port, VersiportEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
this.LogDebug("Versiport change: {0}", args.Event);
if(args.Event == eVersiportEvent.DigitalInChange)
if (args.Event == eVersiportEvent.DigitalInChange)
{
InputStateFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate();
@@ -102,20 +106,20 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
try
{
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
InputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.InputState.JoinNumber]);
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
this.LogError("Unable to link device {key}. Input is null. {message}", Key, e.Message);
this.LogDebug(e, "Stack Trace: ");
}
}
@@ -127,63 +131,50 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// </summary>
public static Versiport GetVersiportDigitalInput(IOPortConfig dc)
{
IIOPorts ioPortDevice;
if (dc.PortDeviceKey.Equals("processor"))
{
if (!Global.ControlSystem.SupportsVersiport)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Processor does not support Versiports");
Debug.LogError("GetVersiportDigitalInput: Processor does not support Versiports");
return null;
}
ioPortDevice = Global.ControlSystem;
return Global.ControlSystem.VersiPorts[dc.PortNumber];
}
else
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IIOPorts ioPortDevice))
{
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
if (ioPortDev == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} is not a valid device", dc.PortDeviceKey);
return null;
}
ioPortDevice = ioPortDev;
}
if (ioPortDevice == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device '0' is not a valid IIOPorts Device", dc.PortDeviceKey);
Debug.LogError("GetVersiportDigitalInput: Device {key} is not a valid device", dc.PortDeviceKey);
return null;
}
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalInput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
Debug.LogError("GetVersiportDigitalInput: Device {key} does not contain versiport {port}", dc.PortDeviceKey, dc.PortNumber);
return null;
}
return ioPortDevice.VersiPorts[dc.PortNumber];
}
}
/// <summary>
/// Represents a GenericVersiportDigitalInputDeviceFactory
/// Factory class for GenericVersiportDigitalInputDevice
/// </summary>
public class GenericVersiportDigitalInputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
{
/// <summary>
/// Constructor for GenericVersiportDigitalInputDeviceFactory
/// </summary>
public GenericVersiportDigitalInputDeviceFactory()
{
TypeNames = new List<string>() { "versiportinput" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device");
Debug.LogDebug("Factory Attempting to create new Generic Versiport Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());

View File

@@ -2,18 +2,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Bridges;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using Serilog.Events;
namespace PepperDash.Essentials.Core.CrestronIO
@@ -21,76 +16,68 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// <summary>
/// Represents a generic digital input deviced tied to a versiport
/// </summary>
public class GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput
public class GenericVersiportDigitalOutputDevice : EssentialsBridgeableDevice, IDigitalOutput, IHasFeedback
{
public Versiport OutputPort { get; private set; }
private Versiport outputPort;
/// <summary>
/// Gets or sets the OutputStateFeedback
/// </summary>
public BoolFeedback OutputStateFeedback { get; private set; }
Func<bool> OutputStateFeedbackFunc
{
get
{
return () => OutputPort.DigitalOut;
}
}
/// <inheritdoc />
public FeedbackCollection<Feedback> Feedbacks { get; private set; } = new FeedbackCollection<Feedback>();
/// <summary>
/// Initializes a new instance of the <see cref="GenericVersiportDigitalOutputDevice"/> class.
/// </summary>
public GenericVersiportDigitalOutputDevice(string key, string name, Func<IOPortConfig, Versiport> postActivationFunc, IOPortConfig config) :
base(key, name)
{
OutputStateFeedback = new BoolFeedback(OutputStateFeedbackFunc);
OutputStateFeedback = new BoolFeedback("outputState", () => outputPort.DigitalOut);
AddPostActivationAction(() =>
{
OutputPort = postActivationFunc(config);
outputPort = postActivationFunc(config);
OutputPort.Register();
outputPort.Register();
if (!OutputPort.SupportsDigitalOutput)
if (!outputPort.SupportsDigitalOutput)
{
Debug.LogMessage(LogEventLevel.Information, this, "Device does not support configuration as a Digital Output");
this.LogError("Device does not support configuration as a Digital Output");
return;
}
OutputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput);
outputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalOutput);
OutputPort.VersiportChange += OutputPort_VersiportChange;
outputPort.VersiportChange += OutputPort_VersiportChange;
});
}
void OutputPort_VersiportChange(Versiport port, VersiportEventArgs args)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Versiport change: {0}", args.Event);
this.LogDebug("Versiport change: {event}", args.Event);
if(args.Event == eVersiportEvent.DigitalOutChange)
if (args.Event == eVersiportEvent.DigitalOutChange)
OutputStateFeedback.FireUpdate();
}
/// <summary>
/// Set value of the versiport digital output
/// </summary>
/// <param name="state">value to set the output to</param>
/// <summary>
/// SetOutput method
/// </summary>
/// <param name="state">value to set the output to</param>
public void SetOutput(bool state)
{
if (OutputPort.SupportsDigitalOutput)
{
Debug.LogMessage(LogEventLevel.Information, this, "Passed the Check");
OutputPort.DigitalOut = state;
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Versiport does not support Digital Output Mode");
}
if (!outputPort.SupportsDigitalOutput)
{
this.LogError("Versiport does not support Digital Output Mode");
return;
}
outputPort.DigitalOut = state;
}
#region Bridge Linking
@@ -114,12 +101,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
else
{
Debug.LogMessage(LogEventLevel.Information, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
try
{
Debug.LogMessage(LogEventLevel.Debug, this, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
// Link feedback for input state
OutputStateFeedback.LinkInputSig(trilist.BooleanInput[joinMap.OutputState.JoinNumber]);
@@ -127,8 +114,8 @@ namespace PepperDash.Essentials.Core.CrestronIO
}
catch (Exception e)
{
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to link device '{0}'. Input is null", Key);
Debug.LogMessage(LogEventLevel.Debug, this, "Error: {0}", e);
this.LogError("Unable to link device: {message}", e.Message);
this.LogDebug(e, "Stack Trace: ");
}
}
@@ -140,41 +127,28 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// </summary>
public static Versiport GetVersiportDigitalOutput(IOPortConfig dc)
{
IIOPorts ioPortDevice;
if (dc.PortDeviceKey.Equals("processor"))
if (dc.PortDeviceKey.Equals("processor"))
{
if (!Global.ControlSystem.SupportsVersiport)
{
if (!Global.ControlSystem.SupportsVersiport)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Processor does not support Versiports");
return null;
}
ioPortDevice = Global.ControlSystem;
}
else
{
var ioPortDev = DeviceManager.GetDeviceForKey(dc.PortDeviceKey) as IIOPorts;
if (ioPortDev == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} is not a valid device", dc.PortDeviceKey);
return null;
}
ioPortDevice = ioPortDev;
}
if (ioPortDevice == null)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device '0' is not a valid IOPorts Device", dc.PortDeviceKey);
Debug.LogError("GetVersiportDigitalOutput: Processor does not support Versiports");
return null;
}
return Global.ControlSystem.VersiPorts[dc.PortNumber];
}
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOuptut: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
}
var port = ioPortDevice.VersiPorts[dc.PortNumber];
return port;
if (!(DeviceManager.GetDeviceForKey(dc.PortDeviceKey) is IIOPorts ioPortDevice))
{
Debug.LogError("GetVersiportDigitalOutput: Device {key} is not a valid device", dc.PortDeviceKey);
return null;
}
if (dc.PortNumber > ioPortDevice.NumberOfVersiPorts)
{
Debug.LogMessage(LogEventLevel.Information, "GetVersiportDigitalOutput: Device {0} does not contain a port {1}", dc.PortDeviceKey, dc.PortNumber);
return null;
}
return ioPortDevice.VersiPorts[dc.PortNumber];
}
}
@@ -184,18 +158,18 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// </summary>
public class GenericVersiportDigitalOutputDeviceFactory : EssentialsDeviceFactory<GenericVersiportDigitalInputDevice>
{
/// <summary>
/// Initialize a new instance of the <see cref="GenericVersiportDigitalOutputDeviceFactory"/> class.
/// </summary>
public GenericVersiportDigitalOutputDeviceFactory()
{
TypeNames = new List<string>() { "versiportoutput" };
}
/// <summary>
/// BuildDevice method
/// </summary>
/// <inheritdoc />
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Versiport Device");
Debug.LogDebug("Factory Attempting to create new Generic Versiport Device");
var props = JsonConvert.DeserializeObject<IOPortConfig>(dc.Properties.ToString());

View File

@@ -12,6 +12,12 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// </summary>
public interface IAnalogInput
{
/// <summary>
/// Get the InputValueFeedback.
/// </summary>
/// <remarks>
/// Updates when the analog input value changes
/// </remarks>
IntFeedback InputValueFeedback { get; }
}
}

View File

@@ -14,25 +14,28 @@ namespace PepperDash.Essentials.Core.CrestronIO
/// </summary>
public class IOPortConfig
{
[JsonProperty("portDeviceKey")]
/// <summary>
/// Gets or sets the PortDeviceKey
/// </summary>
[JsonProperty("portDeviceKey")]
public string PortDeviceKey { get; set; }
[JsonProperty("portNumber")]
/// <summary>
/// Gets or sets the PortNumber
/// </summary>
[JsonProperty("portNumber")]
public uint PortNumber { get; set; }
[JsonProperty("disablePullUpResistor")]
/// <summary>
/// Gets or sets the DisablePullUpResistor
/// </summary>
[JsonProperty("disablePullUpResistor")]
public bool DisablePullUpResistor { get; set; }
[JsonProperty("minimumChange")]
/// <summary>
/// Gets or sets the MinimumChange
/// </summary>
[JsonProperty("minimumChange")]
public int MinimumChange { get; set; }
}
}

View File

@@ -18,7 +18,7 @@ namespace PepperDash.Essentials.Core
public List<string> TypeNames { get; protected set; }
/// <summary>
/// The method that will build the device
/// Build the device using the configuration
/// </summary>
/// <param name="dc">The device config</param>
/// <returns>An instance of the device</returns>

View File

@@ -12,7 +12,7 @@ namespace PepperDash.Essentials.Core
public interface IHasFeedback : IKeyed
{
/// <summary>
/// This method shall return a list of all Output objects on a device,
/// This method returns a list of all Output objects on a device,
/// including all "aggregate" devices.
/// </summary>
FeedbackCollection<Feedback> Feedbacks { get; }

View File

@@ -103,6 +103,12 @@ namespace PepperDash.Essentials.Core
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to hide this scenario in the UI.
/// </summary>
[JsonProperty("hideInUi", NullValueHandling = NullValueHandling.Ignore)]
public bool HideInUi { get; set; }
/// <summary>
/// Gets or sets the collection of partition states.
/// </summary>

View File

@@ -109,6 +109,12 @@ namespace PepperDash.Essentials.Core
[JsonProperty("isActive")]
bool IsActive { get; }
/// <summary>
/// Gets a value indicating whether this scenario should be hidden in the UI.
/// </summary>
[JsonProperty("hideInUi")]
bool HideInUi { get; }
/// <summary>
/// Activates this room combination scenario
/// </summary>

View File

@@ -14,18 +14,40 @@ namespace PepperDash.Essentials.Core
{
private RoomCombinationScenarioConfig _config;
/// <summary>
/// Gets or sets the key associated with the object.
/// </summary>
[JsonProperty("key")]
public string Key { get; set; }
/// <summary>
/// Gets or sets the name associated with the object.
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("partitionStates")]
/// <summary>
/// Gets a value indicating whether to hide this scenario in the UI.
/// </summary>
///
[JsonProperty("hideInUi")]
public bool HideInUi
{
get { return _config.HideInUi; }
}
/// <summary>
/// Gets or sets the PartitionStates
/// </summary>
///
[JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; private set; }
/// <summary>
/// Determines which UI devices get mapped to which room in this scenario. The Key should be the key of the UI device and the Value should be the key of the room to map to
/// </summary>
[JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; }

View File

@@ -1,9 +1,10 @@
using Newtonsoft.Json;
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
using PepperDash.Core.Logging;
using PepperDash.Essentials.Core;
using System;
namespace PepperDash.Essentials.AppServer.Messengers
{
@@ -12,35 +13,46 @@ namespace PepperDash.Essentials.AppServer.Messengers
/// </summary>
public class DeviceVolumeMessenger : MessengerBase
{
private readonly IBasicVolumeWithFeedback _localDevice;
private readonly IBasicVolumeControls device;
public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeWithFeedback device)
/// <summary>
/// Initializes a new instance of the <see cref="DeviceVolumeMessenger"/> class.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="messagePath">The message path.</param>
/// <param name="device">The device.</param>
public DeviceVolumeMessenger(string key, string messagePath, IBasicVolumeControls device)
: base(key, messagePath, device as IKeyName)
{
_localDevice = device;
this.device = device;
}
private void SendStatus()
private void SendStatus(string id = null)
{
try
{
if (!(device is IBasicVolumeWithFeedback feedbackDevice))
{
return;
}
var messageObj = new VolumeStateMessage
{
Volume = new Volume
{
Level = _localDevice?.VolumeLevelFeedback.IntValue ?? -1,
Muted = _localDevice?.MuteFeedback.BoolValue ?? false,
Level = feedbackDevice?.VolumeLevelFeedback.IntValue ?? -1,
Muted = feedbackDevice?.MuteFeedback.BoolValue ?? false,
HasMute = true, // assume all devices have mute for now
}
};
if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
if (device is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
{
messageObj.Volume.RawValue = volumeAdvanced.RawVolumeLevel.ToString();
messageObj.Volume.Units = volumeAdvanced.Units;
}
PostStatusMessage(messageObj);
PostStatusMessage(messageObj, id);
}
catch (Exception ex)
{
@@ -53,44 +65,23 @@ namespace PepperDash.Essentials.AppServer.Messengers
protected override void RegisterActions()
{
AddAction("/fullStatus", (id, content) => SendStatus());
AddAction("/level", (id, content) =>
{
var volume = content.ToObject<MobileControlSimpleContent<ushort>>();
_localDevice.SetVolume(volume.Value);
});
AddAction("/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume up with {value}", DeviceKey, b);
try
{
device.VolumeUp(b);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Got exception during volume up: {Exception}", null, ex);
}
}));
AddAction("/muteToggle", (id, content) =>
{
_localDevice.MuteToggle();
});
AddAction("/muteOn", (id, content) =>
{
_localDevice.MuteOn();
});
AddAction("/muteOff", (id, content) =>
{
_localDevice.MuteOff();
});
AddAction("/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, "Calling {localDevice} volume up with {value}", DeviceKey, b);
try
{
_localDevice.VolumeUp(b);
}
catch (Exception ex)
{
Debug.LogMessage(ex, "Got exception during volume up: {Exception}", null, ex);
}
}));
{
device.MuteToggle();
});
AddAction("/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
{
@@ -98,7 +89,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
try
{
_localDevice.VolumeDown(b);
device.VolumeDown(b);
}
catch (Exception ex)
{
@@ -106,7 +97,38 @@ namespace PepperDash.Essentials.AppServer.Messengers
}
}));
_localDevice.MuteFeedback.OutputChange += (sender, args) =>
if (!(device is IBasicVolumeWithFeedback feedback))
{
this.LogDebug("Skipping feedback methods for {deviceKey}", (device as IKeyName)?.Key);
return;
}
AddAction("/fullStatus", (id, content) => SendStatus(id));
AddAction("/volumeStatus", (id, content) => SendStatus(id));
AddAction("/level", (id, content) =>
{
var volume = content.ToObject<MobileControlSimpleContent<ushort>>();
feedback.SetVolume(volume.Value);
});
AddAction("/muteOn", (id, content) =>
{
feedback.MuteOn();
});
AddAction("/muteOff", (id, content) =>
{
feedback.MuteOff();
});
feedback.MuteFeedback.OutputChange += (sender, args) =>
{
PostStatusMessage(JToken.FromObject(
new
@@ -119,10 +141,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
);
};
_localDevice.VolumeLevelFeedback.OutputChange += (sender, args) =>
feedback.VolumeLevelFeedback.OutputChange += (sender, args) =>
{
var rawValue = "";
if (_localDevice is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
if (feedback is IBasicVolumeWithFeedbackAdvanced volumeAdvanced)
{
rawValue = volumeAdvanced.RawVolumeLevel.ToString();
}
@@ -138,8 +160,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
PostStatusMessage(JToken.FromObject(message));
};
}
#endregion

View File

@@ -488,15 +488,15 @@ namespace PepperDash.Essentials
messengerAdded = true;
}
if (device is IBasicVolumeWithFeedback)
if (device is IBasicVolumeControls)
{
var deviceKey = device.Key;
this.LogVerbose(
"Adding IBasicVolumeControlWithFeedback for {deviceKey}",
"Adding IBasicVolumeControls for {deviceKey}",
deviceKey
);
var volControlDevice = device as IBasicVolumeWithFeedback;
var volControlDevice = device as IBasicVolumeControls;
var messenger = new DeviceVolumeMessenger(
$"{device.Key}-volume-{Key}",
string.Format("/device/{0}", deviceKey),

View File

@@ -16,6 +16,7 @@ using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceInfo;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.UI;
using Serilog.Events;
using Feedback = PepperDash.Essentials.Core.Feedback;
namespace PepperDash.Essentials.Touchpanel
@@ -190,12 +191,6 @@ namespace PepperDash.Essentials.Touchpanel
RegisterForExtenders();
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Appliance)
{
this.LogInformation("Not running on processor. Skipping CS LAN Configuration");
return;
}
try
{
var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter);
@@ -205,11 +200,6 @@ namespace PepperDash.Essentials.Touchpanel
this.csSubnetMask = System.Net.IPAddress.Parse(csSubnetMask);
this.csIpAddress = System.Net.IPAddress.Parse(csIpAddress);
}
catch (ArgumentException)
{
this.LogInformation("This processor does not have a CS LAN");
}
}
/// <summary>
/// Updates the theme setting for this touchpanel controller and persists the change to configuration.
@@ -515,7 +505,7 @@ namespace PepperDash.Essentials.Touchpanel
_bridge.UserCodeChanged += UpdateFeedbacks;
_bridge.AppUrlChanged += (s, a) =>
{
this.LogInformation("AppURL changed");
this.LogInformation("AppURL changed: {appURL}", _bridge.AppUrl);
SetAppUrl(_bridge.AppUrl);
UpdateFeedbacks(s, a);
};