Compare commits

..

48 Commits

Author SHA1 Message Date
Neil Dorin
2e61d8d709 fix: Changes LevelControlLists to AudioControlPointLists and modified IHasDspPresets 2024-05-21 16:49:13 -06:00
Neil Dorin
d8d2c5b340 build(force-patch): Updates PD.Core version to support LevelControlList property merge in config 2024-05-16 23:07:13 -06:00
Neil Dorin
7e736ae519 fix: initializes LevelControlLists in config 2024-05-16 22:44:57 -06:00
Neil Dorin
0067e11d3d fix: Adds new property to EssentialsRoomBase and implements consistent default key if no key set 2024-05-16 20:57:38 -06:00
Neil Dorin
7942c91f73 feat: Adds LevelControlListKey to IEssentialsRoom 2024-05-16 20:49:11 -06:00
Neil Dorin
e1638762a1 feat: Adds helper method for getting LevelControlList by key 2024-05-16 20:30:22 -06:00
Neil Dorin
3566400379 fix: Adds LevelControlListKey to EssentialsRoomPropertiesConfig 2024-05-16 20:24:45 -06:00
Neil Dorin
dde85f39a2 fix: combine enum values 2024-05-16 20:20:11 -06:00
Neil Dorin
735433f660 fix: adds missing flags decorator to enum 2024-05-16 17:26:35 -06:00
Neil Dorin
734149960b fix: Adds missing StringEnumConverter 2024-05-16 17:23:38 -06:00
Neil Dorin
cb16f2a505 feat: Adds LevelControlLists to BasicConfig and LevelControlListItem class 2024-05-16 17:17:59 -06:00
Neil Dorin
cb9eb5dafa Merge remote-tracking branch 'origin/feature-2.0.0/video-codec-interface-uiextensions' into feature-2.0.0/room-combiner-updates 2024-05-14 16:44:30 -06:00
Neil Dorin
eb955aa014 build: updates version of PD.Core --force-patch 2024-05-14 15:32:23 -06:00
Joshua_Gutenplan
2d9ffca78e Merge branch 'feature-2.0.0/room-combiner-updates' into feature-2.0.0/video-codec-interface-uiextensions 2024-05-10 21:36:53 -07:00
Neil Dorin
98f1a09c25 feat: Adds IHasCiscoNavigatorTouchpanel interface 2024-05-10 14:49:37 -06:00
Neil Dorin
a11ad421f0 fix: better implmentation of input select 2024-05-10 13:16:59 -06:00
Neil Dorin
8878ff7ddd chore: renames property to Keys 2024-05-09 16:09:16 -06:00
Neil Dorin
7e4b5f984f feat: Adds IHasAccessoryDevices 2024-05-09 16:07:52 -06:00
Neil Dorin
64ab315142 fix: various updates for room combining from testing 2024-05-09 15:16:35 -06:00
Neil Dorin
c47a93f4d0 Merge remote-tracking branch 'origin/feature-2.0.0/add-screenLift-controls' into feature-2.0.0/room-combiner-updates 2024-05-09 15:15:50 -06:00
Joshua_Gutenplan
5a55a701d6 fix: remove codec interfaces that are only needed in cisco epi now 2024-05-09 12:10:42 -07:00
Andrew Knous
01862ab9aa feat: moves mockdisplay factory from PepperDash.Essentials.Core to PepperDash.Essential.Devices.Common 2024-05-09 13:48:59 -04:00
Andrew Knous
8ec6fa785e feat: adds IProjectorScreenLiftControl and ScreenLiftController 2024-05-09 13:47:46 -04:00
Joshua_Gutenplan
e37c675da1 Merge remote-tracking branch 'origin/feature-2.0.0/room-combiner-updates' into feature-2.0.0/video-codec-interface-uiextensions 2024-05-06 12:55:16 -07:00
Neil Dorin
3ee8cb7ea3 feat: updates IHasInput to remove requirement for SetInputs method (unnecessary) 2024-05-03 13:34:22 -06:00
Neil Dorin
2b6f79b68f feat: updates to Room combiner for use with mobile control 2024-05-02 17:27:34 -06:00
Neil Dorin
65369606a4 feat: updates to room combiner interfaces 2024-05-02 15:00:17 -06:00
Joshua_Gutenplan
e9954b3081 fix: add GetRoomMessenger to IMobileControl 2024-05-02 12:07:00 -07:00
Neil Dorin
bc67a4382b Merge pull request #1185 from PepperDash/feature-2.0.0/tech-password-interface
Feature 2.0.0/tech password interface
2024-05-02 09:55:41 -06:00
Joshua_Gutenplan
e1b50649fd fix: UiWebViewDisplayActionArgs add target 2024-04-30 21:41:53 -07:00
Joshua_Gutenplan
5e69ea1947 Merge remote-tracking branch 'origin/feature-2.0.0/tech-password-interface' into feature-2.0.0/video-codec-interface-uiextensions 2024-04-30 10:24:50 -07:00
Neil Dorin
80b8cc6385 feat: Adds SecondsRemainingFeedback to SecondsCountdownTimer 2024-04-26 13:15:15 -06:00
Neil Dorin
82f78bf068 feat: adds StarShutdown method to IShutdownPromptTimer 2024-04-26 12:08:26 -06:00
Neil Dorin
d8d27949c3 fix: updates to IMobileControlTouchpanelController 2024-04-26 09:31:27 -06:00
Joshua_Gutenplan
fd1b92a6c0 Merge remote-tracking branch 'origin/feature-2.0.0/tech-password-interface' into feature-2.0.0/video-codec-interface-uiextensions 2024-04-25 19:13:46 -07:00
Neil Dorin
fa9b493431 feat: Adds IMobileControlTouchpanelController 2024-04-25 16:31:54 -06:00
Joshua_Gutenplan
06d806687d feat: IMobileControlTouchpanelController 2024-04-25 15:29:44 -07:00
Joshua_Gutenplan
d8e2f8cd51 feat: IVideoCodecUiExtensions 2024-04-25 10:03:38 -07:00
Neil Dorin
e5d5c90aa9 feat: Adds ITechPassword 2024-04-24 16:54:51 -06:00
Neil Dorin
661f7b827a fix: Updates to scheduler to attempt to deal with exceptions modifying existing events. Adds console command to allow deletign event group 2024-04-18 16:12:31 -06:00
Neil Dorin
5fad706cd8 Merge pull request #1179 from PepperDash/feature-2.0.0/soft-codec-routing
Update interfaces for Generic Soft Codec device
2024-04-12 10:31:03 -06:00
Andrew Welker
49c4d2a387 fix: use IRoutingSink instead of IRoutingSinkWithSwitching 2024-04-11 09:15:05 -05:00
Neil Dorin
cf81431f57 feat: updates interfaces on GenericSoftCodec and adds IRoutingSink 2024-04-10 10:59:32 -06:00
Neil Dorin
8a7bcd5297 Merge pull request #1178 from PepperDash/feature-2.0.0/interface-updates
Multiple Updates
2024-04-09 10:36:21 -06:00
Andrew Welker
1fdaa84a62 fix: remove generics from matrix routing interfaces 2024-04-09 08:33:58 -05:00
Neil Dorin
8a374072ae feat: Adds EndpointKeys to IHasMatrixRouting 2024-04-04 16:16:54 -06:00
Neil Dorin
5d608887a1 feat: Adds IEssentialsRoomPropertiesConfig 2024-04-03 14:38:54 -06:00
Andrew Welker
d2d041dbf7 fix: make IRoutingOutputSlot & RoutingOutputSlotBase generic 2024-04-03 10:46:43 -05:00
37 changed files with 937 additions and 246 deletions

