mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-08 01:04:56 +00:00
test: initial attempt at tests with Claude Code
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapter that wraps actual Crestron Control System for production use
|
||||
/// </summary>
|
||||
public class CrestronControlSystemAdapter : ICrestronControlSystem
|
||||
{
|
||||
private readonly CrestronControlSystem _controlSystem;
|
||||
private readonly Dictionary<uint, IRelayPort> _relayPorts;
|
||||
|
||||
public CrestronControlSystemAdapter(CrestronControlSystem controlSystem)
|
||||
{
|
||||
_controlSystem = controlSystem ?? throw new ArgumentNullException(nameof(controlSystem));
|
||||
_relayPorts = new Dictionary<uint, IRelayPort>();
|
||||
|
||||
if (_controlSystem.SupportsRelay)
|
||||
{
|
||||
for (uint i = 1; i <= (uint)_controlSystem.NumberOfRelayPorts; i++)
|
||||
{
|
||||
_relayPorts[i] = new RelayPortAdapter(_controlSystem.RelayPorts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsRelay => _controlSystem.SupportsRelay;
|
||||
public uint NumberOfRelayPorts => (uint)_controlSystem.NumberOfRelayPorts;
|
||||
public Dictionary<uint, IRelayPort> RelayPorts => _relayPorts;
|
||||
public string ProgramIdTag => "TestProgram"; // Simplified for now
|
||||
public string ControllerPrompt => _controlSystem.ControllerPrompt;
|
||||
public bool SupportsEthernet => _controlSystem.SupportsEthernet;
|
||||
public bool SupportsDigitalInput => _controlSystem.SupportsDigitalInput;
|
||||
public uint NumberOfDigitalInputPorts => (uint)_controlSystem.NumberOfDigitalInputPorts;
|
||||
public bool SupportsVersiPort => _controlSystem.SupportsVersiport;
|
||||
public uint NumberOfVersiPorts => (uint)_controlSystem.NumberOfVersiPorts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapter for Crestron relay port
|
||||
/// </summary>
|
||||
public class RelayPortAdapter : IRelayPort
|
||||
{
|
||||
private readonly Crestron.SimplSharpPro.Relay _relay;
|
||||
|
||||
public RelayPortAdapter(Crestron.SimplSharpPro.Relay relay)
|
||||
{
|
||||
_relay = relay ?? throw new ArgumentNullException(nameof(relay));
|
||||
}
|
||||
|
||||
public void Open() => _relay.Open();
|
||||
public void Close() => _relay.Close();
|
||||
public void Pulse(int delayMs)
|
||||
{
|
||||
// Crestron Relay.Pulse() doesn't take parameters
|
||||
// We'll just call the basic Pulse method
|
||||
_relay.Close();
|
||||
System.Threading.Thread.Sleep(delayMs);
|
||||
_relay.Open();
|
||||
}
|
||||
public bool State => _relay.State;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapter for Crestron digital input
|
||||
/// </summary>
|
||||
public class DigitalInputAdapter : IDigitalInput
|
||||
{
|
||||
private readonly Crestron.SimplSharpPro.DigitalInput _digitalInput;
|
||||
|
||||
public DigitalInputAdapter(Crestron.SimplSharpPro.DigitalInput digitalInput)
|
||||
{
|
||||
_digitalInput = digitalInput ?? throw new ArgumentNullException(nameof(digitalInput));
|
||||
_digitalInput.StateChange += OnStateChange;
|
||||
}
|
||||
|
||||
public bool State => _digitalInput.State;
|
||||
public event EventHandler<DigitalInputEventArgs> StateChange;
|
||||
|
||||
private void OnStateChange(DigitalInput digitalInput, Crestron.SimplSharpPro.DigitalInputEventArgs args)
|
||||
{
|
||||
StateChange?.Invoke(this, new Abstractions.DigitalInputEventArgs(args.State));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapter for Crestron VersiPort
|
||||
/// </summary>
|
||||
public class VersiPortAdapter : IVersiPort
|
||||
{
|
||||
private readonly Crestron.SimplSharpPro.Versiport _versiPort;
|
||||
|
||||
public VersiPortAdapter(Crestron.SimplSharpPro.Versiport versiPort)
|
||||
{
|
||||
_versiPort = versiPort ?? throw new ArgumentNullException(nameof(versiPort));
|
||||
_versiPort.VersiportChange += OnVersiportChange;
|
||||
}
|
||||
|
||||
public bool DigitalIn => _versiPort.DigitalIn;
|
||||
public void SetDigitalOut(bool value) => _versiPort.DigitalOut = value;
|
||||
public ushort AnalogIn => _versiPort.AnalogIn;
|
||||
public event EventHandler<VersiPortEventArgs> VersiportChange;
|
||||
|
||||
private void OnVersiportChange(Versiport port, VersiportEventArgs args)
|
||||
{
|
||||
var eventType = args.Event == eVersiportEvent.DigitalInChange
|
||||
? VersiPortEventType.DigitalInChange
|
||||
: VersiPortEventType.AnalogInChange;
|
||||
|
||||
VersiportChange?.Invoke(this, new Abstractions.VersiPortEventArgs
|
||||
{
|
||||
EventType = eventType,
|
||||
Value = args.Event == eVersiportEvent.DigitalInChange ? (object)port.DigitalIn : port.AnalogIn
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstraction for Crestron Control System to enable unit testing
|
||||
/// </summary>
|
||||
public interface ICrestronControlSystem
|
||||
{
|
||||
bool SupportsRelay { get; }
|
||||
uint NumberOfRelayPorts { get; }
|
||||
Dictionary<uint, IRelayPort> RelayPorts { get; }
|
||||
string ProgramIdTag { get; }
|
||||
string ControllerPrompt { get; }
|
||||
bool SupportsEthernet { get; }
|
||||
bool SupportsDigitalInput { get; }
|
||||
uint NumberOfDigitalInputPorts { get; }
|
||||
bool SupportsVersiPort { get; }
|
||||
uint NumberOfVersiPorts { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction for relay port
|
||||
/// </summary>
|
||||
public interface IRelayPort
|
||||
{
|
||||
void Open();
|
||||
void Close();
|
||||
void Pulse(int delayMs);
|
||||
bool State { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction for digital input
|
||||
/// </summary>
|
||||
public interface IDigitalInput
|
||||
{
|
||||
bool State { get; }
|
||||
event EventHandler<DigitalInputEventArgs> StateChange;
|
||||
}
|
||||
|
||||
public class DigitalInputEventArgs : EventArgs
|
||||
{
|
||||
public bool State { get; set; }
|
||||
public DigitalInputEventArgs(bool state)
|
||||
{
|
||||
State = state;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction for VersiPort
|
||||
/// </summary>
|
||||
public interface IVersiPort
|
||||
{
|
||||
bool DigitalIn { get; }
|
||||
void SetDigitalOut(bool value);
|
||||
ushort AnalogIn { get; }
|
||||
event EventHandler<VersiPortEventArgs> VersiportChange;
|
||||
}
|
||||
|
||||
public class VersiPortEventArgs : EventArgs
|
||||
{
|
||||
public VersiPortEventType EventType { get; set; }
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
public enum VersiPortEventType
|
||||
{
|
||||
DigitalInChange,
|
||||
AnalogInChange
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Abstractions;
|
||||
using PepperDash.Essentials.Core.CrestronIO;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Devices
|
||||
{
|
||||
/// <summary>
|
||||
/// Testable version of CrestronProcessor that uses abstractions
|
||||
/// </summary>
|
||||
public class CrestronProcessorTestable : Device, ISwitchedOutputCollection
|
||||
{
|
||||
public Dictionary<uint, ISwitchedOutput> SwitchedOutputs { get; private set; }
|
||||
|
||||
public ICrestronControlSystem Processor { get; private set; }
|
||||
|
||||
public CrestronProcessorTestable(string key, ICrestronControlSystem processor)
|
||||
: base(key)
|
||||
{
|
||||
SwitchedOutputs = new Dictionary<uint, ISwitchedOutput>();
|
||||
Processor = processor ?? throw new ArgumentNullException(nameof(processor));
|
||||
GetRelays();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GenericRelayDevice for each relay on the processor and adds them to the SwitchedOutputs collection
|
||||
/// </summary>
|
||||
void GetRelays()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Processor.SupportsRelay)
|
||||
{
|
||||
for (uint i = 1; i <= Processor.NumberOfRelayPorts; i++)
|
||||
{
|
||||
if (Processor.RelayPorts.ContainsKey(i))
|
||||
{
|
||||
var relay = new GenericRelayDeviceTestable(
|
||||
string.Format("{0}-relay-{1}", this.Key, i),
|
||||
Processor.RelayPorts[i]);
|
||||
SwitchedOutputs.Add(i, relay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Debug, this, "Error Getting Relays from processor:\n '{0}'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Testable version of GenericRelayDevice
|
||||
/// </summary>
|
||||
public class GenericRelayDeviceTestable : Device, ISwitchedOutput
|
||||
{
|
||||
private readonly IRelayPort _relayPort;
|
||||
|
||||
public GenericRelayDeviceTestable(string key, IRelayPort relayPort)
|
||||
: base(key)
|
||||
{
|
||||
_relayPort = relayPort ?? throw new ArgumentNullException(nameof(relayPort));
|
||||
OutputIsOnFeedback = new BoolFeedback(() => IsOn);
|
||||
}
|
||||
|
||||
public void OpenRelay()
|
||||
{
|
||||
_relayPort.Open();
|
||||
OutputIsOnFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
public void CloseRelay()
|
||||
{
|
||||
_relayPort.Close();
|
||||
OutputIsOnFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
public void PulseRelay(int delayMs)
|
||||
{
|
||||
_relayPort.Pulse(delayMs);
|
||||
}
|
||||
|
||||
public void On()
|
||||
{
|
||||
CloseRelay();
|
||||
}
|
||||
|
||||
public void Off()
|
||||
{
|
||||
OpenRelay();
|
||||
}
|
||||
|
||||
public void PowerToggle()
|
||||
{
|
||||
if (IsOn)
|
||||
Off();
|
||||
else
|
||||
On();
|
||||
}
|
||||
|
||||
public bool IsOn => _relayPort.State;
|
||||
|
||||
public BoolFeedback OutputIsOnFeedback { get; private set; }
|
||||
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
OutputIsOnFeedback = new BoolFeedback(() => IsOn);
|
||||
return base.CustomActivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user