Merge branch 'development' into feature/room-combining

This commit is contained in:
Neil Dorin
2021-07-19 15:45:56 -06:00
5 changed files with 230 additions and 37 deletions

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.GeneralIO;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core.CrestronIO
{
public class C2NIoController:CrestronGenericBaseDevice, IComPorts, IIROutputPorts, IRelayPorts
{
private C2nIo _device;
public C2NIoController(string key, Func<DeviceConfig, C2nIo> preActivationFunc, DeviceConfig config):base(key, config.Name)
{
AddPreActivationAction(() =>
{
_device = preActivationFunc(config);
RegisterCrestronGenericBase(_device);
});
}
#region Implementation of IComPorts
public CrestronCollection<ComPort> ComPorts
{
get { return _device.ComPorts; }
}
public int NumberOfComPorts
{
get { return _device.NumberOfComPorts; }
}
#endregion
#region Implementation of IIROutputPorts
public CrestronCollection<IROutputPort> IROutputPorts
{
get { return _device.IROutputPorts; }
}
public int NumberOfIROutputPorts
{
get { return _device.NumberOfIROutputPorts; }
}
#endregion
#region Implementation of IRelayPorts
public CrestronCollection<Relay> RelayPorts
{
get { return _device.RelayPorts; }
}
public int NumberOfRelayPorts
{
get { return _device.NumberOfRelayPorts; }
}
#endregion
}
public class C2NIoControllerFactory : EssentialsDeviceFactory<C2nRthsController>
{
public C2NIoControllerFactory()
{
TypeNames = new List<string>() { "c2nio" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new C2N-IO Device");
return new C2NIoController(dc.Key, GetC2NIoDevice, dc);
}
static C2nIo GetC2NIoDevice(DeviceConfig dc)
{
var control = CommFactory.GetControlPropertiesConfig(dc);
var cresnetId = control.CresnetIdInt;
var branchId = control.ControlPortNumber;
var parentKey = string.IsNullOrEmpty(control.ControlPortDevKey) ? "processor" : control.ControlPortDevKey;
if (parentKey.Equals("processor", StringComparison.CurrentCultureIgnoreCase))
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nIo", parentKey);
return new C2nIo(cresnetId, Global.ControlSystem);
}
var cresnetBridge = DeviceManager.GetDeviceForKey(parentKey) as IHasCresnetBranches;
if (cresnetBridge != null)
{
Debug.Console(0, "Device {0} is a valid cresnet master - creating new C2nIo", parentKey);
return new C2nIo(cresnetId, cresnetBridge.CresnetBranches[branchId]);
}
Debug.Console(0, "Device {0} is not a valid cresnet master", parentKey);
return null;
}
}
}

View File