1
.gitignore vendored
View File

@@ -391,3 +391,4 @@ FodyWeavers.xsd
essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/PepperDash_Essentials_Interfaces.csproj
.DS_Store
/._PepperDash.Essentials.sln
.vscode/settings.json

View File

@@ -1,15 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Net.Http;
using Crestron.SimplSharp.Net.Http;
using PepperDash.Core;
using PepperDash.Core.DebugThings;
using System;
namespace PepperDash.Essentials.Core
{
[Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")]
[Obsolete("Please use the builtin HttpClient class instead: https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines")]
public class GenericHttpClient : Device, IBasicCommunication
{
public HttpClient Client;

View File

@@ -0,0 +1,19 @@
using Crestron.SimplSharpPro;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Core.Config
{
public class AudioControlPointListItem
{
[JsonProperty("levelControls")]
public Dictionary<string, LevelControlListItem> LevelControls { get; set; }
[JsonProperty("presets")]
public Dictionary<string, PresetListItem> Presets { get; set; }
}
}

View File

@@ -23,7 +23,10 @@ namespace PepperDash.Essentials.Core.Config
public Dictionary<string, Dictionary<string, SourceListItem>> SourceLists { get; set; }
[JsonProperty("destinationLists")]
public Dictionary<string, Dictionary<string,DestinationListItem>> DestinationLists { get; set; }
public Dictionary<string, Dictionary<string, DestinationListItem>> DestinationLists { get; set; }
[JsonProperty("audioControlPointLists")]
public Dictionary<string, Dictionary<string, AudioControlPointListItem>> AudioControlPointLists { get; set; }
[JsonProperty("tieLines")]
public List<TieLineConfig> TieLines { get; set; }
@@ -37,6 +40,7 @@ namespace PepperDash.Essentials.Core.Config
Devices = new List<DeviceConfig>();
SourceLists = new Dictionary<string, Dictionary<string, SourceListItem>>();
DestinationLists = new Dictionary<string, Dictionary<string, DestinationListItem>>();
AudioControlPointLists = new Dictionary<string, Dictionary<string, AudioControlPointListItem>>();
TieLines = new List<TieLineConfig>();
JoinMaps = new Dictionary<string, JObject>();
}
@@ -55,8 +59,8 @@ namespace PepperDash.Essentials.Core.Config
/// <summary>
/// Retrieves a DestinationListItem based on the key
/// </summary>
/// <param name="key">key of the item to retrieve</param>
/// <returns>DestinationListItem if the key exists, null otherwise</returns>
/// <param name="key">key of the list to retrieve</param>
/// <returns>DestinationList if the key exists, null otherwise</returns>
public Dictionary<string, DestinationListItem> GetDestinationListForKey(string key)
{
if (string.IsNullOrEmpty(key) || !DestinationLists.ContainsKey(key))
@@ -65,7 +69,20 @@ namespace PepperDash.Essentials.Core.Config
}
return DestinationLists[key];
}
}
/// <summary>
/// Retrieves a AudioControlPointList based on the key
/// </summary>
/// <param name="key">key of the list to retrieve</param>
/// <returns>AudioControlPointList if the key exists, null otherwise</returns>
public Dictionary<string, AudioControlPointListItem> GetAudioControlPointListForKey(string key)
{
if (string.IsNullOrEmpty(key) || !AudioControlPointLists.ContainsKey(key))
return null;
return AudioControlPointLists[key];
}
/// <summary>
/// Checks Devices for an item with a Key that matches and returns it if found. Otherwise, retunes null

View File

@@ -15,10 +15,8 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// <example>
/// See MockDisplay for example implemntation
/// </example>
public interface IHasInputs<TKey, TSelector>: IKeyName
public interface IHasInputs<T, TSelector>: IKeyName
{
ISelectableItems<TKey> Inputs { get; }
void SetInput(TSelector selector);
ISelectableItems<T> Inputs { get; }
}
}

View File

@@ -44,7 +44,10 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
void AddDeviceMessenger(IMobileControlMessenger messenger);
bool CheckForDeviceMessenger(string key);
}
IMobileControlRoomMessenger GetRoomMessenger(string key);
}
/// <summary>
/// Describes a mobile control messenger
@@ -106,4 +109,11 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
Action<string,string, JToken> Action { get; }
}
public interface IMobileControlTouchpanelController : IKeyed
{
string DefaultRoomKey { get; }
void SetAppUrl(string url);
bool UseDirectServer { get; }
bool ZoomRoomController { get; }
}
}

View File

@@ -0,0 +1,27 @@
using Crestron.SimplSharpPro.DeviceSupport;
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
/// <summary>
/// Defines a class that has warm up and cool down
/// </summary>
public interface IProjectorScreenLiftControl
{
void Raise();
void Lower();
BoolFeedback IsInUpPosition { get; }
bool InUpPosition { get; }
event EventHandler<EventArgs> PositionChanged;
string DisplayDeviceKey { get; }
eScreenLiftControlType Type { get; } // screen/lift
}
public enum eScreenLiftControlType
{
lift,
screen
}
}

View File

@@ -17,6 +17,6 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
Dictionary<TKey, ISelectableItem> Items { get; set; }
[JsonProperty("currentItem")]
string CurrentItem { get; set; }
TKey CurrentItem { get; set; }
}
}

View File

@@ -0,0 +1,36 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Core
{
public abstract class AudioControlListItemBase
{
[JsonProperty("parentDeviceKey")]
public string ParentDeviceKey { get; set; }
[JsonProperty("itemKey")]
public string ItemKey { get; set; }
/// <summary>
/// A name that will override the items's name on the UI
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Indicates if the item should be included in the user accessible list
/// </summary>
[JsonProperty("includeInUserList")]
public bool IncludeInUserList { get; set; }
/// <summary>
/// Used to specify the order of the items in the source list when displayed
/// </summary>
[JsonProperty("order")]
public int Order { get; set; }
}
}

