Compare commits

...

8 Commits

11 changed files with 662 additions and 7 deletions

View File

@@ -62,6 +62,11 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc;
}
public void SetValueFunc(Func<bool> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate()
{
bool newValue = InTestMode ? TestValue : ValueFunc.Invoke();

View File

@@ -51,6 +51,12 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc;
}
public void SetValueFunc(Func<int> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate()
{
var newValue = InTestMode ? TestValue : ValueFunc.Invoke();

View File

@@ -52,7 +52,10 @@ namespace PepperDash.Essentials.Core
ValueFunc = valueFunc;
}
public void SetValueFunc(Func<string> newFunc)
{
ValueFunc = newFunc;
}
public override void FireUpdate()
{

View File

@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Represents an abstract controller device for a partition dividing rooms that are combinable
///
/// In Auto mode, it can use a partition sensor to automatically determine whether the partition is present.
///
/// In Manual mode it accepts user input to tell it whether the partition is present.
/// </summary>
public class EssentialsPartitionController : IPartitionController
{
private IPartitionStateProvider _partitionSensor;
private bool isInAutoMode;
private bool partitionPresent;
public EssentialsPartitionController(string key, string name, IPartitionStateProvider sensor, bool defaultToManualMode, List<string> adjacentRoomKeys)
{
Key = key;
Name = name;
AdjacentRoomKeys = adjacentRoomKeys;
if (sensor != null)
{
_partitionSensor = sensor;
if (!defaultToManualMode)
{
SetAutoMode();
}
else
{
SetManualMode();
}
}
else
{
SetManualMode();
}
PartitionPresentFeedback.FireUpdate();
}
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
if (isInAutoMode)
{
PartitionPresentFeedback.FireUpdate();
}
}
#region IPartitionController Members
public List<string> AdjacentRoomKeys { get; private set; }
public void SetAutoMode()
{
isInAutoMode = true;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
}
else
{
PartitionPresentFeedback = new BoolFeedback(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
}
if (_partitionSensor != null)
{
_partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
}
}
public void SetManualMode()
{
isInAutoMode = false;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => partitionPresent);
}
else
{
PartitionPresentFeedback = new BoolFeedback(() => partitionPresent);
}
if (_partitionSensor != null)
{
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
}
}
public void SetPartitionStatePresent()
{
if (!isInAutoMode)
{
partitionPresent = true;
PartitionPresentFeedback.FireUpdate();
}
}
public void SetPartitionStateNotPresent()
{
if (!isInAutoMode)
{
partitionPresent = false;
PartitionPresentFeedback.FireUpdate();
}
}
public void ToggglePartitionState()
{
if (!isInAutoMode)
{
partitionPresent = !partitionPresent;
PartitionPresentFeedback.FireUpdate();
}
}
#endregion
#region IPartitionStateProvider Members
public BoolFeedback PartitionPresentFeedback { get; private set; }
#endregion
#region IKeyName Members
public string Name { get; private set; }
#endregion
#region IKeyed Members
public string Key { get; private set; }
#endregion
}
}

View File

@@ -13,13 +13,13 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core
{
[Description("Wrapper class for GLS Cresnet Partition Sensor")]
public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice
public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice, IPartitionStateProvider
{
private GlsPartCn _partitionSensor;
public StringFeedback NameFeedback { get; private set; }
public BoolFeedback EnableFeedback { get; private set; }
public BoolFeedback PartitionSensedFeedback { get; private set; }
public BoolFeedback PartitionPresentFeedback { get; private set; }
public BoolFeedback PartitionNotSensedFeedback { get; private set; }
public IntFeedback SensitivityFeedback { get; private set; }
@@ -40,7 +40,7 @@ namespace PepperDash.Essentials.Core
NameFeedback = new StringFeedback(() => Name);
EnableFeedback = new BoolFeedback(() => _partitionSensor.EnableFeedback.BoolValue);
PartitionSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionPresentFeedback = new BoolFeedback(() => _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionNotSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionNotSensedFeedback.BoolValue);
SensitivityFeedback = new IntFeedback(() => _partitionSensor.SensitivityFeedback.UShortValue);
@@ -61,7 +61,7 @@ namespace PepperDash.Essentials.Core
}
case (GlsPartCn.PartitionSensedFeedbackEventId):
{
PartitionSensedFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate();
break;
}
case (GlsPartCn.PartitionNotSensedFeedbackEventId):
@@ -186,7 +186,7 @@ namespace PepperDash.Essentials.Core
// link output to simpl
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]);
PartitionSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionPresentFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]);
SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]);
@@ -216,7 +216,7 @@ namespace PepperDash.Essentials.Core
IsOnline.FireUpdate();
NameFeedback.FireUpdate();
EnableFeedback.FireUpdate();
PartitionSensedFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate();
SensitivityFeedback.FireUpdate();
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the functionality of a device that senses and provides partition state
/// </summary>
public interface IPartitionStateProvider : IKeyName
{
BoolFeedback PartitionPresentFeedback { get; }
}
/// <summary>
/// Describes the functionality of a device that can provide partition state either manually via user input or optionally via a sensor state
/// </summary>
public interface IPartitionController : IPartitionStateProvider
{
List<string> AdjacentRoomKeys { get; }
void SetPartitionStatePresent();
void SetPartitionStateNotPresent();
void ToggglePartitionState();
void SetManualMode();
void SetAutoMode();
}
}

