Merge pull request #248 from PepperDash/feature/implement-IStreamDebugging-on-ComPortController

Add IStreamDebugging interface to ComPortController
This commit is contained in:
Andrew Welker 2020-06-10 15:58:17 -06:00 committed by GitHub
commit 84d8ff410e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 330 additions and 238 deletions

View file

@ -11,8 +11,10 @@ using PepperDash.Core;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
public class ComPortController : Device, IBasicCommunication public class ComPortController : Device, IBasicCommunicationWithStreamDebugging
{ {
public CommunicationStreamDebugging StreamDebugging { get; private set; }
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived; public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived; public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
@ -24,6 +26,8 @@ namespace PepperDash.Essentials.Core
public ComPortController(string key, Func<EssentialsControlPropertiesConfig, ComPort> postActivationFunc, public ComPortController(string key, Func<EssentialsControlPropertiesConfig, ComPort> postActivationFunc,
ComPort.ComPortSpec spec, EssentialsControlPropertiesConfig config) : base(key) ComPort.ComPortSpec spec, EssentialsControlPropertiesConfig config) : base(key)
{ {
StreamDebugging = new CommunicationStreamDebugging(key);
Spec = spec; Spec = spec;
AddPostActivationAction(() => AddPostActivationAction(() =>
@ -91,7 +95,12 @@ namespace PepperDash.Essentials.Core
} }
var textHandler = TextReceived; var textHandler = TextReceived;
if (textHandler != null) if (textHandler != null)
{
if (StreamDebugging.RxStreamDebuggingIsEnabled)
Debug.Console(0, this, "Recevied: '{0}'", s);
textHandler(this, new GenericCommMethodReceiveTextArgs(s)); textHandler(this, new GenericCommMethodReceiveTextArgs(s));
}
} }
public override bool Deactivate() public override bool Deactivate()
@ -105,7 +114,10 @@ namespace PepperDash.Essentials.Core
{ {
if (Port == null) if (Port == null)
return; return;
Port.Send(text);
if (StreamDebugging.TxStreamDebuggingIsEnabled)
Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, text);
Port.Send(text);
} }
public void SendBytes(byte[] bytes) public void SendBytes(byte[] bytes)
@ -113,6 +125,9 @@ namespace PepperDash.Essentials.Core
if (Port == null) if (Port == null)
return; return;
var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length);
if (StreamDebugging.TxStreamDebuggingIsEnabled)
Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes));
Port.Send(text); Port.Send(text);
} }

View file

@ -43,7 +43,10 @@ namespace PepperDash.Essentials.Core
CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)), "apimethods", "", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive", CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive",
"Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator); "Simulates incoming data on a com device", 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> /// <summary>
/// Calls activate steps on all Device class items /// Calls activate steps on all Device class items
@ -299,5 +302,79 @@ namespace PepperDash.Essentials.Core
} }
com.SimulateReceive(match.Groups[2].Value); com.SimulateReceive(match.Groups[2].Value);
} }
/// <summary>
/// Attempts to set the debug level of a device
/// </summary>
/// <param name="s"></param>
public static void SetDeviceStreamDebugging(string s)
{
var args = s.Split(' ');
var deviceKey = args[0];
var setting = args[1];
var timeout = args[2];
var device = GetDeviceForKey(deviceKey) as IStreamDebugging;
if (device == null)
{
Debug.Console(0, "Unable to get device with key: {0}", deviceKey);
return;
}
else
{
eStreamDebuggingSetting debugSetting = eStreamDebuggingSetting.Off;
try
{
debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), setting, true);
}
catch
{
Debug.Console(0, "Unable to convert setting value. Please use off/rx/tx/both");
return;
}
if (!string.IsNullOrEmpty(timeout))
{
try
{
var min = Convert.ToUInt32(timeout);
device.StreamDebugging.SetDebuggingWithSpecificTimeout(debugSetting, min);
Debug.Console(0, "Device: '{0}' debug level set to {1) for {2} minutes", deviceKey, debugSetting, min);
}
catch (Exception e)
{
Debug.Console(0, "Unable to convert minutes or settings value. Please use an integer value for minutes. Errro: {0}", e);
return;
}
}
else
{
device.StreamDebugging.SetDebuggingWithDefaultTimeout(debugSetting);
Debug.Console(0, "Device: '{0}' debug level set to {1) for default time (30 minutes)", deviceKey, debugSetting);
}
}
}
/// <summary>
/// Sets stream debugging settings to off for all devices
/// </summary>
public static void DisableAllDeviceStreamDebugging()
{
foreach (var device in AllDevices)
{
var streamDevice = device as IStreamDebugging;
if (streamDevice != null)
{
streamDevice.StreamDebugging.SetDebuggingWithDefaultTimeout(eStreamDebuggingSetting.Off);
}
}
}
} }
} }