View File

@@ -52,5 +52,11 @@ namespace PepperDash.Essentials.Core
[JsonProperty("sinkType")]
public eRoutingSignalType SinkType { get; set; }
[JsonProperty("isCodecContentDestination")]
public bool isCodecContentDestination { get; set; }
[JsonProperty("isProgramAudioDestination")]
public bool isProgramAudioDestination { get; set; }
}
}

View File

@@ -1,17 +0,0 @@
using System.Collections.Generic;
namespace PepperDash.Essentials.Core
{
public interface IHasDspPresets
{
List<IDspPreset> Presets { get; }
void RecallPreset(IDspPreset preset);
}
public interface IDspPreset
{
string Name { get; }
}
}

View File

@@ -0,0 +1,12 @@
using PepperDash.Core;
using System.Collections.Generic;
namespace PepperDash.Essentials.Core
{
public interface IDspPresets
{
Dictionary<string, IKeyName> Presets { get; }
void RecallPreset(string key);
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Devices;
namespace PepperDash.Essentials.Core
{
public class LevelControlListItem : AudioControlListItemBase
{
[JsonIgnore]
public IBasicVolumeWithFeedback LevelControl
{
get
{
if (_levelControl == null)
_levelControl = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IBasicVolumeWithFeedback;
return _levelControl;
}
}
IBasicVolumeWithFeedback _levelControl;
/// <summary>
/// Gets the name from the device if it implements IKeyName or else returns the Name property
/// </summary>
[JsonProperty("preferredName")]
public string PreferredName
{
get
{
if (!string.IsNullOrEmpty(Name)) return Name;
else
{
if (LevelControl is IKeyName namedLevelControl)
{
if (namedLevelControl == null)
return "---";
return namedLevelControl.Name;
}
else return "---";
}
}
}
/// <summary>
/// Indicates if the item is a level, mute , or both
/// </summary>
[JsonProperty("type")]
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public eLevelControlType Type { get; set; }
}
[Flags]
public enum eLevelControlType
{
Level = 0,
Mute = 1,
LevelAndMute = Level | Mute,
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class PresetListItem : AudioControlListItemBase
{
[JsonIgnore]
public IKeyName Preset
{
get
{
if (_preset == null)
{
var parent = DeviceManager.GetDeviceForKey(ParentDeviceKey) as IDspPresets;
if (parent == null || !parent.Presets.ContainsKey(ItemKey))
return null;
_preset = parent.Presets[ItemKey];
}
return _preset;
}
}
private IKeyName _preset;
/// <summary>
/// Gets the name from the device if it implements IKeyName or else returns the Name property
/// </summary>
[JsonProperty("preferredName")]
public string PreferredName
{
get
{
if (!string.IsNullOrEmpty(Name)) return Name;
else return Preset.Name;
}
}
}
}

View File

@@ -220,19 +220,5 @@ namespace PepperDash.Essentials.Core
}
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public class MockDisplayFactory : EssentialsDeviceFactory<MockDisplay>
{
public MockDisplayFactory()
{
TypeNames = new List<string>() { "mockdisplay" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device");
return new MockDisplay(dc.Key, dc.Name);
}
}
}

View File

@@ -22,15 +22,31 @@ namespace PepperDash.Essentials.Core
static Scheduler()
{
CrestronConsole.AddNewConsoleCommand(DeleteEventGroup, "DeleteEventGroup", "Deletes the event group by key", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ClearEventsFromGroup, "ClearAllEvents", "Clears all scheduled events for this group", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListAllEventGroups, "ListAllEventGroups", "Lists all the event groups by key", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ListAllEventsForGroup, "ListEventsForGroup",
"Lists all events for the given group", ConsoleAccessLevelEnum.AccessOperator);
}
static void DeleteEventGroup(string groupName)
{
if (EventGroups.ContainsKey(groupName))
{
var group = EventGroups[groupName];
EventGroups.Remove(groupName);
group.Dispose();
group = null;
}
}
/// <summary>
/// Clears (deletes) all events from a group
/// </summary>
@@ -40,7 +56,7 @@ namespace PepperDash.Essentials.Core
if (!EventGroups.ContainsKey(groupName))
{
Debug.LogMessage(LogEventLevel.Information,
"[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.",
"[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.", null,
groupName);
return;
}
@@ -51,47 +67,47 @@ namespace PepperDash.Essentials.Core
{
group.ClearAllEvents();
Debug.LogMessage(LogEventLevel.Information, "[Scheduler]: All events deleted from group '{0}'", groupName);
Debug.LogMessage(LogEventLevel.Information, "[Scheduler]: All events deleted from group '{0}'", null, groupName);
}
else
Debug.LogMessage(LogEventLevel.Information,
"[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.",
"[Scheduler]: Unable to delete events from group '{0}'. Group not found in EventGroups dictionary.", null,
groupName);
}
static void ListAllEventGroups(string command)
{
Debug.LogMessage(LogEventLevel.Information, "Event Groups:");
CrestronConsole.ConsoleCommandResponse("Event Groups:");
foreach (var group in EventGroups)
{
Debug.LogMessage(LogEventLevel.Information, "{0}", group.Key);
CrestronConsole.ConsoleCommandResponse($"{group.Key}");
}
}
static void ListAllEventsForGroup(string args)
{
Debug.LogMessage(LogEventLevel.Information, "Getting events for group {0}...", args);
Debug.LogMessage(LogEventLevel.Information, "Getting events for group {0}...", null, args);
ScheduledEventGroup group;
if (!EventGroups.TryGetValue(args, out group))
{
Debug.LogMessage(LogEventLevel.Information, "Unabled to get event group for key {0}", args);
Debug.LogMessage(LogEventLevel.Information, "Unabled to get event group for key {0}", null, args);
return;
}
foreach (var evt in group.ScheduledEvents)
{
Debug.LogMessage(LogEventLevel.Information,
@"
****Event key {0}****
Event date/time: {1}
Persistent: {2}
Acknowlegable: {3}
Recurrence: {4}
Recurrence Days: {5}
********************", evt.Key, evt.Value.DateAndTime, evt.Value.Persistent, evt.Value.Acknowledgeable,
evt.Value.Recurrence.Recurrence, evt.Value.Recurrence.RecurrenceDays);
CrestronConsole.ConsoleCommandResponse(
$@"
****Event key {evt.Key}****
Event state: {evt.Value.EventState}
Event date/time: {evt.Value.DateAndTime}
Persistent: {evt.Value.Persistent}
Acknowlegable: {evt.Value.Acknowledgeable}
Recurrence: {evt.Value.Recurrence.Recurrence}
Recurrence Days: {evt.Value.Recurrence.RecurrenceDays}
********************");
}
}
@@ -138,10 +154,9 @@ Recurrence Days: {5}
var dayOfWeek = eventTime.DayOfWeek;
Debug.LogMessage(LogEventLevel.Debug, "[Scheduler]: eventTime day of week is: {0}", dayOfWeek);
Debug.LogMessage(LogEventLevel.Debug, "[Scheduler]: eventTime day of week is: {0}",null, dayOfWeek);
switch (dayOfWeek)
{
{
case DayOfWeek.Sunday:
{
if ((recurrence & ScheduledEventCommon.eWeekDays.Sunday) == ScheduledEventCommon.eWeekDays.Sunday)
@@ -203,53 +218,64 @@ Recurrence Days: {5}
public static void CreateEventFromConfig(ScheduledEventConfig config, ScheduledEventGroup group, ScheduledEvent.UserEventCallBack handler)
{
if (group == null)
try
{
Debug.LogMessage(LogEventLevel.Information, "Unable to create event. Group is null");
return;
if (group == null)
{
Debug.LogMessage(LogEventLevel.Information, "Unable to create event. Group is null", null, null);
return;
}
var scheduledEvent = new ScheduledEvent(config.Key, group)
{
Acknowledgeable = config.Acknowledgeable,
Persistent = config.Persistent
};
scheduledEvent.UserCallBack += handler;
scheduledEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday);
var eventTime = DateTime.Parse(config.Time);
if (DateTime.Now > eventTime)
{
eventTime = eventTime.AddDays(1);
}
Debug.LogMessage(LogEventLevel.Verbose, "[Scheduler] Current Date day of week: {0} recurrence days: {1}", null, eventTime.DayOfWeek,
config.Days);
var dayOfWeekConverted = ConvertDayOfWeek(eventTime);
Debug.LogMessage(LogEventLevel.Debug, "[Scheduler] eventTime Day: {0}", null, dayOfWeekConverted);
while (!dayOfWeekConverted.IsFlagSet(config.Days))
{
eventTime = eventTime.AddDays(1);
dayOfWeekConverted = ConvertDayOfWeek(eventTime);
}
scheduledEvent.DateAndTime.SetAbsoluteEventTime(eventTime);
scheduledEvent.Recurrence.Weekly(config.Days);
Debug.LogMessage(LogEventLevel.Verbose, $"[Scheduler] Event State: {scheduledEvent.EventState}", null, null);
if (config.Enable && scheduledEvent.EventState != ScheduledEventCommon.eEventState.Enabled)
{
scheduledEvent.Enable();
}
else if (!config.Enable && scheduledEvent.EventState != ScheduledEventCommon.eEventState.Disabled)
{
scheduledEvent.Disable();
}
}
var scheduledEvent = new ScheduledEvent(config.Key, group)
catch (Exception e)
{
Acknowledgeable = config.Acknowledgeable,
Persistent = config.Persistent
};
scheduledEvent.UserCallBack += handler;
scheduledEvent.DateAndTime.SetFirstDayOfWeek(ScheduledEventCommon.eFirstDayOfWeek.Sunday);
var eventTime = DateTime.Parse(config.Time);
if (DateTime.Now > eventTime)
{
eventTime = eventTime.AddDays(1);
}
Debug.LogMessage(LogEventLevel.Verbose, "[Scheduler] Current Date day of week: {0} recurrence days: {1}", eventTime.DayOfWeek,
config.Days);
var dayOfWeekConverted = ConvertDayOfWeek(eventTime);
Debug.LogMessage(LogEventLevel.Debug, "[Scheduler] eventTime Day: {0}", dayOfWeekConverted);
while (!dayOfWeekConverted.IsFlagSet(config.Days))
{
eventTime = eventTime.AddDays(1);
dayOfWeekConverted = ConvertDayOfWeek(eventTime);
}
scheduledEvent.DateAndTime.SetAbsoluteEventTime(eventTime);
scheduledEvent.Recurrence.Weekly(config.Days);
if (config.Enable)
{
scheduledEvent.Enable();
}
else
{
scheduledEvent.Disable();
Debug.LogMessage(LogEventLevel.Error, "Error creating scheduled event: {0}", null, e);
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
@@ -17,9 +18,31 @@ namespace PepperDash.Essentials.Core
{
private IPartitionStateProvider _partitionSensor;
private bool isInAutoMode;
public bool IsInAutoMode { get; private set; }
private bool partitionPresent;
private bool _partitionPresent;
public bool PartitionPresent
{
get
{
return _partitionPresent;
}
set
{
if (_partitionPresent == value)
{
return;
}
_partitionPresent = value;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.FireUpdate();
}
}
}
public EssentialsPartitionController(string key, string name, IPartitionStateProvider sensor, bool defaultToManualMode, List<string> adjacentRoomKeys)
{
@@ -52,7 +75,7 @@ namespace PepperDash.Essentials.Core
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
if (isInAutoMode)
if (IsInAutoMode)
{
PartitionPresentFeedback.FireUpdate();
}
@@ -64,7 +87,7 @@ namespace PepperDash.Essentials.Core
public void SetAutoMode()
{
isInAutoMode = true;
IsInAutoMode = true;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => _partitionSensor.PartitionPresentFeedback.BoolValue);
@@ -76,20 +99,21 @@ namespace PepperDash.Essentials.Core
if (_partitionSensor != null)
{
_partitionSensor.PartitionPresentFeedback.OutputChange -= PartitionPresentFeedback_OutputChange;
_partitionSensor.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
}
}
public void SetManualMode()
{
isInAutoMode = false;
IsInAutoMode = false;
if (PartitionPresentFeedback != null)
{
PartitionPresentFeedback.SetValueFunc(() => partitionPresent);
PartitionPresentFeedback.SetValueFunc(() => _partitionPresent);
}
else
{
PartitionPresentFeedback = new BoolFeedback(() => partitionPresent);
PartitionPresentFeedback = new BoolFeedback(() => _partitionPresent);
}
if (_partitionSensor != null)
@@ -101,27 +125,30 @@ namespace PepperDash.Essentials.Core
public void SetPartitionStatePresent()
{
if (!isInAutoMode)
if (!IsInAutoMode)
{
partitionPresent = true;
PartitionPresent = true;
PartitionPresentFeedback.FireUpdate();
}
}
public void SetPartitionStateNotPresent()
{
if (!isInAutoMode)
if (!IsInAutoMode)
{
partitionPresent = false;
PartitionPresent = false;
PartitionPresentFeedback.FireUpdate();
}
}
public void ToggglePartitionState()
{
if (!isInAutoMode)
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"Toggling Partition State for {Key}", this);
Debug.LogMessage(Serilog.Events.LogEventLevel.Verbose, $"IsInAutoMode: {IsInAutoMode}", this);
if (!IsInAutoMode)
{
partitionPresent = !partitionPresent;
PartitionPresent = !PartitionPresent;
PartitionPresentFeedback.FireUpdate();
}
}

View File

@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using System.Collections.Generic;
using Newtonsoft.Json;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
@@ -13,7 +9,11 @@ namespace PepperDash.Essentials.Core
/// </summary>
public interface IPartitionStateProvider : IKeyName
{
[JsonIgnore]
BoolFeedback PartitionPresentFeedback { get; }
[JsonProperty("partitionPresent")]
bool PartitionPresent { get; }
}
/// <summary>
@@ -21,8 +21,12 @@ namespace PepperDash.Essentials.Core
/// </summary>
public interface IPartitionController : IPartitionStateProvider
{
[JsonProperty("adjacentRoomKeys")]
List<string> AdjacentRoomKeys { get; }
[JsonProperty("isInAutoMode")]
bool IsInAutoMode { get; }
void SetPartitionStatePresent();
void SetPartitionStateNotPresent();

View File

@@ -23,7 +23,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.42" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-402" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-419" />
</ItemGroup>
<ItemGroup>
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />

View File

@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
using Serilog.Events;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Core
{
@@ -17,7 +17,33 @@ namespace PepperDash.Essentials.Core
private List<IEssentialsRoom> _rooms;
private bool isInAutoMode;
public List<IKeyName> Rooms
{
get
{
return _rooms.Cast<IKeyName>().ToList();
}
}
private bool _isInAutoMode;
public bool IsInAutoMode
{
get
{
return _isInAutoMode;
}
set
{
if(value == _isInAutoMode)
{
return;
}
_isInAutoMode = value;
IsInAutoModeFeedback.FireUpdate();
}
}
private CTimer _scenarioChangeDebounceTimer;
@@ -36,14 +62,14 @@ namespace PepperDash.Essentials.Core
_scenarioChangeDebounceTimeSeconds = _propertiesConfig.ScenarioChangeDebounceTimeSeconds;
}
IsInAutoModeFeedback = new BoolFeedback(() => isInAutoMode);
IsInAutoModeFeedback = new BoolFeedback(() => _isInAutoMode);
// default to auto mode
isInAutoMode = true;
IsInAutoMode = true;
if (_propertiesConfig.defaultToManualMode)
{
isInAutoMode = false;
IsInAutoMode = false;
}
IsInAutoModeFeedback.FireUpdate();
@@ -56,7 +82,7 @@ namespace PepperDash.Essentials.Core
SetRooms();
if (isInAutoMode)
if (IsInAutoMode)
{
DetermineRoomCombinationScenario();
}
@@ -111,7 +137,11 @@ namespace PepperDash.Essentials.Core
void StartDebounceTimer()
{
var time = _scenarioChangeDebounceTimeSeconds * 1000;
// default to 500ms for manual mode
var time = 500;
// if in auto mode, debounce the scenario change
if(IsInAutoMode) time = _scenarioChangeDebounceTimeSeconds * 1000;
if (_scenarioChangeDebounceTimer == null)
{
@@ -185,7 +215,7 @@ namespace PepperDash.Essentials.Core
{
_currentScenario.Activate();
Debug.LogMessage(LogEventLevel.Debug, this, "Current Scenario: {0}", _currentScenario.Name);
Debug.LogMessage(LogEventLevel.Debug, $"Current Scenario: {_currentScenario.Name}", this);
}
var handler = RoomCombinationScenarioChanged;
@@ -201,20 +231,17 @@ namespace PepperDash.Essentials.Core
public void SetAutoMode()
{
isInAutoMode = true;
IsInAutoModeFeedback.FireUpdate();
IsInAutoMode = true;
}
public void SetManualMode()
{
isInAutoMode = false;
IsInAutoModeFeedback.FireUpdate();
IsInAutoMode = false;
}
public void ToggleMode()
{
isInAutoMode = !isInAutoMode;
IsInAutoModeFeedback.FireUpdate();
IsInAutoMode = !IsInAutoMode;
}
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; private set; }
@@ -223,7 +250,7 @@ namespace PepperDash.Essentials.Core
public void TogglePartitionState(string partitionKey)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)) as IPartitionController;
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey));
if (partition != null)
{
@@ -233,7 +260,7 @@ namespace PepperDash.Essentials.Core
public void SetRoomCombinationScenario(string scenarioKey)
{
if (isInAutoMode)
if (IsInAutoMode)
{
Debug.LogMessage(LogEventLevel.Information, this, "Cannot set room combination scenario when in auto mode. Set to auto mode first.");
return;

View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
@@ -21,13 +18,21 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// The current room combination scenario
/// </summary>
[JsonProperty("currentScenario")]
IRoomCombinationScenario CurrentScenario { get; }
/// <summary>
/// When true, indicates the current mode is auto mode
/// </summary>
[JsonIgnore]
BoolFeedback IsInAutoModeFeedback {get;}
[JsonProperty("isInAutoMode")]
bool IsInAutoMode { get; }
[JsonProperty("rooms")]
List<IKeyName> Rooms { get; }
/// <summary>
/// Sets auto mode
/// </summary>
@@ -46,11 +51,13 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// The available room combinatino scenarios
/// </summary>
[JsonProperty("roomCombinationScenarios")]
List<IRoomCombinationScenario> RoomCombinationScenarios { get; }
/// <summary>
/// The partition
/// </summary>
[JsonProperty("partitions")]
List<IPartitionController> Partitions { get; }
/// <summary>
@@ -71,8 +78,12 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// When true, indicates that this room combination scenario is active
/// </summary>
[JsonIgnore]
BoolFeedback IsActiveFeedback { get; }
[JsonProperty("isActive")]
bool IsActive { get; }
/// <summary>
/// Activates this room combination scenario
/// </summary>
@@ -86,11 +97,13 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// The state of the partitions that would activate this scenario
/// </summary>
[JsonProperty("partitionStates")]
List<PartitionState> PartitionStates { get; }
/// <summary>
/// The mapping of UIs by key to rooms by key
/// </summary>
[JsonProperty("uiMap")]
Dictionary<string, string> UiMap { get; set; }
}

View File

@@ -16,20 +16,41 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Represents a room combination scenario
/// </summary>
public class RoomCombinationScenario: IRoomCombinationScenario
public class RoomCombinationScenario: IRoomCombinationScenario, IKeyName
{
private RoomCombinationScenarioConfig _config;
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("partitionStates")]
public List<PartitionState> PartitionStates { get; private set; }
[JsonProperty("uiMap")]
public Dictionary<string, string> UiMap { get; set; }
private bool _isActive;
[JsonProperty("isActive")]
public bool IsActive
{
get { return _isActive; }
set
{
if(value == _isActive)
{
return;
}
_isActive = value;
IsActiveFeedback.FireUpdate();
}
}
[JsonIgnore]
public BoolFeedback IsActiveFeedback { get; private set; }
private List<DeviceActionWrapper> activationActions;
@@ -67,8 +88,7 @@ namespace PepperDash.Essentials.Core
}
}
_isActive = true;
IsActiveFeedback.FireUpdate();
IsActive = true;
}
public void Deactivate()
@@ -83,8 +103,7 @@ namespace PepperDash.Essentials.Core
}
}
_isActive = false;
IsActiveFeedback.FireUpdate();
IsActive = false;
}
}