@@ -23,7 +23,7 @@ namespace PepperDash.Essentials.Core
protected bool ComputedValue; protected bool ComputedValue;
public BoolFeedbackLogic() protected BoolFeedbackLogic()
{ {
Output = new BoolFeedback(() => ComputedValue); Output = new BoolFeedback(() => ComputedValue);
} }
@@ -40,21 +40,18 @@ namespace PepperDash.Essentials.Core
public void AddOutputsIn(List<BoolFeedback> outputs) public void AddOutputsIn(List<BoolFeedback> outputs)
{ {
foreach (var o in outputs) foreach (var o in outputs.Where(o => !OutputsIn.Contains(o)))
{ {
// skip existing OutputsIn.Add(o);
if (OutputsIn.Contains(o)) continue; o.OutputChange += AnyInput_OutputChange;
}
OutputsIn.Add(o); Evaluate();
o.OutputChange += AnyInput_OutputChange;
}
Evaluate();
} }
public void RemoveOutputIn(BoolFeedback output) public void RemoveOutputIn(BoolFeedback output)
{ {
// Don't double up outputs // Don't double up outputs
if (OutputsIn.Contains(output)) return; if (!OutputsIn.Contains(output)) return;
OutputsIn.Remove(output); OutputsIn.Remove(output);
output.OutputChange -= AnyInput_OutputChange; output.OutputChange -= AnyInput_OutputChange;
@@ -71,6 +68,12 @@ namespace PepperDash.Essentials.Core
Evaluate(); Evaluate();
} }
public void ClearOutputs()
{
OutputsIn.Clear();
Evaluate();
}
void AnyInput_OutputChange(object sender, EventArgs e) void AnyInput_OutputChange(object sender, EventArgs e)
{ {
Evaluate(); Evaluate();
@@ -85,11 +88,12 @@ namespace PepperDash.Essentials.Core
{ {
var prevValue = ComputedValue; var prevValue = ComputedValue;
var newValue = OutputsIn.All(o => o.BoolValue); var newValue = OutputsIn.All(o => o.BoolValue);
if (newValue != prevValue) if (newValue == prevValue)
{ {
ComputedValue = newValue; return;
Output.FireUpdate(); }
} ComputedValue = newValue;
Output.FireUpdate();
} }
} }
@@ -99,33 +103,35 @@ namespace PepperDash.Essentials.Core
{ {
var prevValue = ComputedValue; var prevValue = ComputedValue;
var newValue = OutputsIn.Any(o => o.BoolValue); var newValue = OutputsIn.Any(o => o.BoolValue);
if (newValue != prevValue) if (newValue == prevValue)
{ {
ComputedValue = newValue; return;
Output.FireUpdate(); }
} ComputedValue = newValue;
Output.FireUpdate();
} }
} }
public class BoolFeedbackLinq : BoolFeedbackLogic public class BoolFeedbackLinq : BoolFeedbackLogic
{ {
Func<IEnumerable<BoolFeedback>, bool> Predicate; readonly Func<IEnumerable<BoolFeedback>, bool> _predicate;
public BoolFeedbackLinq(Func<IEnumerable<BoolFeedback>, bool> predicate) public BoolFeedbackLinq(Func<IEnumerable<BoolFeedback>, bool> predicate)
: base() : base()
{ {
Predicate = predicate; _predicate = predicate;
} }
protected override void Evaluate() protected override void Evaluate()
{ {
var prevValue = ComputedValue; var prevValue = ComputedValue;
var newValue = Predicate(OutputsIn); var newValue = _predicate(OutputsIn);
if (newValue != prevValue) if (newValue == prevValue)
{ {
ComputedValue = newValue; return;
Output.FireUpdate(); }
} ComputedValue = newValue;
Output.FireUpdate();
} }
} }
} }

View File