View File

@@ -233,6 +233,8 @@
<Compile Include="Interfaces\ILogStringsWithLevel.cs" />
<Compile Include="Occupancy\GlsOccupancySensorPropertiesConfig.cs" />
<Compile Include="Occupancy\GlsOirOccupancySensorController.cs" />
<Compile Include="PartitionSensor\EssentialsPartitionController.cs" />
<Compile Include="PartitionSensor\IPartitionStateProvider.cs" />
<Compile Include="Queues\ComsMessage.cs" />
<Compile Include="Queues\ProcessStringMessage.cs" />
<Compile Include="Queues\GenericQueue.cs" />
@@ -287,6 +289,10 @@
<Compile Include="Remotes\CrestronRemotePropertiesConfig.cs" />
<Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" />
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\EssentialsRoomCombinerPropertiesConfig.cs" />
<Compile Include="Room\Combining\IEssentialsRoomCombiner.cs" />
<Compile Include="Room\Combining\RoomCombinationScenario.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" />
<Compile Include="Room\IEssentialsRoom.cs" />

View File

@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
namespace PepperDash.Essentials.Core
{
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner
{
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
private IRoomCombinationScenario _currentScenario;
private List<IEssentialsRoom> _rooms;
private bool isInAutoMode;
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
: base(key)
{
_propertiesConfig = props;
IsInAutoModeFeedback = new BoolFeedback(() => isInAutoMode);
// default to auto mode
isInAutoMode = true;
if (_propertiesConfig.defaultToManualMode)
{
isInAutoMode = false;
}
IsInAutoModeFeedback.FireUpdate();
CreateScenarios();
SetupPartitionStateProviders();
SetRooms();
}
void CreateScenarios()
{
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
{
var scenario = new RoomCombinationScenario(scenarioConfig);
RoomCombinationScenarios.Add(scenario);
}
}
void SetRooms()
{
_rooms = new List<IEssentialsRoom>();
foreach (var roomKey in _propertiesConfig.RoomKeys)
{
var room = DeviceManager.GetDeviceForKey(roomKey) as IEssentialsRoom;
if (room != null)
{
_rooms.Add(room);
}
}
}
void SetupPartitionStateProviders()
{
foreach (var pConfig in _propertiesConfig.Partitions)
{
var sensor = DeviceManager.GetDeviceForKey(pConfig.DeviceKey) as IPartitionStateProvider;
var partition = new EssentialsPartitionController(pConfig.Key, pConfig.Name, sensor, _propertiesConfig.defaultToManualMode, pConfig.AdjacentRoomKeys);
partition.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
Partitions.Add(partition);
}
}
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
DetermineRoomCombinationScenario();
}
/// <summary>
/// Determines the current room combination scenario based on the state of the partition sensors
/// </summary>
void DetermineRoomCombinationScenario()
{
//RoomCombinationScenarios.FirstOrDefault((s) =>
//{
// foreach (var partitionState in s.PartitionStates)
// {
// var partition = Partitions.FirstOrDefault(
// }
//});
}
#region IEssentialsRoomCombiner Members
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
public IRoomCombinationScenario CurrentScenario
{
get
{
return _currentScenario;
}
set
{
if (value != _currentScenario)
{
_currentScenario = value;
var handler = RoomCombinationScenarioChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
}
public BoolFeedback IsInAutoModeFeedback { get; private set; }
public void SetAutoMode()
{
isInAutoMode = true;
IsInAutoModeFeedback.FireUpdate();
}
public void SetManualMode()
{
isInAutoMode = false;
IsInAutoModeFeedback.FireUpdate();
}
public void ToggleMode()
{
isInAutoMode = !isInAutoMode;
IsInAutoModeFeedback.FireUpdate();
}
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; private set; }
public List<IPartitionStateProvider> Partitions { get; private set; }
public void TogglePartitionState(string partitionKey)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)) as IPartitionController;
if (partition != null)
{
partition.ToggglePartitionState();
}
}
public void SetRoomCombinationScenario(string scenarioKey)
{
}
#endregion
}
}

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Config properties for an EssentialsRoomCombiner device
/// </summary>
public class EssentialsRoomCombinerPropertiesConfig
{
/// <summary>
/// The list of partitions that device the rooms
/// </summary>
[JsonProperty("partitions")]
public List<PartitionConfig> Partitions {get; set;}
/// <summary>
/// The list of combinations scenarios for the rooms
/// </summary>
[JsonProperty("scenarios")]
public List<RoomCombinationScenarioConfig> Scenarios { get; set; }
/// <summary>
/// The list of rooms keys that can be combined
/// </summary>
[JsonProperty("roomMap")]
public List<string> RoomKeys {get; set;}
/// <summary>
/// Set to true to default to manual mode
/// </summary>
[JsonProperty("defaultToManualMode")]
public bool defaultToManualMode { get; set; }
/// <summary>
/// The key of the scenario to default to at system startup if in manual mode
/// </summary>
[JsonProperty("defaultScenarioKey")]
public string defaultScenarioKey { get; set; }
}
/// <summary>
/// Config properties for a partition that separates rooms
/// </summary>
public class PartitionConfig : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Key of the device that implements IPartitionStateProvider to provide the state of the partition
/// </summary>
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
/// <summary>
/// Keys of the rooms that this partion would be located between
/// </summary>
[JsonProperty("adjacentRoomKeys")]
public List<string> AdjacentRoomKeys { get; set; }
}
/// <summary>
/// Config propeties for a room combination scenario
/// </summary>
public class RoomCombinationScenarioConfig : IKeyName
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; set; }
[JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; }
[JsonProperty("activationActions")]
public List<DeviceActionWrapper> ActivationActions { get; set; }
[JsonProperty("deactivationActions")]
public List<DeviceActionWrapper> DeactivationActions { get; set; }
}
/// <summary>
/// Config properties to represent the state of a partition sensor in a RoomCombinationScenario
/// </summary>
public class PartitionState
{
[JsonProperty("partitionKey")]
public string PartitionKey { get; set; }
[JsonProperty("partitionSensedState")]
public bool PartitionPresent { get; set; }
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Describes the functionality for an EssentailsRoomCombiner device
/// </summary>
public interface IEssentialsRoomCombiner : IKeyed
{
/// <summary>
/// Indicates that the room combination scenario has changed
/// </summary>
event EventHandler<EventArgs> RoomCombinationScenarioChanged;
/// <summary>
/// The current room combination scenario
/// </summary>
IRoomCombinationScenario CurrentScenario { get; }
/// <summary>
/// When true, indicates the current mode is auto mode
/// </summary>
BoolFeedback IsInAutoModeFeedback {get;}
/// <summary>
/// Sets auto mode
/// </summary>
void SetAutoMode();
/// <summary>
/// Sets manual mode
/// </summary>
void SetManualMode();
/// <summary>
/// Toggles the current mode between auto and manual
/// </summary>
void ToggleMode();
/// <summary>
/// The available room combinatino scenarios
/// </summary>
List<IRoomCombinationScenario> RoomCombinationScenarios { get; }
/// <summary>
/// The partition
/// </summary>
List<IPartitionStateProvider> Partitions { get; }
/// <summary>
/// Toggles the state of a manual partition sensor
/// </summary>
/// <param name="partitionKey"></param>
void TogglePartitionState(string partitionKey);
/// <summary>
/// Sets the room combination scenario (if in manual mode)
/// </summary>
/// <param name="scenarioKey"></param>
void SetRoomCombinationScenario(string scenarioKey);
}
public interface IRoomCombinationScenario : IKeyName
{
/// <summary>
/// When true, indicates that this room combination scenario is active
/// </summary>
BoolFeedback IsActiveFeedback { get; }
/// <summary>
/// Activates this room combination scenario
/// </summary>
void Activate();
/// <summary>
/// The state of the partitions that would activate this scenario
/// </summary>
List<PartitionState> PartitionStates { get; }
/// <summary>
/// The mapping of UIs by key to rooms by key
/// </summary>
Dictionary<string, string> UiMap { get; set; }
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
/// <summary>
/// Represents a room combination scenario
/// </summary>
public class RoomCombinationScenario: IRoomCombinationScenario
{
private RoomCombinationScenarioConfig _config;
public string Key { get; set; }
public string Name { get; set; }
public List<PartitionState> PartitionStates { get; private set; }
public Dictionary<string, string> UiMap { get; set; }
private bool _isActive;
public BoolFeedback IsActiveFeedback { get; private set; }
List<DeviceActionWrapper> activationActions;
List<DeviceActionWrapper> deactivationActions;
public RoomCombinationScenario(RoomCombinationScenarioConfig config)
{
Key = config.Key;
Name = config.Name;
PartitionStates = config.PartitionStates;
UiMap = config.UiMap;
activationActions = config.ActivationActions;
deactivationActions = config.DeactivationActions;
_config = config;
IsActiveFeedback = new BoolFeedback(() => _isActive);
}
public void Activate()
{
if (activationActions != null)
{
foreach (var action in activationActions)
{
DeviceJsonApi.DoDeviceAction(action);
}
}
_isActive = true;
IsActiveFeedback.FireUpdate();
}
public void Deactivate()
{
if (deactivationActions != null)
{
foreach (var action in deactivationActions)
{
DeviceJsonApi.DoDeviceAction(action);
}
}
_isActive = false;
IsActiveFeedback.FireUpdate();
}
}
}