View File

@@ -198,6 +198,9 @@ namespace PepperDash.Essentials.Room.Config
public string SourceListKey { get; set; }
[JsonProperty("destinationListKey")]
public string DestinationListKey { get; set; }
[JsonProperty("levelControlListKey")]
public string LevelControlListKey { get; set; }
[JsonProperty("defaultSourceItem")]
public string DefaultSourceItem { get; set; }
/// <summary>

View File

@@ -59,28 +59,81 @@ namespace PepperDash.Essentials.Core
/// </summary>
public IMobileControlRoomMessenger MobileControlRoomBridge { get; private set; }
protected const string _defaultListKey = "default";
/// <summary>
/// The config name of the source list
/// </summary>
///
protected string _SourceListKey;
private string _sourceListKey;
public string SourceListKey {
get
{
return _SourceListKey;
}
private set
{
if (value != _SourceListKey)
if(string.IsNullOrEmpty(_sourceListKey))
{
_SourceListKey = value;
return _defaultListKey;
}
else
{
return _sourceListKey;
}
}
protected set
{
if (value != _sourceListKey)
{
_sourceListKey = value;
}
}
}
public string DestinationListKey { get; private set; }
private string _destinationListKey;
public string DestinationListKey
{
get
{
if (string.IsNullOrEmpty(_destinationListKey))
{
return _defaultListKey;
}
else
{
return _destinationListKey;
}
}
protected set
{
if (value != _destinationListKey)
{
_destinationListKey = value;
}
}
}
private string _levelControlListKey;
public string LevelControlListKey
{
get
{
if (string.IsNullOrEmpty(_levelControlListKey))
{
return _defaultListKey;
}
else
{
return _destinationListKey;
}
}
protected set
{
if (value != _levelControlListKey)
{
_levelControlListKey = value;
}
}
}
protected const string _defaultSourceListKey = "default";
/// <summary>
/// Timer used for informing the UIs of a shutdown
@@ -141,6 +194,7 @@ namespace PepperDash.Essentials.Core
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
ShutdownType = eShutdownType.None;
};
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
ShutdownPromptSeconds = 60;
@@ -191,7 +245,7 @@ namespace PepperDash.Essentials.Core
}
else
{
sourceListKey = _defaultSourceListKey;
sourceListKey = _defaultListKey;
}
}