@@ -2,17 +2,18 @@
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.GeneralIO;
using PepperDash.Core; using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core namespace PepperDash.Essentials.Core
{ {
/// <summary> /// <summary>
/// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects /// Aggregates the RoomIsOccupied feedbacks of one or more IOccupancyStatusProvider objects
/// </summary> /// </summary>
public class IOccupancyStatusProviderAggregator : Device, IOccupancyStatusProvider public class IOccupancyStatusProviderAggregator : EssentialsDevice, IOccupancyStatusProvider
{ {
/// <summary> /// <summary>
/// Aggregated feedback of all linked IOccupancyStatusProvider devices /// Aggregated feedback of all linked IOccupancyStatusProvider devices
@@ -21,16 +22,51 @@ namespace PepperDash.Essentials.Core
{ {
get get
{ {
return AggregatedOccupancyStatus.Output; return _aggregatedOccupancyStatus.Output;
} }
} }
private BoolFeedbackOr AggregatedOccupancyStatus; private readonly BoolFeedbackOr _aggregatedOccupancyStatus;
public IOccupancyStatusProviderAggregator(string key, string name) public IOccupancyStatusProviderAggregator(string key, string name)
: base(key, name) : base(key, name)
{ {
AggregatedOccupancyStatus = new BoolFeedbackOr(); _aggregatedOccupancyStatus = new BoolFeedbackOr();
}
public IOccupancyStatusProviderAggregator(string key, string name, OccupancyAggregatorConfig config)
: this(key, name)
{
AddPostActivationAction(() =>
{
if (config.DeviceKeys.Count == 0)
{
return;
}
foreach (var deviceKey in config.DeviceKeys)
{
var device = DeviceManager.GetDeviceForKey(deviceKey);
if (device == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice,
"Unable to retrieve Occupancy provider with key {0}", deviceKey);
continue;
}
var provider = device as IOccupancyStatusProvider;
if (provider == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice,
"Device with key {0} does NOT implement IOccupancyStatusProvider. Please check configuration.");
continue;
}
AddOccupancyStatusProvider(provider);
}
});
} }
/// <summary> /// <summary>
@@ -39,7 +75,35 @@ namespace PepperDash.Essentials.Core
/// <param name="statusProvider"></param> /// <param name="statusProvider"></param>
public void AddOccupancyStatusProvider(IOccupancyStatusProvider statusProvider) public void AddOccupancyStatusProvider(IOccupancyStatusProvider statusProvider)
{ {
AggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback); _aggregatedOccupancyStatus.AddOutputIn(statusProvider.RoomIsOccupiedFeedback);
}
public void RemoveOccupancyStatusProvider(IOccupancyStatusProvider statusProvider)
{
_aggregatedOccupancyStatus.RemoveOutputIn(statusProvider.RoomIsOccupiedFeedback);
}
public void ClearOccupancyStatusProviders()
{
_aggregatedOccupancyStatus.ClearOutputs();
} }
}
public class OccupancyAggregatorFactory : EssentialsDeviceFactory<IOccupancyStatusProviderAggregator>
{
public OccupancyAggregatorFactory()
{
TypeNames = new List<string> { "occupancyAggregator", "occAggregate" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new GlsOccupancySensorBaseController Device");
var config = dc.Properties.ToObject<OccupancyAggregatorConfig>();
return new IOccupancyStatusProviderAggregator(dc.Key, dc.Name, config);
}
} }
} }

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
public class OccupancyAggregatorConfig
{
[JsonProperty("deviceKeys")] public List<string> DeviceKeys { get; set; }
public OccupancyAggregatorConfig()
{
DeviceKeys = new List<string>();
}
}
}

View File

@@ -162,6 +162,7 @@
<Compile Include="Config\Essentials\ConfigWriter.cs" /> <Compile Include="Config\Essentials\ConfigWriter.cs" />
<Compile Include="Config\Essentials\EssentialsConfig.cs" /> <Compile Include="Config\Essentials\EssentialsConfig.cs" />
<Compile Include="Config\SourceDevicePropertiesConfigBase.cs" /> <Compile Include="Config\SourceDevicePropertiesConfigBase.cs" />
<Compile Include="Crestron IO\C2nIo\C2nIoController.cs" />
<Compile Include="Crestron IO\C2nRts\C2nRthsController.cs" /> <Compile Include="Crestron IO\C2nRts\C2nRthsController.cs" />
<Compile Include="Crestron IO\Cards\C3CardControllerBase.cs" /> <Compile Include="Crestron IO\Cards\C3CardControllerBase.cs" />
<Compile Include="Crestron IO\Cards\C3Com3Controller.cs" /> <Compile Include="Crestron IO\Cards\C3Com3Controller.cs" />
@@ -235,6 +236,7 @@
<Compile Include="Occupancy\GlsOirOccupancySensorController.cs" /> <Compile Include="Occupancy\GlsOirOccupancySensorController.cs" />
<Compile Include="PartitionSensor\EssentialsPartitionController.cs" /> <Compile Include="PartitionSensor\EssentialsPartitionController.cs" />
<Compile Include="PartitionSensor\IPartitionStateProvider.cs" /> <Compile Include="PartitionSensor\IPartitionStateProvider.cs" />
<Compile Include="Occupancy\OccupancyAggregatorConfig.cs" />
<Compile Include="Queues\ComsMessage.cs" /> <Compile Include="Queues\ComsMessage.cs" />
<Compile Include="Queues\ProcessStringMessage.cs" /> <Compile Include="Queues\ProcessStringMessage.cs" />
<Compile Include="Queues\GenericQueue.cs" /> <Compile Include="Queues\GenericQueue.cs" />