View file

@ -1,236 +1,236 @@
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 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.Bridges; using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Routing; using PepperDash.Essentials.Core.Routing;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
[Description("Wrapper class for a Basic IR Display")] [Description("Wrapper class for a Basic IR Display")]
public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced public class BasicIrDisplay : DisplayBase, IBasicVolumeControls, IBridgeAdvanced
{ {
public IrOutputPortController IrPort { get; private set; } public IrOutputPortController IrPort { get; private set; }
public ushort IrPulseTime { get; set; } public ushort IrPulseTime { get; set; }
protected override Func<bool> PowerIsOnFeedbackFunc protected override Func<bool> PowerIsOnFeedbackFunc
{ {
get { return () => _PowerIsOn; } get { return () => _PowerIsOn; }
} }
protected override Func<bool> IsCoolingDownFeedbackFunc protected override Func<bool> IsCoolingDownFeedbackFunc
{ {
get { return () => _IsCoolingDown; } get { return () => _IsCoolingDown; }
} }
protected override Func<bool> IsWarmingUpFeedbackFunc protected override Func<bool> IsWarmingUpFeedbackFunc
{ {
get { return () => _IsWarmingUp; } get { return () => _IsWarmingUp; }
} }
bool _PowerIsOn; bool _PowerIsOn;
bool _IsWarmingUp; bool _IsWarmingUp;
bool _IsCoolingDown; bool _IsCoolingDown;
public BasicIrDisplay(string key, string name, IROutputPort port, string irDriverFilepath) public BasicIrDisplay(string key, string name, IROutputPort port, string irDriverFilepath)
: base(key, name) : base(key, name)
{ {
IrPort = new IrOutputPortController(key + "-ir", port, irDriverFilepath); IrPort = new IrOutputPortController(key + "-ir", port, irDriverFilepath);
DeviceManager.AddDevice(IrPort); DeviceManager.AddDevice(IrPort);
PowerIsOnFeedback.OutputChange += (o, a) => { PowerIsOnFeedback.OutputChange += (o, a) => {
Debug.Console(2, this, "Power on={0}", _PowerIsOn); Debug.Console(2, this, "Power on={0}", _PowerIsOn);
if (_PowerIsOn) StartWarmingTimer(); if (_PowerIsOn) StartWarmingTimer();
else StartCoolingTimer(); else StartCoolingTimer();
}; };
IsWarmingUpFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Warming up={0}", _IsWarmingUp); IsWarmingUpFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Warming up={0}", _IsWarmingUp);
IsCoolingDownFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Cooling down={0}", _IsCoolingDown); IsCoolingDownFeedback.OutputChange += (o, a) => Debug.Console(2, this, "Cooling down={0}", _IsCoolingDown);
InputPorts.AddRange(new RoutingPortCollection<RoutingInputPort> InputPorts.AddRange(new RoutingPortCollection<RoutingInputPort>
{ {
new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video, new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi1), this, false), eRoutingPortConnectionType.Hdmi, new Action(Hdmi1), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video, new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi2), this, false), eRoutingPortConnectionType.Hdmi, new Action(Hdmi2), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video, new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi3), this, false), eRoutingPortConnectionType.Hdmi, new Action(Hdmi3), this, false),
new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video, new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Hdmi4), this, false), eRoutingPortConnectionType.Hdmi, new Action(Hdmi4), this, false),
new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, new RoutingInputPort(RoutingPortNames.ComponentIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Component1), this, false), eRoutingPortConnectionType.Hdmi, new Action(Component1), this, false),
new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Video1), this, false), eRoutingPortConnectionType.Hdmi, new Action(Video1), this, false),
new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video, new RoutingInputPort(RoutingPortNames.AntennaIn, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, new Action(Antenna), this, false), eRoutingPortConnectionType.Hdmi, new Action(Antenna), this, false),
}); });
} }
public void Hdmi1() public void Hdmi1()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_1, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_1, IrPulseTime);
} }
public void Hdmi2() public void Hdmi2()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_2, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_2, IrPulseTime);
} }
public void Hdmi3() public void Hdmi3()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_3, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_3, IrPulseTime);
} }
public void Hdmi4() public void Hdmi4()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_4, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_HDMI_4, IrPulseTime);
} }
public void Component1() public void Component1()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_COMPONENT_1, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_COMPONENT_1, IrPulseTime);
} }
public void Video1() public void Video1()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_VIDEO_1, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_VIDEO_1, IrPulseTime);
} }
public void Antenna() public void Antenna()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_ANTENNA, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_ANTENNA, IrPulseTime);
} }
#region IPower Members #region IPower Members
public override void PowerOn() public override void PowerOn()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_POWER_ON, IrPulseTime);
_PowerIsOn = true; _PowerIsOn = true;
PowerIsOnFeedback.FireUpdate(); PowerIsOnFeedback.FireUpdate();
} }
public override void PowerOff() public override void PowerOff()
{ {
_PowerIsOn = false; _PowerIsOn = false;
PowerIsOnFeedback.FireUpdate(); PowerIsOnFeedback.FireUpdate();
IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_POWER_OFF, IrPulseTime);
} }
public override void PowerToggle() public override void PowerToggle()
{ {
_PowerIsOn = false; _PowerIsOn = false;
PowerIsOnFeedback.FireUpdate(); PowerIsOnFeedback.FireUpdate();
IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime); IrPort.Pulse(IROutputStandardCommands.IROut_POWER, IrPulseTime);
} }
#endregion #endregion
#region IBasicVolumeControls Members #region IBasicVolumeControls Members
public void VolumeUp(bool pressRelease) public void VolumeUp(bool pressRelease)
{ {
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_PLUS, pressRelease); IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_PLUS, pressRelease);
} }
public void VolumeDown(bool pressRelease) public void VolumeDown(bool pressRelease)
{ {
IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_MINUS, pressRelease); IrPort.PressRelease(IROutputStandardCommands.IROut_VOL_MINUS, pressRelease);
} }
public void MuteToggle() public void MuteToggle()
{ {
IrPort.Pulse(IROutputStandardCommands.IROut_MUTE, 200); IrPort.Pulse(IROutputStandardCommands.IROut_MUTE, 200);
} }
#endregion #endregion
void StartWarmingTimer() void StartWarmingTimer()
{ {
_IsWarmingUp = true; _IsWarmingUp = true;
IsWarmingUpFeedback.FireUpdate(); IsWarmingUpFeedback.FireUpdate();
new CTimer(o => { new CTimer(o => {
_IsWarmingUp = false; _IsWarmingUp = false;
IsWarmingUpFeedback.FireUpdate(); IsWarmingUpFeedback.FireUpdate();
}, 10000); }, 10000);
} }
void StartCoolingTimer() void StartCoolingTimer()
{ {
_IsCoolingDown = true; _IsCoolingDown = true;
IsCoolingDownFeedback.FireUpdate(); IsCoolingDownFeedback.FireUpdate();
new CTimer(o => new CTimer(o =>
{ {
_IsCoolingDown = false; _IsCoolingDown = false;
IsCoolingDownFeedback.FireUpdate(); IsCoolingDownFeedback.FireUpdate();
}, 7000); }, 7000);
} }
#region IRoutingSink Members #region IRoutingSink Members
/// <summary> /// <summary>
/// Typically called by the discovery routing algorithm. /// Typically called by the discovery routing algorithm.
/// </summary> /// </summary>
/// <param name="inputSelector">A delegate containing the input selector method to call</param> /// <param name="inputSelector">A delegate containing the input selector method to call</param>
public override void ExecuteSwitch(object inputSelector) public override void ExecuteSwitch(object inputSelector)
{ {
Debug.Console(2, this, "Switching to input '{0}'", (inputSelector as Action).ToString()); Debug.Console(2, this, "Switching to input '{0}'", (inputSelector as Action).ToString());
Action finishSwitch = () => Action finishSwitch = () =>
{ {
var action = inputSelector as Action; var action = inputSelector as Action;
if (action != null) if (action != null)
action(); action();
}; };
if (!PowerIsOnFeedback.BoolValue) if (!PowerIsOnFeedback.BoolValue)
{ {
PowerOn(); PowerOn();
EventHandler<FeedbackEventArgs> oneTimer = null; EventHandler<FeedbackEventArgs> oneTimer = null;
oneTimer = (o, a) => oneTimer = (o, a) =>
{ {
if (IsWarmingUpFeedback.BoolValue) return; // Only catch done warming if (IsWarmingUpFeedback.BoolValue) return; // Only catch done warming
IsWarmingUpFeedback.OutputChange -= oneTimer; IsWarmingUpFeedback.OutputChange -= oneTimer;
finishSwitch(); finishSwitch();
}; };
IsWarmingUpFeedback.OutputChange += oneTimer; IsWarmingUpFeedback.OutputChange += oneTimer;
} }
else // Do it! else // Do it!
finishSwitch(); finishSwitch();
} }
#endregion #endregion
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{ {
LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge); LinkDisplayToApi(this, trilist, joinStart, joinMapKey, bridge);
} }
} }
public class BasicIrDisplayFactory : EssentialsDeviceFactory<BasicIrDisplay> public class BasicIrDisplayFactory : EssentialsDeviceFactory<BasicIrDisplay>
{ {
public BasicIrDisplayFactory() public BasicIrDisplayFactory()
{ {
TypeNames = new List<string>() { "basicirdisplay" }; TypeNames = new List<string>() { "basicirdisplay" };
} }
public override EssentialsDevice BuildDevice(DeviceConfig dc) public override EssentialsDevice BuildDevice(DeviceConfig dc)
{ {
Debug.Console(1, "Factory Attempting to create new BasicIrDisplay Device"); Debug.Console(1, "Factory Attempting to create new BasicIrDisplay Device");
var ir = IRPortHelper.GetIrPort(dc.Properties); var ir = IRPortHelper.GetIrPort(dc.Properties);
if (ir != null) if (ir != null)
{ {
var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName); var display = new BasicIrDisplay(dc.Key, dc.Name, ir.Port, ir.FileName);
display.IrPulseTime = 200; // Set default pulse time for IR commands. display.IrPulseTime = 200; // Set default pulse time for IR commands.
return display; return display;
} }
return null; return null;
} }
} }
} }

View file

@ -64,7 +64,7 @@
</Reference> </Reference>
<Reference Include="Crestron.SimplSharpPro.Gateways, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="Crestron.SimplSharpPro.Gateways, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath> <HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Gateways.dll</HintPath>
</Reference> </Reference>
<Reference Include="Crestron.SimplSharpPro.GeneralIO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL"> <Reference Include="Crestron.SimplSharpPro.GeneralIO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>

@ -1 +1 @@
Subproject commit 15206840b3e6338f695e4ffba634a72e51ea1be5 Subproject commit 974d2f473c06b2c90b18c06e0f758ca47d466be8