View File

@@ -29,6 +29,8 @@ namespace PepperDash.Essentials.Core
string DestinationListKey { get; }
string LevelControlListKey { get; }
SecondsCountdownTimer ShutdownPromptTimer { get; }
int ShutdownPromptSeconds { get; }
int ShutdownVacancySeconds { get; }

View File

@@ -22,7 +22,7 @@ namespace PepperDash.Essentials.Core
/// </summary>
public interface IHasDefaultDisplay
{
IRoutingSinkWithSwitching DefaultDisplay { get; }
IRoutingSink DefaultDisplay { get; }
}
/// <summary>
@@ -30,7 +30,7 @@ namespace PepperDash.Essentials.Core
/// </summary>
public interface IHasMultipleDisplays
{
Dictionary<eSourceListItemDestinationTypes, IRoutingSinkWithSwitching> Displays { get; }
Dictionary<eSourceListItemDestinationTypes, IRoutingSink> Displays { get; }
}
/// <summary>
@@ -57,6 +57,8 @@ namespace PepperDash.Essentials.Core
public interface IHasMatrixRouting
{
string MatrixRoutingDeviceKey { get; }
List<string> EndpointKeys { get; }
}
/// <summary>
@@ -75,6 +77,34 @@ namespace PepperDash.Essentials.Core
SecondsCountdownTimer ShutdownPromptTimer { get; }
void SetShutdownPromptSeconds(int seconds);
void StartShutdown(eShutdownType type);
}
/// <summary""'""">
/// Describes a room with a tech password
/// </summary>
public interface ITechPassword
{
event EventHandler<TechPasswordEventArgs> TechPasswordValidateResult;
event EventHandler<EventArgs> TechPasswordChanged;
int TechPasswordLength { get; }
void ValidateTechPassword(string password);
void SetTechPassword(string oldPassword, string newPassword);
}
public class TechPasswordEventArgs : EventArgs
{
public bool IsValid { get; private set; }
public TechPasswordEventArgs(bool isValid)
{
IsValid = isValid;
}
}
/// <summary>
@@ -129,4 +159,13 @@ namespace PepperDash.Essentials.Core
Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; }
}
public interface IHasAccessoryDevices : IKeyName
{
List<string> AccessoryDeviceKeys { get; }
}
public interface IHasCiscoNavigatorTouchpanel
{
string CiscoNavigatorTouchpanelKey { get; }
}
}

View File

@@ -2,10 +2,10 @@
namespace PepperDash.Essentials.Core.Routing
{
public interface IMatrixRouting<TInput, TOutput> where TInput : IRoutingInputSlot where TOutput : IRoutingOutputSlot
public interface IMatrixRouting
{
Dictionary<string, TInput> InputSlots { get; }
Dictionary<string, TOutput> OutputSlots { get; }
Dictionary<string, IRoutingInputSlot> InputSlots { get; }
Dictionary<string, IRoutingOutputSlot> OutputSlots { get; }
void Route(string inputSlotKey, string outputSlotKey, eRoutingSignalType type);
}

View File

@@ -1,26 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Core.Routing
namespace PepperDash.Essentials.Core.Routing
{
public interface IRoutingInputSlot: IRoutingSlot, IOnline, IVideoSync
{
string TxDeviceKey { get; }
}
public abstract class RoutingInputSlotBase : IRoutingInputSlot
{
public abstract string TxDeviceKey { get; }
public abstract int SlotNumber { get; }
public abstract eRoutingSignalType SupportedSignalTypes { get; }
public abstract string Name { get; }
public abstract BoolFeedback IsOnline { get; }
public abstract bool VideoSyncDetected { get; }
public abstract string Key { get; }
public abstract event EventHandler VideoSyncChanged;
}
}

View File

@@ -9,18 +9,6 @@ namespace PepperDash.Essentials.Core.Routing
string RxDeviceKey { get; }
Dictionary<eRoutingSignalType, RoutingInputSlotBase> CurrentRoutes { get; }
}
public abstract class RoutingOutputSlotBase : IRoutingOutputSlot
{
public abstract string RxDeviceKey { get; }
public abstract Dictionary<eRoutingSignalType, RoutingInputSlotBase> CurrentRoutes { get; }
public abstract int SlotNumber { get; }
public abstract eRoutingSignalType SupportedSignalTypes { get; }
public abstract string Name { get; }
public abstract string Key { get; }
public abstract event EventHandler OutputSlotChanged;
}
Dictionary<eRoutingSignalType, IRoutingInputSlot> CurrentRoutes { get; }
}
}

View File

@@ -23,6 +23,8 @@ namespace PepperDash.Essentials.Core
public IntFeedback PercentFeedback { get; private set; }
public StringFeedback TimeRemainingFeedback { get; private set; }
public IntFeedback SecondsRemainingFeedback { get; private set; }
public bool CountsDown { get; set; }
/// <summary>
@@ -50,8 +52,8 @@ namespace PepperDash.Essentials.Core
var timeSpan = FinishTime - DateTime.Now;
Debug.LogMessage(LogEventLevel.Verbose, this,
"timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}",
Debug.LogMessage(LogEventLevel.Verbose,
"timeSpan.Minutes == {0}, timeSpan.Seconds == {1}, timeSpan.TotalSeconds == {2}", this,
timeSpan.Minutes, timeSpan.Seconds, timeSpan.TotalSeconds);
if (Math.Floor(timeSpan.TotalSeconds) < 60 && Math.Floor(timeSpan.TotalSeconds) >= 0) //ignore milliseconds
@@ -64,6 +66,8 @@ namespace PepperDash.Essentials.Core
: String.Format("{0:00}:{1:00}", timeSpan.Minutes, timeSpan.Seconds);
});
SecondsRemainingFeedback = new IntFeedback(() => (int)(FinishTime - DateTime.Now).TotalSeconds);
PercentFeedback =
new IntFeedback(
() =>
@@ -99,6 +103,7 @@ namespace PepperDash.Essentials.Core
public void Reset()
{
_isRunning = false;
IsRunningFeedback.FireUpdate();
Start();
}
@@ -129,7 +134,11 @@ namespace PepperDash.Essentials.Core
void StopHelper()
{
if (_secondTimer != null)
{
_secondTimer.Stop();
_secondTimer = null;
}
_isRunning = false;
IsRunningFeedback.FireUpdate();
}
@@ -144,6 +153,7 @@ namespace PepperDash.Essentials.Core
PercentFeedback.FireUpdate();
TimeRemainingFeedback.FireUpdate();
SecondsRemainingFeedback.FireUpdate();
}
}
}

View File

@@ -6,6 +6,7 @@ using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Routing;
using Serilog.Events;
@@ -120,7 +121,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays
// Fake cool-down cycle
CooldownTimer = new CTimer(o =>
{
Debug.LogMessage(LogEventLevel.Verbose, this, "Cooldown timer ending");
Debug.LogMessage(LogEventLevel.Verbose, "Cooldown timer ending", this);
_IsCoolingDown = false;
IsCoolingDownFeedback.InvokeFireUpdate();
_PowerIsOn = false;
@@ -141,10 +142,10 @@ namespace PepperDash.Essentials.Devices.Common.Displays
{
Debug.LogMessage(LogEventLevel.Verbose, this, "ExecuteSwitch: {0}", selector);
if (!_PowerIsOn)
{
PowerOn();
}
if (!_PowerIsOn)
{
PowerOn();
}
if (!Inputs.Items.TryGetValue(selector.ToString(), out var input))
return;
@@ -152,32 +153,6 @@ namespace PepperDash.Essentials.Devices.Common.Displays
input.Select();
}
public void SetInput(string selector)
{
ISelectableItem currentInput = null;
try
{
currentInput = Inputs.Items.SingleOrDefault(Inputs => Inputs.Value.IsSelected).Value;
}
catch { }
if (currentInput != null)
{
Debug.LogMessage(LogEventLevel.Verbose, this, "SetInput: {0}", selector);
currentInput.IsSelected = false;
}
if (!Inputs.Items.TryGetValue(selector, out var input))
return;
input.IsSelected = true;
Inputs.CurrentItem = selector;
}
#region IBasicVolumeWithFeedback Members
@@ -251,4 +226,17 @@ namespace PepperDash.Essentials.Devices.Common.Displays
}
public class MockDisplayFactory : EssentialsDeviceFactory<MockDisplay>
{
public MockDisplayFactory()
{
TypeNames = new List<string>() { "mockdisplay" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Mock Display Device");
return new MockDisplay(dc.Key, dc.Name);
}
}
}

View File

@@ -54,8 +54,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays
public class MockDisplayInput : ISelectableItem
{
private IHasInputs<string, string> _parent;
private MockDisplay _parent;
private bool _isSelected;
@@ -91,7 +90,12 @@ namespace PepperDash.Essentials.Devices.Common.Displays
public void Select()
{
_parent.SetInput(Key);
if (!_parent.PowerIsOnFeedback.BoolValue) _parent.PowerOn();
foreach(var input in _parent.Inputs.Items)
{
input.Value.IsSelected = input.Key == this.Key;
}
}
}
}

View File

@@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.CrestronIO;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Devices.Common;
using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Shades
{
/// <summary>
/// Controls a single shade using three relays
/// </summary>
public class ScreenLiftController : EssentialsDevice, IProjectorScreenLiftControl
{
readonly ScreenLiftControllerConfigProperties Config;
readonly ScreenLiftRelaysConfig RaiseRelayConfig;
readonly ScreenLiftRelaysConfig LowerRelayConfig;
readonly ScreenLiftRelaysConfig LatchedRelayConfig;
Displays.DisplayBase DisplayDevice;
ISwitchedOutput RaiseRelay;
ISwitchedOutput LowerRelay;
ISwitchedOutput LatchedRelay;
public bool InUpPosition
{
get { return _isInUpPosition; }
set
{
if (value == _isInUpPosition) return;
_isInUpPosition = value;
IsInUpPosition.FireUpdate();
PositionChanged?.Invoke(this, new EventArgs());
}
}
private bool _isInUpPosition { get; set; }
public eScreenLiftControlType Type { get; private set; }
public eScreenLiftControlMode Mode { get; private set; }
public string DisplayDeviceKey { get; private set; }
public BoolFeedback IsInUpPosition { get; private set; }
public event EventHandler<EventArgs> PositionChanged;
public ScreenLiftController(string key, string name, ScreenLiftControllerConfigProperties config)
: base(key, name)
{
Config = config;
DisplayDeviceKey = Config.DisplayDeviceKey;
Mode = Config.Mode;
Type = Config.Type;
IsInUpPosition = new BoolFeedback(() => _isInUpPosition);
switch (Mode)
{
case eScreenLiftControlMode.momentary:
{
RaiseRelayConfig = Config.Relays["raise"];
LowerRelayConfig = Config.Relays["lower"];
break;
}
case eScreenLiftControlMode.latched:
{
LatchedRelayConfig = Config.Relays["latched"];
break;
}
}
}
private void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
if (!DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.lift)
{
Raise();
return;
}
if (DisplayDevice.IsCoolingDownFeedback.BoolValue && Type == eScreenLiftControlType.screen)
{
Raise();
return;
}
}
private void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
if (DisplayDevice.IsWarmingUpFeedback.BoolValue)
{
Lower();
}
}
public override bool CustomActivate()
{
//Create ISwitchedOutput objects based on props
switch (Mode)
{
case eScreenLiftControlMode.momentary:
{
Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}");
RaiseRelay = GetSwitchedOutputFromDevice(RaiseRelayConfig.DeviceKey);
LowerRelay = GetSwitchedOutputFromDevice(LowerRelayConfig.DeviceKey);
break;
}
case eScreenLiftControlMode.latched:
{
Debug.LogMessage(LogEventLevel.Debug, this, $"Getting relays for {Mode}");
LatchedRelay = GetSwitchedOutputFromDevice(LatchedRelayConfig.DeviceKey);
break;
}
}
Debug.LogMessage(LogEventLevel.Debug, this, $"Getting display with key {DisplayDeviceKey}");
DisplayDevice = GetDisplayBaseFromDevice(DisplayDeviceKey);
if (DisplayDevice != null)
{
Debug.LogMessage(LogEventLevel.Debug, this, $"Subscribing to {DisplayDeviceKey} feedbacks");
DisplayDevice.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
DisplayDevice.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
}
return base.CustomActivate();
}
public void Raise()
{
if (RaiseRelay == null && LatchedRelay == null) return;
Debug.LogMessage(LogEventLevel.Debug, this, $"Raising {Type}");
switch (Mode)
{
case eScreenLiftControlMode.momentary:
{
PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs);
break;
}
case eScreenLiftControlMode.latched:
{
LatchedRelay.Off();
break;
}
}
InUpPosition = true;
}
public void Lower()
{
if (LowerRelay == null && LatchedRelay == null) return;
Debug.LogMessage(LogEventLevel.Debug, this, $"Lowering {Type}");
switch (Mode)
{
case eScreenLiftControlMode.momentary:
{
PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs);
break;
}
case eScreenLiftControlMode.latched:
{
LatchedRelay.On();
break;
}
}
InUpPosition = false;
}
void PulseOutput(ISwitchedOutput output, int pulseTime)
{
output.On();
CTimer pulseTimer = new CTimer(new CTimerCallbackFunction((o) => output.Off()), pulseTime);
}
/// <summary>
/// Attempts to get the port on teh specified device from config
/// </summary>
/// <param name="relayConfig"></param>
/// <returns></returns>
ISwitchedOutput GetSwitchedOutputFromDevice(string relayKey)
{
var portDevice = DeviceManager.GetDeviceForKey(relayKey);
if (portDevice != null)
{
return (portDevice as ISwitchedOutput);
}
else
{
Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get relay device with key '{0}'", relayKey);
return null;
}
}
Displays.DisplayBase GetDisplayBaseFromDevice(string displayKey)
{
var displayDevice = DeviceManager.GetDeviceForKey(displayKey);
if (displayDevice != null)
{
return displayDevice as Displays.DisplayBase;
}
else
{
Debug.LogMessage(LogEventLevel.Debug, this, "Error: Unable to get display device with key '{0}'", displayKey);
return null;
}
}
}
public class ScreenLiftControllerConfigProperties
{
[JsonProperty("displayDeviceKey")]
public string DisplayDeviceKey { get; set; }
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
public eScreenLiftControlType Type { get; set; }
[JsonProperty("mode")]
[JsonConverter(typeof(StringEnumConverter))]
public eScreenLiftControlMode Mode { get; set; }
[JsonProperty("relays")]
public Dictionary<string,ScreenLiftRelaysConfig> Relays { get; set; }
}
public class ScreenLiftRelaysConfig
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("pulseTimeInMs")]
public int PulseTimeInMs { get; set; }
}
public class ScreenLiftControllerFactory : EssentialsDeviceFactory<RelayControlledShade>
{
public ScreenLiftControllerFactory()
{
TypeNames = new List<string>() { "screenliftcontroller" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.LogMessage(LogEventLevel.Debug, "Factory Attempting to create new Generic Comm Device");
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<ScreenLiftControllerConfigProperties>(dc.Properties.ToString());
return new ScreenLiftController(dc.Key, dc.Name, props);
}
}
public enum eScreenLiftControlMode
{
momentary,
latched
}
}

View File

@@ -27,6 +27,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.42" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-402" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-419" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,14 @@
using PepperDash.Essentials.Room.Config;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PepperDash.Essentials.Devices.Common.Room
{
public interface IEssentialsRoomPropertiesConfig
{
EssentialsRoomPropertiesConfig PropertiesConfig { get; }
}
}

View File

@@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace PepperDash.Essentials.Devices.Common.SoftCodec
{
public class GenericSoftCodec : EssentialsDevice, IRoutingInputsOutputs
public class GenericSoftCodec : EssentialsDevice, IRoutingSource, IRoutingSink
{
public GenericSoftCodec(string key, string name, GenericSoftCodecProperties props) : base(key, name)
{
@@ -48,6 +48,32 @@ namespace PepperDash.Essentials.Devices.Common.SoftCodec
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
public string CurrentSourceInfoKey { get ; set; }
public SourceListItem CurrentSourceInfo
{
get
{
return _CurrentSourceInfo;
}
set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSourceChange;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
if (handler != null)
handler(_CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public event SourceInfoChangeHandler CurrentSourceChange;
}
public class GenericSoftCodecProperties

View File

@@ -47,7 +47,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.20.42" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-402" />
<PackageReference Include="PepperDashCore" Version="2.0.0-alpha-419" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />