Compare commits

...

67 Commits

Author SHA1 Message Date
Neil Dorin
9b62849d9d removes old comment 2021-01-06 14:45:40 -07:00
Neil Dorin
d311b6fef9 Adds AttributeName property to JoinData allowing attribute name to be set from config as well 2021-01-05 18:21:32 -07:00
Neil Dorin
4a642b1e36 Adds UserObject for future use purposes 2021-01-04 16:19:08 -07:00
Neil Dorin
de4f003c67 Swapped out hardcoded joins for join map in Vtc1FusionController 2021-01-04 12:10:12 -07:00
Neil Dorin
708ee1a8ff #535 Wraps up EssentialsHuddleSpaceFusionSystemControllerBase. Starts on Vtc1FusionController 2020-12-30 17:01:55 -07:00
Neil Dorin
7196d0aba8 Adds FusionRoomJoinMap and ability to set IPID and JoinMapKey from config 2020-12-29 20:20:49 -07:00
Andrew Welker
522c107ce6 Merge pull request #532 from PepperDash/feature/room-updates
Feature/room updates
2020-12-17 16:31:37 -07:00
Andrew Welker
cb29775004 Merge branch 'development' into feature/room-updates 2020-12-17 16:13:45 -07:00
Neil Dorin
fccbb55344 Merge pull request #528 from PepperDash/feature/update-plugin-dependency-check
Update Plugin Dependency Check
2020-12-17 16:13:30 -07:00
Andrew Welker
b2402402d9 remove dummy device add 2020-12-17 14:48:01 -07:00
Neil Dorin
f0a3b27e3b Adds dummy source and room power on implementation 2020-12-17 14:28:27 -07:00
Neil Dorin
57ebd2b608 Adds IRunDirectAction to EssentialsTechRoom 2020-12-17 14:07:48 -07:00
Andrew Welker
695ff5487f actually fire the PresetsSaved event 2020-12-17 10:38:31 -07:00
Andrew Welker
66cd39c013 changed event names and added saved event 2020-12-16 16:21:10 -07:00
Andrew Welker
91eec8c258 fix scheduled event saving 2020-12-15 16:43:09 -07:00
Andrew Welker
d2c308c009 Add methods & logic to make sure...
...day & time is in the list of recurrence days
2020-12-15 09:47:35 -07:00
Andrew Welker
a4a99f4a9b remove JsonConverter Attribute 2020-12-15 09:47:08 -07:00
Andrew Welker
eb114b4a95 make Days enum serialize to string 2020-12-15 08:44:10 -07:00
Andrew Welker
93e8d50e55 Merge branch 'development' into feature/update-plugin-dependency-check 2020-12-11 15:51:10 -07:00
Andrew Welker
3c6fc978d4 Merge pull request #530 from PepperDash/hotfix/displayBase-fixes
Hotfix/display base fixes
2020-12-11 15:50:55 -07:00
Andrew Welker
01ddf1721c add method to get scheduled events 2020-12-11 15:42:38 -07:00
Andrew Welker
1ee87c0499 add some debug statements and fix presets file loading 2020-12-09 16:37:14 -07:00
Andrew Welker
f8ae6264f7 add some debug statements and fix presets file loading 2020-12-09 16:18:21 -07:00
Andrew Welker
3e56859943 add UpdatePresets method 2020-12-09 15:14:52 -07:00
Andrew Welker
945db8a233 Merge branch 'development' into hotfix/displayBase-fixes 2020-12-09 13:02:59 -07:00
Andrew Welker
6e4fa48b9d rearrange message formatting 2020-12-08 16:34:00 -07:00
Andrew Welker
7e8f216afb added logic to send presets to far end 2020-12-08 16:24:35 -07:00
Andrew Welker
b09c151738 Added logic to send presets to far end 2020-12-08 16:24:22 -07:00
Andrew Welker
56cf54a644 Added LinkRooms as a PostActivationAction 2020-12-08 16:24:03 -07:00
Andrew Welker
169e897748 Add CriticalSection for file ops 2020-12-08 12:54:35 -07:00
Andrew Welker
748b1ca147 Add config properties
Implement ITvPresetsProvider
2020-12-08 12:51:20 -07:00
Andrew Welker
2e636082bb #526 Add ITvPresetsProvider interface 2020-12-08 12:50:55 -07:00
Andrew Welker
9204ad2701 #525 Add Rooms Array & LinkToRooms method 2020-12-08 12:48:26 -07:00
Andrew Welker
8feb7a142c #524 Fix Fusion Printing 2020-12-08 11:06:06 -07:00
Andrew Welker
d990930b19 #523 Add return statement 2020-12-08 11:05:52 -07:00
Andrew Welker
4d67279827 Log message to error log when configured com port doesn't exist 2020-12-08 08:02:35 -07:00
Andrew Welker
a78b29b0a1 #523 Add NullCheck and Debug message for com Port 2020-12-08 08:01:58 -07:00
Andrew Welker
2c36c0f2cb Run GoWithLoad command in separate thread
when using donotloadonnextboot
2020-12-08 08:01:25 -07:00
Andrew Welker
2eaf21b1e0 Fix event retrieval 2020-12-08 08:01:01 -07:00
Andrew Welker
099e387570 getting things in the right order for scheduling 2020-12-07 17:21:05 -07:00
Andrew Welker
c4755f23cd added logic to subscribe to scheduled event 2020-12-07 16:58:33 -07:00
Andrew Welker
9c4650b4af fixes to get it to load 2020-12-07 16:32:06 -07:00
Andrew Welker
43d7fab04d refactored Fusion Base Class 2020-12-07 11:50:48 -07:00
Andrew Welker
d2b7e71c4a Added GetScheduledEventGroup Method
added logic to enable/disable events
2020-12-07 11:49:30 -07:00
Andrew Welker
ab6d44e604 added enable property to ScheduledEventConfig 2020-12-07 11:48:48 -07:00
Andrew Welker
0dc2e9d134 Added logic to create EssentialsTechRoom 2020-12-07 11:48:34 -07:00
Andrew Welker
3a024b8d4c moved ScheduledEvents list to main object 2020-12-07 11:48:21 -07:00
Andrew Welker
05e2422cb4 refactoring some methods
add handling for Scheduled Events
2020-12-07 11:48:07 -07:00
Andrew Welker
fc5d4f946d added scheduled events config 2020-12-04 21:36:07 -07:00
Andrew Welker
45c1e25e4f Change to list of actions instead of dictionary 2020-12-04 21:35:31 -07:00
Andrew Welker
f11bdcfd53 add schedule config and schedule stuff 2020-12-04 16:21:48 -07:00
Andrew Welker
9888fbf047 added save presets method & expose some properties 2020-12-04 13:44:39 -07:00
Andrew Welker
9171610e34 getting files back in the project 2020-12-04 13:44:39 -07:00
Andrew Welker
7a8c1f3165 adding some overloads 2020-12-04 13:44:39 -07:00
Andrew Welker
008a052045 getting started with EssentialsTechRoom 2020-12-04 13:44:39 -07:00
Andrew Welker
93a5f2e3b2 fix slases 2020-12-04 12:18:08 -07:00
Andrew Welker
0e4edca08a update plugin dependency check message 2020-12-04 11:05:46 -07:00
Andrew Welker
f283f82bbc Merge pull request #520 from PepperDash/feature/add-dm-streaming-start-stop-support
Add dm streaming start stop support
2020-12-02 12:09:50 -07:00
Alex Johnson
ab5dd5f756 Fixes streaming card feedback and removes excess debug 2020-12-02 13:51:44 -05:00
Alex Johnson
e22c71853f Starts adding support for starting and stopping dm stream cards via API bridge 2020-12-02 13:10:47 -05:00
Andrew Welker
8bf27ecbd9 Merge pull request #518 from PepperDash/hotfix/zoom-auto-layout
Hotfix/zoom auto layout
2020-11-30 14:46:43 -07:00
Andrew Welker
d94d003050 Merge branch 'development' into hotfix/zoom-auto-layout 2020-11-30 14:08:08 -07:00
Andrew Welker
b67424c1e1 Merge pull request #507 from PepperDash/hotfix/missing-logo-info-in-room-config
Hotfix/missing logo info in room config
2020-11-24 11:25:06 -07:00
Andrew Welker
c366ee9d12 Merge branch 'development' into hotfix/missing-logo-info-in-room-config 2020-11-24 10:55:09 -07:00
Neil Dorin
b1aa9c3306 Merge pull request #498 from PepperDash/feature/mc-qr-code-checksum
#497 Add logic to set checksum value
2020-11-19 16:01:28 -07:00
Andrew Welker
db6ab3ee98 #497 Add logic to set checksum value 2020-11-18 09:36:39 -07:00
Neil Dorin
2ccf4be559 Merge pull request #496 from PepperDash/release/1.6.7
Release/1.6.7
2020-11-16 12:01:44 -07:00
28 changed files with 3756 additions and 2377 deletions

View File

@@ -70,6 +70,14 @@ namespace PepperDash.Essentials.Bridges
/// Range reports the highest supported HDCP state level for the corresponding input card
/// </summary>
public uint HdcpSupportCapability { get; set; }
/// <summary>
/// DM Chassis Stream Input Start (1), Stop (2), Pause (3) with Feedback
/// </summary>
public uint InputStreamCardStatus { get; set; }
/// <summary>
/// DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback
/// </summary>
public uint OutputStreamCardStatus { get; set; }
#endregion
#region Serials
@@ -115,6 +123,8 @@ namespace PepperDash.Essentials.Bridges
InputUsb = 700; //701-899
HdcpSupportState = 1000; //1001-1199
HdcpSupportCapability = 1200; //1201-1399
InputStreamCardStatus = 1500; //1501-1532
OutputStreamCardStatus = 1600; //1601-1632
//Serial
@@ -145,6 +155,8 @@ namespace PepperDash.Essentials.Bridges
OutputEndpointOnline = OutputEndpointOnline + joinOffset;
HdcpSupportState = HdcpSupportState + joinOffset;
HdcpSupportCapability = HdcpSupportCapability + joinOffset;
InputStreamCardStatus = InputStreamCardStatus + joinOffset;
OutputStreamCardStatus = OutputStreamCardStatus + joinOffset;
OutputDisabledByHdcp = OutputDisabledByHdcp + joinOffset;
TxAdvancedIsPresent = TxAdvancedIsPresent + joinOffset;
}

View File

@@ -12,6 +12,7 @@ using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.Fusion;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.DM;
using PepperDash.Essentials.Fusion;
@@ -52,7 +53,7 @@ namespace PepperDash.Essentials
if (Debug.DoNotLoadOnNextBoot)
{
CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
CrestronConsole.AddNewConsoleCommand(s => CrestronInvoke.BeginInvoke((o) => GoWithLoad()), "go", "Loads configuration file",
ConsoleAccessLevelEnum.AccessOperator);
}
@@ -431,12 +432,26 @@ namespace PepperDash.Essentials
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as EssentialsRoomBase;
if (room != null)
{
// default IPID
uint fusionIpId = 0xf1;
// default to no join map key
string fusionJoinMapKey = string.Empty;
var fusionConfig = room.Config.Properties["fusion"].ToObject<EssentialsRoomFusionConfig>();
if (fusionConfig != null)
{
fusionIpId = fusionConfig.IpIdInt;
fusionJoinMapKey = fusionConfig.JoinMapKey;
}
if (room is EssentialsHuddleSpaceRoom)
{
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase((EssentialsHuddleSpaceRoom)room, 0xf1));
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
@@ -448,12 +463,24 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
CreateMobileControlBridge(room);
}
else if (room is EssentialsTechRoom)
{
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
CreateMobileControlBridge(room);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsRoom, attempting to add to DeviceManager w/o Fusion");

View File

@@ -16,8 +16,8 @@ namespace PepperDash.Essentials.Fusion
{
BooleanSigData CodecIsInCall;
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
: base(room, ipId)
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId, string joinMapKey)
: base(room, ipId, joinMapKey)
{
}
@@ -55,25 +55,25 @@ namespace PepperDash.Essentials.Fusion
// Map FusionRoom Attributes:
// Codec volume
var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
var codecVolume = FusionRoom.CreateOffsetUshortSig(JoinMap.VolumeFader1.JoinNumber, JoinMap.VolumeFader1.Metadata.Description, eSigIoMask.InputOutputSig);
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
// In Call Status
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(JoinMap.VcCodecInCall.JoinNumber, JoinMap.VcCodecInCall.Metadata.Description, eSigIoMask.InputSigOnly);
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
// Online status
if (codec is ICommunicationMonitor)
{
var c = codec as ICommunicationMonitor;
var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
var codecOnline = FusionRoom.CreateOffsetBoolSig(JoinMap.VcCodecOnline.JoinNumber, JoinMap.VcCodecOnline.Metadata.Description, eSigIoMask.InputSigOnly);
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
c.CommunicationMonitor.StatusChange += (o, a) =>
{
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
};
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, JoinMap.VcCodecOnline.Metadata.Description);
}
// Codec IP Address
@@ -101,10 +101,10 @@ namespace PepperDash.Essentials.Fusion
if (codecHasIpInfo)
{
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(JoinMap.VcCodecIpAddress.JoinNumber, JoinMap.VcCodecIpAddress.Metadata.Description, eSigIoMask.InputSigOnly);
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
codecIpPortSig = FusionRoom.CreateOffsetStringSig(JoinMap.VcCodecIpPort.JoinNumber, JoinMap.VcCodecIpPort.Metadata.Description, eSigIoMask.InputSigOnly);
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
}
@@ -123,7 +123,7 @@ namespace PepperDash.Essentials.Fusion
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
}
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Codec", tempAsset.InstanceId);
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
@@ -166,20 +166,19 @@ namespace PepperDash.Essentials.Fusion
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(CreateAdHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
// Room to fusion room
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
// Moved to
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(JoinMap.Display1CurrentSourceName.JoinNumber, JoinMap.Display1CurrentSourceName.Metadata.Description, eSigIoMask.InputSigOnly);
// Don't think we need to get current status of this as nothing should be alive yet.
(Room as EssentialsHuddleVtc1Room).CurrentSourceChange += Room_CurrentSourceInfoChange;
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff", Room.SourceListKey));
// NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
@@ -197,9 +196,9 @@ namespace PepperDash.Essentials.Fusion
uint i = 1;
foreach (var kvp in setTopBoxes)
{
TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.Metadata.Description + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
if (i > JoinMap.Display1SetTopBoxSourceStart.JoinSpan) // We only have five spots
break;
}
@@ -207,7 +206,7 @@ namespace PepperDash.Essentials.Fusion
i = 1;
foreach (var kvp in discPlayers)
{
TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
TryAddRouteActionSigs(JoinMap.Display1DiscPlayerSourceStart.Metadata.Description + " " + i, JoinMap.Display1DiscPlayerSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 5) // We only have five spots
break;
@@ -217,9 +216,9 @@ namespace PepperDash.Essentials.Fusion
i = 1;
foreach (var kvp in laptops)
{
TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
TryAddRouteActionSigs(JoinMap.Display1LaptopSourceStart.Metadata.Description + " " + i, JoinMap.Display1LaptopSourceStart.JoinNumber + i, kvp.Key, kvp.Value.SourceDevice);
i++;
if (i > 10) // We only have ten spots???
if (i > JoinMap.Display1LaptopSourceStart.JoinSpan) // We only have ten spots???
break;
}
@@ -283,7 +282,7 @@ namespace PepperDash.Essentials.Fusion
if (defaultDisplay is IDisplayUsage)
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
MapDisplayToRoomJoins(1, 158, defaultDisplay);
MapDisplayToRoomJoins(1, JoinMap.Display1Start.JoinNumber, defaultDisplay);
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
@@ -328,7 +327,7 @@ namespace PepperDash.Essentials.Fusion
}
protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
protected override void MapDisplayToRoomJoins(int displayIndex, uint joinOffset, DisplayBase display)
{
string displayName = string.Format("Display {0} - ", displayIndex);

View File

@@ -141,11 +141,13 @@
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
<Compile Include="Room\Config\EssentialsTechRoomConfig.cs" />
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
<Compile Include="Room\Types\EssentialsDualDisplayRoom.cs" />
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
<Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomConfig.cs" />
<Compile Include="Room\Types\EssentialsTechRoom.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />

View File

@@ -22,30 +22,25 @@ namespace PepperDash.Essentials.Room.Config
public static Device GetRoomObject(DeviceConfig roomConfig)
{
var typeName = roomConfig.Type.ToLower();
if (typeName == "huddle")
{
var huddle = new EssentialsHuddleSpaceRoom(roomConfig);
return huddle;
return new EssentialsHuddleSpaceRoom(roomConfig);
}
else if (typeName == "huddlevtc1")
{
var rm = new EssentialsHuddleVtc1Room(roomConfig);
return rm;
}
else if (typeName == "ddvc01Bridge")
{
return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
}
else if (typeName == "dualdisplay")
{
var rm = new EssentialsDualDisplayRoom(roomConfig);
if (typeName == "huddlevtc1")
{
return new EssentialsHuddleVtc1Room(roomConfig);
}
if (typeName == "ddvc01bridge")
{
return new Device(roomConfig.Key, roomConfig.Name); // placeholder device that does nothing.
}
if (typeName == "dualdisplay")
{
return new EssentialsDualDisplayRoom(roomConfig);
}
return rm;
}
return null;
return typeName != "techroom" ? null : new EssentialsTechRoom(roomConfig);
}
/// <summary>
@@ -182,6 +177,9 @@ namespace PepperDash.Essentials.Room.Config
[JsonProperty("volumes")]
public EssentialsRoomVolumesConfig Volumes { get; set; }
[JsonProperty("fusion")]
public EssentialsRoomFusionConfig Fusion { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
@@ -225,6 +223,32 @@ namespace PepperDash.Essentials.Room.Config
}
public class EssentialsRoomFusionConfig
{
public uint IpIdInt
{
get
{
try
{
return Convert.ToUInt32(IpId, 16);
}
catch (Exception)
{
throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId));
}
}
}
[JsonProperty("ipId")]
public string IpId { get; set; }
[JsonProperty("joinMapKey")]
public string JoinMapKey { get; set; }
}
public class EssentialsRoomMicrophonePrivacyConfig
{
[JsonProperty("deviceKey")]

View File

@@ -0,0 +1,40 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsTechRoomConfig
{
[JsonProperty("dummySourceKey")]
public string DummySourceKey { get; set; }
[JsonProperty("displays")]
public List<string> Displays;
[JsonProperty("tuners")]
public List<string> Tuners;
[JsonProperty("userPin")]
public string UserPin;
[JsonProperty("techPin")]
public string TechPin;
[JsonProperty("presetsFileName")]
public string PresetsFileName;
[JsonProperty("scheduledEvents")]
public List<ScheduledEventConfig> ScheduledEvents;
[JsonProperty("isPrimary")] public bool IsPrimary;
[JsonProperty("isTvPresetsProvider")] public bool IsTvPresetsProvider;
public EssentialsTechRoomConfig()
{
Displays = new List<string>();
Tuners = new List<string>();
ScheduledEvents = new List<ScheduledEventConfig>();
}
}
}

View File

@@ -0,0 +1,435 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Scheduler;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
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.Presets;
using PepperDash.Essentials.Devices.Common;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public class EssentialsTechRoom : EssentialsRoomBase, ITvPresetsProvider, IBridgeAdvanced, IRunDirectRouteAction
{
private readonly EssentialsTechRoomConfig _config;
private readonly Dictionary<string, TwoWayDisplayBase> _displays;
private readonly DevicePresetsModel _tunerPresets;
private readonly Dictionary<string, IRSetTopBoxBase> _tuners;
private Dictionary<string, string> _currentPresets;
private ScheduledEventGroup _roomScheduledEventGroup;
public EssentialsTechRoom(DeviceConfig config) : base(config)
{
_config = config.Properties.ToObject<EssentialsTechRoomConfig>();
_tunerPresets = new DevicePresetsModel(String.Format("{0}-presets", config.Key), _config.PresetsFileName);
_tunerPresets.SetFileName(_config.PresetsFileName);
_tunerPresets.PresetRecalled += TunerPresetsOnPresetRecalled;
_tuners = GetDevices<IRSetTopBoxBase>(_config.Tuners);
_displays = GetDevices<TwoWayDisplayBase>(_config.Displays);
RoomPowerIsOnFeedback = new BoolFeedback(() => RoomPowerIsOn);
SetUpTunerPresetsFeedback();
SubscribeToDisplayFeedbacks();
CreateOrUpdateScheduledEvents();
}
public Dictionary<string, StringFeedback> CurrentPresetsFeedbacks { get; private set; }
public Dictionary<string, IRSetTopBoxBase> Tuners
{
get { return _tuners; }
}
public Dictionary<string, TwoWayDisplayBase> Displays
{
get { return _displays; }
}
public BoolFeedback RoomPowerIsOnFeedback { get; private set; }
public bool RoomPowerIsOn
{
get { return _displays.All(kv => kv.Value.PowerIsOnFeedback.BoolValue); }
}
#region ITvPresetsProvider Members
public DevicePresetsModel TvPresets
{
get { return _tunerPresets; }
}
#endregion
private void TunerPresetsOnPresetRecalled(ISetTopBoxNumericKeypad device, string channel)
{
if (!_currentPresets.ContainsKey(device.Key))
{
return;
}
_currentPresets[device.Key] = channel;
if (!CurrentPresetsFeedbacks.ContainsKey(device.Key))
{
CurrentPresetsFeedbacks[device.Key].FireUpdate();
}
}
private void SetUpTunerPresetsFeedback()
{
_currentPresets = new Dictionary<string, string>();
CurrentPresetsFeedbacks = new Dictionary<string, StringFeedback>();
foreach (var setTopBox in _tuners)
{
var tuner = setTopBox.Value;
_currentPresets.Add(tuner.Key, String.Empty);
CurrentPresetsFeedbacks.Add(tuner.Key, new StringFeedback(() => _currentPresets[tuner.Key]));
}
}
private void SubscribeToDisplayFeedbacks()
{
foreach (var display in _displays)
{
display.Value.PowerIsOnFeedback.OutputChange +=
(sender, args) => RoomPowerIsOnFeedback.InvokeFireUpdate();
}
}
private void CreateOrUpdateScheduledEvents()
{
var eventsConfig = _config.ScheduledEvents;
GetOrCreateScheduleGroup();
foreach (var eventConfig in eventsConfig)
{
CreateOrUpdateSingleEvent(eventConfig);
}
_roomScheduledEventGroup.UserGroupCallBack += HandleScheduledEvent;
}
private void GetOrCreateScheduleGroup()
{
if (_roomScheduledEventGroup == null)
{
_roomScheduledEventGroup = Scheduler.GetEventGroup(Key) ?? new ScheduledEventGroup(Key);
Scheduler.AddEventGroup(_roomScheduledEventGroup);
}
_roomScheduledEventGroup.RetrieveAllEvents();
}
private void CreateOrUpdateSingleEvent(ScheduledEventConfig scheduledEvent)
{
if (!_roomScheduledEventGroup.ScheduledEvents.ContainsKey(scheduledEvent.Key))
{
SchedulerUtilities.CreateEventFromConfig(scheduledEvent, _roomScheduledEventGroup, HandleScheduledEvent);
return;
}
var roomEvent = _roomScheduledEventGroup.ScheduledEvents[scheduledEvent.Key];
if (!SchedulerUtilities.CheckEventTimeForMatch(roomEvent, DateTime.Parse(scheduledEvent.Time)) &&
!SchedulerUtilities.CheckEventRecurrenceForMatch(roomEvent, scheduledEvent.Days))
{
return;
}
Debug.Console(1, this,
"Existing event does not match new config properties. Deleting existing event '{0}' and creating new event from configuration",
roomEvent.Name);
_roomScheduledEventGroup.DeleteEvent(roomEvent);
SchedulerUtilities.CreateEventFromConfig(scheduledEvent, _roomScheduledEventGroup, HandleScheduledEvent);
}
public void AddOrUpdateScheduledEvent(ScheduledEventConfig scheduledEvent)
{
//update config based on key of scheduleEvent
GetOrCreateScheduleGroup();
var existingEventIndex = _config.ScheduledEvents.FindIndex((e) => e.Key == scheduledEvent.Key);
if (existingEventIndex < 0)
{
_config.ScheduledEvents.Add(scheduledEvent);
}
else
{
_config.ScheduledEvents[existingEventIndex] = scheduledEvent;
}
//create or update event based on config
CreateOrUpdateSingleEvent(scheduledEvent);
//save config
Config.Properties = JToken.FromObject(_config);
CustomSetConfig(Config);
//Fire Event
OnScheduledEventUpdate();
}
public List<ScheduledEventConfig> GetScheduledEvents()
{
return _config.ScheduledEvents ?? new List<ScheduledEventConfig>();
}
private void OnScheduledEventUpdate()
{
var handler = ScheduledEventsChanged;
if (handler == null)
{
return;
}
handler(this, new ScheduledEventEventArgs {ScheduledEvents = _config.ScheduledEvents});
}
public event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged;
private void HandleScheduledEvent(ScheduledEvent schevent, ScheduledEventCommon.eCallbackReason type)
{
var eventConfig = _config.ScheduledEvents.FirstOrDefault(e => e.Key == schevent.Name);
if (eventConfig == null)
{
Debug.Console(1, this, "Event with name {0} not found", schevent.Name);
return;
}
Debug.Console(1, this, "Running actions for event {0}", schevent.Name);
if (eventConfig.Acknowledgeable)
{
schevent.Acknowledge();
}
CrestronInvoke.BeginInvoke((o) =>
{
foreach (var a in eventConfig.Actions)
{
DeviceJsonApi.DoDeviceAction(a);
}
});
}
public void RoomPowerOn()
{
var dummySource = DeviceManager.GetDeviceForKey(_config.DummySourceKey) as IRoutingOutputs;
if (dummySource == null)
{
Debug.Console(1, this, "Unable to get source with key: {0}", _config.DummySourceKey);
return;
}
foreach (var display in _displays)
{
RunDirectRoute(dummySource, display.Value);
}
}
public void RoomPowerOff()
{
foreach (var display in _displays)
{
display.Value.PowerOff();
}
}
private Dictionary<string, T> GetDevices<T>(ICollection<string> config) where T : IKeyed
{
try
{
var returnValue = DeviceManager.AllDevices.OfType<T>()
.Where(d => config.Contains(d.Key))
.ToDictionary(d => d.Key, d => d);
return returnValue;
}
catch
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error,
"Error getting devices. Check Essentials Configuration");
return null;
}
}
#region Overrides of EssentialsRoomBase
protected override Func<bool> IsWarmingFeedbackFunc
{
get { return () => false; }
}
protected override Func<bool> IsCoolingFeedbackFunc
{
get { return () => false; }
}
protected override Func<bool> OnFeedbackFunc
{
get { return () => RoomPowerIsOn; }
}
protected override void EndShutdown()
{
}
public override void SetDefaultLevels()
{
}
public override void PowerOnToDefaultOrLastSource()
{
}
public override bool RunDefaultPresentRoute()
{
return false;
}
public override void RoomVacatedForTimeoutPeriod(object o)
{
}
#endregion
#region Implementation of IBridgeAdvanced
public void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new EssentialsTechRoomJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!String.IsNullOrEmpty(joinMapSerialized))
{
joinMap = JsonConvert.DeserializeObject<EssentialsTechRoomJoinMap>(joinMapSerialized);
}
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
uint i;
if (_config.IsPrimary)
{
i = 0;
foreach (var feedback in CurrentPresetsFeedbacks)
{
feedback.Value.LinkInputSig(trilist.StringInput[(uint) (joinMap.CurrentPreset.JoinNumber + i)]);
i++;
}
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine)
{
return;
}
foreach (var feedback in CurrentPresetsFeedbacks)
{
feedback.Value.FireUpdate();
}
};
}
i = 0;
foreach (var setTopBox in _tuners)
{
var tuner = setTopBox;
trilist.SetStringSigAction(joinMap.CurrentPreset.JoinNumber + i, s => _tunerPresets.Dial(s, tuner.Value));
}
}
#endregion
private class EssentialsTechRoomJoinMap : JoinMapBaseAdvanced
{
[JoinName("currentPreset")]
public JoinDataComplete CurrentPreset = new JoinDataComplete(new JoinData {JoinNumber = 1, JoinSpan = 16},
new JoinMetadata {Description = "Current Tuner Preset", JoinType = eJoinType.Serial});
public EssentialsTechRoomJoinMap(uint joinStart) : base(joinStart, typeof(EssentialsTechRoomJoinMap))
{
}
}
#region IRunDirectRouteAction Members
private void RunDirectRoute(IRoutingOutputs source, IRoutingSink dest)
{
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", dest.Key);
return;
}
if (source == null)
{
dest.ReleaseRoute();
if (dest is IHasPowerControl)
(dest as IHasPowerControl).PowerOff();
}
else
{
dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video);
}
}
/// <summary>
/// Attempts to route directly between a source and destination
/// </summary>
/// <param name="sourceKey"></param>
/// <param name="destinationKey"></param>
public void RunDirectRoute(string sourceKey, string destinationKey)
{
IRoutingSink dest = null;
dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSink;
var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs;
if (source == null || dest == null)
{
Debug.Console(1, this, "Cannot route unknown source or destination '{0}' to {1}", sourceKey, destinationKey);
return;
}
RunDirectRoute(source, dest);
}
#endregion
}
public class ScheduledEventEventArgs : EventArgs
{
public List<ScheduledEventConfig> ScheduledEvents;
}
}

View File

@@ -99,12 +99,19 @@ namespace PepperDash.Essentials.Core.Bridges
Eisc.SigChange += Eisc_SigChange;
AddPostActivationAction(LinkDevices);
AddPostActivationAction(LinkRooms);
}
private void LinkDevices()
{
Debug.Console(1, this, "Linking Devices...");
if (PropertiesConfig.Devices == null)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "No devices linked to this bridge");
return;
}
foreach (var d in PropertiesConfig.Devices)
{
var device = DeviceManager.GetDeviceForKey(d.DeviceKey);
@@ -131,6 +138,16 @@ namespace PepperDash.Essentials.Core.Bridges
}
}
RegisterEisc();
}
private void RegisterEisc()
{
if (Eisc.Registered)
{
return;
}
var registerResult = Eisc.Register();
if (registerResult != eDeviceRegistrationUnRegistrationResponse.Success)
@@ -142,6 +159,33 @@ namespace PepperDash.Essentials.Core.Bridges
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "EISC registration successful");
}
public void LinkRooms()
{
Debug.Console(1, this, "Linking Rooms...");
if (PropertiesConfig.Rooms == null)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "No rooms linked to this bridge.");
return;
}
foreach (var room in PropertiesConfig.Rooms)
{
var rm = DeviceManager.GetDeviceForKey(room.RoomKey) as IBridgeAdvanced;
if (rm == null)
{
Debug.Console(1, this, Debug.ErrorLogLevel.Notice,
"Room {0} does not implement IBridgeAdvanced. Skipping...", room.RoomKey);
continue;
}
rm.LinkToApi(Eisc, room.JoinStart, room.JoinMapKey, this);
}
RegisterEisc();
}
/// <summary>
/// Adds a join map
/// </summary>
@@ -290,6 +334,9 @@ namespace PepperDash.Essentials.Core.Bridges
[JsonProperty("devices")]
public List<ApiDevicePropertiesConfig> Devices { get; set; }
[JsonProperty("rooms")]
public List<ApiRoomPropertiesConfig> Rooms { get; set; }
public class ApiDevicePropertiesConfig
{
@@ -303,6 +350,18 @@ namespace PepperDash.Essentials.Core.Bridges
public string JoinMapKey { get; set; }
}
public class ApiRoomPropertiesConfig
{
[JsonProperty("roomKey")]
public string RoomKey { get; set; }
[JsonProperty("joinStart")]
public uint JoinStart { get; set; }
[JsonProperty("joinMapKey")]
public string JoinMapKey { get; set; }
}
}
public class EiscApiAdvancedFactory : EssentialsDeviceFactory<EiscApiAdvanced>

View File

@@ -47,7 +47,7 @@ namespace PepperDash.Essentials.Core.Bridges
/// <param name="joinStart">Join this join map will start at</param>
/// <param name="type">Type of the child join map</param>
public AppleTvJoinMap(uint joinStart, Type type) : base(joinStart, type)
{
}
{
}
}
}

View File

@@ -76,6 +76,14 @@ namespace PepperDash.Essentials.Core.Bridges
public JoinDataComplete HdcpSupportCapability = new JoinDataComplete(new JoinData { JoinNumber = 1201, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Input HDCP Support Capability", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("InputStreamCardState")]
public JoinDataComplete InputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1501, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Stream Input Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("OutputStreamCardState")]
public JoinDataComplete OutputStreamCardState = new JoinDataComplete(new JoinData { JoinNumber = 1601, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Stream Output Start (1), Stop (2), Pause (3) with Feedback", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Analog });
[JoinName("InputNames")]
public JoinDataComplete InputNames = new JoinDataComplete(new JoinData { JoinNumber = 101, JoinSpan = 32 },
new JoinMetadata { Description = "DM Chassis Input Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial });

View File

@@ -56,6 +56,11 @@ namespace PepperDash.Essentials.Core
private void RegisterAndConfigureComPort()
{
if (Port == null)
{
Debug.Console(0,this,Debug.ErrorLogLevel.Error, "Configured com Port for this device does not exist.");
return;
}
if (Port.Parent is CrestronControlSystem)
{
var result = Port.Register();

View File

@@ -104,7 +104,7 @@ namespace PepperDash.Essentials.Core
var dev = GetIComPortsDeviceFromManagedDevice(config.ControlPortDevKey);
if (dev != null && config.ControlPortNumber <= dev.NumberOfComPorts)
return dev.ComPorts[config.ControlPortNumber];
Debug.Console(0, "GetComPort: Device '{0}' does not have com port {1}", config.ControlPortDevKey, config.ControlPortNumber);
Debug.Console(0,Debug.ErrorLogLevel.Notice, "GetComPort: Device '{0}' does not have com port {1}", config.ControlPortDevKey, config.ControlPortNumber);
return null;
}

View File

@@ -1,5 +1,5 @@
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.SmartObjects;
@@ -8,7 +8,7 @@ namespace PepperDash.Essentials.Core
/// <summary>
///
/// </summary>
public interface INumericKeypad
public interface INumericKeypad:IKeyed
{
void Digit0(bool pressRelease);
void Digit1(bool pressRelease);

View File

@@ -0,0 +1,9 @@
using PepperDash.Essentials.Core.Presets;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
public interface ITvPresetsProvider
{
DevicePresetsModel TvPresets { get; }
}
}

View File

@@ -84,8 +84,6 @@ namespace PepperDash.Essentials.Core
}
public abstract void PowerOn();
public abstract void PowerOff();
public abstract void PowerToggle();
@@ -102,7 +100,7 @@ namespace PepperDash.Essentials.Core
}
}
public abstract void ExecuteSwitch(object selector);
public abstract void ExecuteSwitch(object selector);
protected void LinkDisplayToApi(DisplayBase displayDevice, BasicTriList trilist, uint joinStart, string joinMapKey,
EiscApiAdvanced bridge)
@@ -319,7 +317,5 @@ namespace PepperDash.Essentials.Core
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core.Fusion
{
public class EssentialsHuddleSpaceRoomFusionRoomJoinMap : JoinMapBaseAdvanced
{
// Processor Attributes
[JoinName("ProcessorIp1")]
public JoinDataComplete ProcessorIp1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Info - Processor - IP 1" },
new JoinMetadata { Description = "Info - Processor - IP 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorIp2")]
public JoinDataComplete ProcessorIp2 = new JoinDataComplete(new JoinData { JoinNumber = 51, JoinSpan = 1, AttributeName = "Info - Processor - IP 2" },
new JoinMetadata { Description = "Info - Processor - IP 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorGateway")]
public JoinDataComplete ProcessorGateway = new JoinDataComplete(new JoinData { JoinNumber = 52, JoinSpan = 1, AttributeName = "Info - Processor - Gateway" },
new JoinMetadata { Description = "Info - Processor - Gateway", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorHostname")]
public JoinDataComplete ProcessorHostname = new JoinDataComplete(new JoinData { JoinNumber = 53, JoinSpan = 1, AttributeName = "Info - Processor - Hostname" },
new JoinMetadata { Description = "Info - Processor - Hostname", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorDomain")]
public JoinDataComplete ProcessorDomain = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1, AttributeName = "Info - Processor - Domain" },
new JoinMetadata { Description = "Info - Processor - Domain", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorDns1")]
public JoinDataComplete ProcessorDns1 = new JoinDataComplete(new JoinData { JoinNumber = 55, JoinSpan = 1, AttributeName = "Info - Processor - DNS 1" },
new JoinMetadata { Description = "Info - Processor - DNS 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorDns2")]
public JoinDataComplete ProcessorDns2 = new JoinDataComplete(new JoinData { JoinNumber = 56, JoinSpan = 1, AttributeName = "Info - Processor - DNS 2" },
new JoinMetadata { Description = "Info - Processor - DNS 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorMac1")]
public JoinDataComplete ProcessorMac1 = new JoinDataComplete(new JoinData { JoinNumber = 57, JoinSpan = 1, AttributeName = "Info - Processor - MAC 1" },
new JoinMetadata { Description = "Info - Processor - MAC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorMac2")]
public JoinDataComplete ProcessorMac2 = new JoinDataComplete(new JoinData { JoinNumber = 58, JoinSpan = 1, AttributeName = "Info - Processor - MAC 2" },
new JoinMetadata { Description = "Info - Processor - MAC 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorNetMask1")]
public JoinDataComplete ProcessorNetMask1 = new JoinDataComplete(new JoinData { JoinNumber = 59, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 1" },
new JoinMetadata { Description = "Info - Processor - Net Mask 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorNetMask2")]
public JoinDataComplete ProcessorNetMask2 = new JoinDataComplete(new JoinData { JoinNumber = 60, JoinSpan = 1, AttributeName = "Info - Processor - Net Mask 2" },
new JoinMetadata { Description = "Info - Processor - Net Mask 2", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorFirmware")]
public JoinDataComplete ProcessorFirmware = new JoinDataComplete(new JoinData { JoinNumber = 61, JoinSpan = 1, AttributeName = "Info - Processor - Firmware" },
new JoinMetadata { Description = "Info - Processor - Firmware", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProgramNameStart")]
public JoinDataComplete ProgramNameStart = new JoinDataComplete(new JoinData { JoinNumber = 62, JoinSpan = 10, AttributeName = "Info - Processor - Program" },
new JoinMetadata { Description = "Info - Processor - Program", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("ProcessorReboot")]
public JoinDataComplete ProcessorReboot = new JoinDataComplete(new JoinData { JoinNumber = 74, JoinSpan = 1, AttributeName = "Processor - Reboot" },
new JoinMetadata { Description = "Processor - Reboot", JoinCapabilities = eJoinCapabilities.FromFusion, JoinType = eJoinType.Digital });
// Volume Controls
[JoinName("VolumeFader1")]
public JoinDataComplete VolumeFader1 = new JoinDataComplete(new JoinData { JoinNumber = 50, JoinSpan = 1, AttributeName = "Volume - Fader01" },
new JoinMetadata { Description = "Volume - Fader01", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Analog });
// Codec Info
[JoinName("VcCodecInCall")]
public JoinDataComplete VcCodecInCall = new JoinDataComplete(new JoinData { JoinNumber = 69, JoinSpan = 1, AttributeName = "Conf - VC 1 In Call" },
new JoinMetadata { Description = "Conf - VC 1 In Call", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("VcCodecOnline")]
public JoinDataComplete VcCodecOnline = new JoinDataComplete(new JoinData { JoinNumber = 122, JoinSpan = 1, AttributeName = "Online - VC 1" },
new JoinMetadata { Description = "Online - VC 1", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("VcCodecIpAddress")]
public JoinDataComplete VcCodecIpAddress = new JoinDataComplete(new JoinData { JoinNumber = 121, JoinSpan = 1, AttributeName = "IP Address - VC" },
new JoinMetadata { Description = "IP Address - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
[JoinName("VcCodecIpPort")]
public JoinDataComplete VcCodecIpPort = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 1, AttributeName = "IP Port - VC" },
new JoinMetadata { Description = "IP Port - VC", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
// Source Attributes
[JoinName("Display1CurrentSourceName")]
public JoinDataComplete Display1CurrentSourceName = new JoinDataComplete(new JoinData { JoinNumber = 84, JoinSpan = 1, AttributeName = "Display 1 - Current Source" },
new JoinMetadata { Description = "Display 1 - Current Source", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Serial });
// Device Online Status
[JoinName("TouchpanelOnlineStart")]
public JoinDataComplete TouchpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 150, JoinSpan = 10, AttributeName = "Online - Touch Panel" },
new JoinMetadata { Description = "Online - Touch Panel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("XpanelOnlineStart")]
public JoinDataComplete XpanelOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 160, JoinSpan = 5, AttributeName = "Online - XPanel" },
new JoinMetadata { Description = "Online - XPanel", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("DisplayOnlineStart")]
public JoinDataComplete DisplayOnlineStart = new JoinDataComplete(new JoinData { JoinNumber = 170, JoinSpan = 10, AttributeName = "Online - Display" },
new JoinMetadata { Description = "Online - Display", JoinCapabilities = eJoinCapabilities.ToFusion, JoinType = eJoinType.Digital });
[JoinName("Display1LaptopSourceStart")]
public JoinDataComplete Display1LaptopSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 166, JoinSpan = 5, AttributeName = "Display 1 - Source Laptop" },
new JoinMetadata { Description = "Display 1 - Source Laptop", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
[JoinName("Display1DiscPlayerSourceStart")]
public JoinDataComplete Display1DiscPlayerSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 181, JoinSpan = 5, AttributeName = "Display 1 - Source Disc Player" },
new JoinMetadata { Description = "Display 1 - Source Disc Player", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
[JoinName("Display1SetTopBoxSourceStart")]
public JoinDataComplete Display1SetTopBoxSourceStart = new JoinDataComplete(new JoinData { JoinNumber = 188, JoinSpan = 5, AttributeName = "Display 1 - Source TV" },
new JoinMetadata { Description = "Display 1 - Source TV", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
// Display 1
[JoinName("Display1Start")]
public JoinDataComplete Display1Start = new JoinDataComplete(new JoinData { JoinNumber = 158, JoinSpan = 1 },
new JoinMetadata { Description = "Display 1 Start", JoinCapabilities = eJoinCapabilities.ToFromFusion, JoinType = eJoinType.Digital });
/// <summary>
/// Constructor to use when instantiating this Join Map without inheriting from it
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart)
: base(joinStart, typeof(EssentialsHuddleSpaceRoomFusionRoomJoinMap))
{
}
/// <summary>
/// Constructor to use when extending this Join map
/// </summary>
/// <param name="joinStart">Join this join map will start at</param>
/// <param name="type">Type of the child join map</param>
public EssentialsHuddleSpaceRoomFusionRoomJoinMap(uint joinStart, Type type) : base(joinStart, type)
{
}
}
}

View File

@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharp.Scheduler;
using PepperDash.Core;
using PepperDash.Essentials.Core.Fusion;
using PepperDash.Essentials.Room.Config;
using Activator = System.Activator;
namespace PepperDash.Essentials.Core
{
@@ -14,7 +17,7 @@ namespace PepperDash.Essentials.Core
/// </summary>
public static class Scheduler
{
private static Dictionary<string, ScheduledEventGroup> EventGroups = new Dictionary<string,ScheduledEventGroup>();
private static readonly Dictionary<string, ScheduledEventGroup> EventGroups = new Dictionary<string,ScheduledEventGroup>();
static Scheduler()
{
@@ -49,7 +52,6 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// Adds the event group to the global list
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static void AddEventGroup(ScheduledEventGroup eventGroup)
{
@@ -67,6 +69,13 @@ namespace PepperDash.Essentials.Core
if(!EventGroups.ContainsKey(eventGroup.Name))
EventGroups.Remove(eventGroup.Name);
}
public static ScheduledEventGroup GetEventGroup(string key)
{
ScheduledEventGroup returnValue;
return EventGroups.TryGetValue(key, out returnValue) ? returnValue : null;
}
}
public static class SchedulerUtilities
@@ -135,5 +144,90 @@ namespace PepperDash.Essentials.Core
return isMatch;
}
public static bool CheckEventTimeForMatch(ScheduledEvent evnt, DateTime time)
{
return evnt.DateAndTime.Hour == time.Hour && evnt.DateAndTime.Minute == time.Minute;
}
public static bool CheckEventRecurrenceForMatch(ScheduledEvent evnt, ScheduledEventCommon.eWeekDays days)
{
return evnt.Recurrence.RecurrenceDays == days;
}
public static void CreateEventFromConfig(ScheduledEventConfig config, ScheduledEventGroup group, ScheduledEvent.UserEventCallBack handler)
{
if (group == null)
{
Debug.Console(0, "Unable to create event. Group is 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.Console(2, "[Scheduler] Current Date day of week: {0} recurrence days: {1}", eventTime.DayOfWeek,
config.Days);
var dayOfWeekConverted = ConvertDayOfWeek(eventTime);
Debug.Console(1, "[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();
}
}
private static ScheduledEventCommon.eWeekDays ConvertDayOfWeek(DateTime eventTime)
{
return (ScheduledEventCommon.eWeekDays) Enum.Parse(typeof(ScheduledEventCommon.eWeekDays), eventTime.DayOfWeek.ToString(), true);
}
private static bool IsFlagSet<T>(this T value, T flag) where T : struct
{
CheckIsEnum<T>(true);
var lValue = Convert.ToInt64(value);
var lFlag = Convert.ToInt64(flag);
return (lValue & lFlag) != 0;
}
private static void CheckIsEnum<T>(bool withFlags)
{
if (!typeof(T).IsEnum)
throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName));
if (withFlags && !Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName));
}
}
}

View File

@@ -266,7 +266,7 @@ namespace PepperDash.Essentials.Core
@"Join Number: {0} | JoinSpan: '{1}' | Description: '{2}' | Type: '{3}' | Capabilities: '{4}'",
join.Value.JoinNumber,
join.Value.JoinSpan,
String.IsNullOrEmpty(join.Value.Metadata.Description) ? join.Value.Metadata.Label: join.Value.Metadata.Description,
String.IsNullOrEmpty(join.Value.Metadata.Description) ? join.Value.Metadata.Label : join.Value.Metadata.Description,
join.Value.Metadata.JoinType.ToString(),
join.Value.Metadata.JoinCapabilities.ToString());
}
@@ -288,7 +288,7 @@ namespace PepperDash.Essentials.Core
}
else
{
Debug.Console(2, "No mathcing key found in join map for: '{0}'", customJoinData.Key);
Debug.Console(2, "No matching key found in join map for: '{0}'", customJoinData.Key);
}
}
@@ -327,7 +327,10 @@ namespace PepperDash.Essentials.Core
None = 0,
ToSIMPL = 1,
FromSIMPL = 2,
ToFromSIMPL = ToSIMPL | FromSIMPL
ToFromSIMPL = ToSIMPL | FromSIMPL,
ToFusion = 4,
FromFusion = 8,
ToFromFusion = ToFusion | FromFusion,
}
[Flags]
@@ -340,7 +343,7 @@ namespace PepperDash.Essentials.Core
DigitalAnalog = Digital | Analog,
DigitalSerial = Digital | Serial,
AnalogSerial = Analog | Serial,
DigitalAnalogSerial = Digital | Analog | Serial
DigitalAnalogSerial = Digital | Analog | Serial,
}
/// <summary>
@@ -394,7 +397,7 @@ namespace PepperDash.Essentials.Core
}
/// <summary>
/// Data describing the join. Can be
/// Data describing the join. Can be overridden from configuratino
/// </summary>
public class JoinData
{
@@ -408,6 +411,11 @@ namespace PepperDash.Essentials.Core
/// </summary>
[JsonProperty("joinSpan")]
public uint JoinSpan { get; set; }
/// <summary>
/// Fusion Attribute Name (optional)
/// </summary>
[JsonProperty("attributeName")]
public string AttributeName { get; set; }
}
/// <summary>
@@ -419,6 +427,10 @@ namespace PepperDash.Essentials.Core
private JoinData _data;
public JoinMetadata Metadata { get; set; }
/// <summary>
/// To store some future information as you please
/// </summary>
public object UserObject { get; private set; }
public JoinDataComplete(JoinData data, JoinMetadata metadata)
{
@@ -449,6 +461,11 @@ namespace PepperDash.Essentials.Core
get { return _data.JoinSpan; }
}
public string AttributeName
{
get { return _data.AttributeName; }
}
public void SetCustomJoinData(JoinData customJoinData)
{
_data = customJoinData;

View File

@@ -199,6 +199,7 @@
<Compile Include="Devices\PC\Laptop.cs" />
<Compile Include="Devices\ReconfigurableDevice.cs" />
<Compile Include="Devices\VolumeDeviceChangeEventArgs.cs" />
<Compile Include="DeviceTypeInterfaces\ITvPresetsProvider.cs" />
<Compile Include="DeviceTypeInterfaces\LanguageLabel.cs" />
<Compile Include="DeviceTypeInterfaces\ILanguageProvider.cs" />
<Compile Include="DeviceTypeInterfaces\IHasBranding.cs" />
@@ -219,6 +220,7 @@
<Compile Include="Fusion\FusionCustomPropertiesBridge.cs" />
<Compile Include="Fusion\FusionEventHandlers.cs" />
<Compile Include="Fusion\FusionProcessorQueries.cs" />
<Compile Include="Fusion\EssentialsHuddleSpaceRoomFusionRoomJoinMap.cs" />
<Compile Include="Fusion\FusionRviDataClasses.cs" />
<Compile Include="Gateways\CenRfgwController.cs" />
<Compile Include="Gateways\EssentialsRfGatewayConfig.cs" />
@@ -278,6 +280,7 @@
<Compile Include="Remotes\Hrxx0WirelessRemoteController.cs" />
<Compile Include="Room\Behaviours\RoomOnToDefaultSourceWhenOccupied.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomScheduledEventsConfig.cs" />
<Compile Include="Room\Interfaces.cs" />
<Compile Include="Room\iOccupancyStatusProvider.cs" />
<Compile Include="Routing\DummyRoutingInputsDevice.cs" />

View File

@@ -402,13 +402,16 @@ namespace PepperDash.Essentials
/// Loads a
/// </summary>
/// <param name="plugin"></param>
/// <param name="loadedAssembly"></param>
static void LoadCustomPlugin(IPluginDeviceFactory plugin, LoadedAssembly loadedAssembly)
{
var passed = Global.IsRunningMinimumVersionOrHigher(plugin.MinimumEssentialsFrameworkVersion);
if (!passed)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Plugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin", plugin.MinimumEssentialsFrameworkVersion);
Debug.Console(0, Debug.ErrorLogLevel.Error,
"\r\n********************\r\n\tPlugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin {1}\r\n********************",
plugin.MinimumEssentialsFrameworkVersion, loadedAssembly.Name);
return;
}
else

View File

@@ -1,178 +1,301 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PepperDash.Core;
//using SSMono.IO;
using PepperDash.Core.WebApi.Presets;
namespace PepperDash.Essentials.Core.Presets
{
/// <summary>
/// Class that represents the model behind presets display
/// </summary>
public class DevicePresetsModel : Device
{
public event EventHandler PresetsLoaded;
/// <summary>
/// Class that represents the model behind presets display
/// </summary>
public class DevicePresetsModel : Device
{
public delegate void PresetRecalledCallback(ISetTopBoxNumericKeypad device, string channel);
public int PulseTime { get; set; }
public int DigitSpacingMS { get; set; }
public bool PresetsAreLoaded { get; private set; }
public delegate void PresetsSavedCallback(List<PresetChannel> presets);
public List<PresetChannel> PresetsList { get { return _PresetsList.ToList(); } }
List<PresetChannel> _PresetsList;
public int Count { get { return PresetsList != null ? PresetsList.Count : 0; } }
private readonly CCriticalSection _fileOps = new CCriticalSection();
private readonly bool _initSuccess;
public bool UseLocalImageStorage { get; set; }
public string ImagesLocalHostPrefix { get; set; }
public string ImagesPathPrefix { get; set; }
public string ListPathPrefix { get; set; }
private readonly ISetTopBoxNumericKeypad _setTopBox;
/// <summary>
/// The methods on the STB device to call when dialing
/// </summary>
Dictionary<char, Action<bool>> DialFunctions;
Action<bool> EnterFunction;
/// <summary>
/// The methods on the STB device to call when dialing
/// </summary>
private Dictionary<char, Action<bool>> _dialFunctions;
bool DialIsRunning;
string FilePath;
bool InitSuccess;
//SSMono.IO.FileSystemWatcher ListWatcher;
private bool _dialIsRunning;
private Action<bool> _enterFunction;
private string _filePath;
public DevicePresetsModel(string key, ISetTopBoxNumericKeypad setTopBox, string fileName)
: base(key)
{
PulseTime = 150;
DigitSpacingMS = 150;
public DevicePresetsModel(string key, ISetTopBoxNumericKeypad setTopBox, string fileName)
: this(key, fileName)
{
try
{
_setTopBox = setTopBox;
try
{
// Grab the digit functions from the device
// If any fail, the whole thing fails peacefully
DialFunctions = new Dictionary<char, Action<bool>>(10)
{
{ '1', setTopBox.Digit1 },
{ '2', setTopBox.Digit2 },
{ '3', setTopBox.Digit3 },
{ '4', setTopBox.Digit4 },
{ '5', setTopBox.Digit5 },
{ '6', setTopBox.Digit6 },
{ '7', setTopBox.Digit7 },
{ '8', setTopBox.Digit8 },
{ '9', setTopBox.Digit9 },
{ '0', setTopBox.Digit0 },
{ '-', setTopBox.Dash }
};
}
catch
{
Debug.Console(0, "DevicePresets '{0}', not attached to INumericKeypad device. Ignoring", key);
DialFunctions = null;
return;
}
// Grab the digit functions from the device
// If any fail, the whole thing fails peacefully
_dialFunctions = new Dictionary<char, Action<bool>>(10)
{
{'1', setTopBox.Digit1},
{'2', setTopBox.Digit2},
{'3', setTopBox.Digit3},
{'4', setTopBox.Digit4},
{'5', setTopBox.Digit5},
{'6', setTopBox.Digit6},
{'7', setTopBox.Digit7},
{'8', setTopBox.Digit8},
{'9', setTopBox.Digit9},
{'0', setTopBox.Digit0},
{'-', setTopBox.Dash}
};
}
catch
{
Debug.Console(0, "DevicePresets '{0}', not attached to INumericKeypad device. Ignoring", key);
_dialFunctions = null;
return;
}
EnterFunction = setTopBox.KeypadEnter;
_enterFunction = setTopBox.KeypadEnter;
}
UseLocalImageStorage = true;
public DevicePresetsModel(string key, string fileName) : base(key)
{
PulseTime = 150;
DigitSpacingMs = 150;
ImagesLocalHostPrefix = "http://" + CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS,0);
ImagesPathPrefix = @"/presets/images.zip/";
ListPathPrefix = @"/html/presets/lists/";
UseLocalImageStorage = true;
SetFileName(fileName);
ImagesLocalHostPrefix = "http://" + CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
ImagesPathPrefix = @"/presets/images.zip/";
ListPathPrefix = @"/html/presets/lists/";
//ListWatcher = new FileSystemWatcher(@"\HTML\presets\lists");
//ListWatcher.NotifyFilter = NotifyFilters.LastWrite;
//ListWatcher.EnableRaisingEvents = true;
//ListWatcher.Changed += ListWatcher_Changed;
InitSuccess = true;
}
SetFileName(fileName);
_initSuccess = true;
}
public event PresetRecalledCallback PresetRecalled;
public event PresetsSavedCallback PresetsSaved;
public int PulseTime { get; set; }
public int DigitSpacingMs { get; set; }
public bool PresetsAreLoaded { get; private set; }
public List<PresetChannel> PresetsList { get; private set; }
public int Count
{
get { return PresetsList != null ? PresetsList.Count : 0; }
}
public bool UseLocalImageStorage { get; set; }
public string ImagesLocalHostPrefix { get; set; }
public string ImagesPathPrefix { get; set; }
public string ListPathPrefix { get; set; }
public event EventHandler PresetsLoaded;
public void SetFileName(string path)
{
FilePath = ListPathPrefix + path;
LoadChannels();
}
public void SetFileName(string path)
{
_filePath = ListPathPrefix + path;
public void LoadChannels()
{
PresetsAreLoaded = false;
try
{
var pl = JsonConvert.DeserializeObject<PresetsList>(Crestron.SimplSharp.CrestronIO.File.ReadToEnd(FilePath, Encoding.ASCII));
Name = pl.Name;
_PresetsList = pl.Channels;
}
catch (Exception e)
{
Debug.Console(2, this, "LoadChannels: Error reading presets file. These presets will be empty:\r '{0}'\r Error:{1}", FilePath, e.Message);
// Just save a default empty list
_PresetsList = new List<PresetChannel>();
}
PresetsAreLoaded = true;
Debug.Console(2, this, "Setting presets file path to {0}", _filePath);
LoadChannels();
}
var handler = PresetsLoaded;
if (handler != null)
handler(this, EventArgs.Empty);
}
public void LoadChannels()
{
try
{
_fileOps.Enter();
public void Dial(int presetNum)
{
if (presetNum <= _PresetsList.Count)
Dial(_PresetsList[presetNum - 1].Channel);
}
Debug.Console(2, this, "Loading presets from {0}", _filePath);
PresetsAreLoaded = false;
try
{
var pl = JsonConvert.DeserializeObject<PresetsList>(File.ReadToEnd(_filePath, Encoding.ASCII));
Name = pl.Name;
PresetsList = pl.Channels;
}
catch (Exception e)
{
Debug.Console(2, this,
"LoadChannels: Error reading presets file. These presets will be empty:\r '{0}'\r Error:{1}",
_filePath, e.Message);
// Just save a default empty list
PresetsList = new List<PresetChannel>();
}
PresetsAreLoaded = true;
public void Dial(string chanNum)
{
if (DialIsRunning || !InitSuccess) return;
if (DialFunctions == null)
{
Debug.Console(1, "DevicePresets '{0}', not attached to keypad device. Ignoring channel", Key);
return;
}
var handler = PresetsLoaded;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
finally
{
_fileOps.Leave();
}
}
DialIsRunning = true;
CrestronInvoke.BeginInvoke(o =>
{
foreach (var c in chanNum.ToCharArray())
{
if (DialFunctions.ContainsKey(c))
Pulse(DialFunctions[c]);
CrestronEnvironment.Sleep(DigitSpacingMS);
}
public void Dial(int presetNum)
{
if (presetNum <= PresetsList.Count)
{
Dial(PresetsList[presetNum - 1].Channel);
}
}
if (EnterFunction != null)
Pulse(EnterFunction);
DialIsRunning = false;
});
}
public void Dial(string chanNum)
{
if (_dialIsRunning || !_initSuccess)
{
return;
}
if (_dialFunctions == null)
{
Debug.Console(1, "DevicePresets '{0}', not attached to keypad device. Ignoring channel", Key);
return;
}
void Pulse(Action<bool> act)
{
act(true);
CrestronEnvironment.Sleep(PulseTime);
act(false);
}
_dialIsRunning = true;
CrestronInvoke.BeginInvoke(o =>
{
foreach (var c in chanNum.ToCharArray())
{
if (_dialFunctions.ContainsKey(c))
{
Pulse(_dialFunctions[c]);
}
CrestronEnvironment.Sleep(DigitSpacingMs);
}
/// <summary>
/// Event handler for filesystem watcher. When directory changes, this is called
/// </summary>
//void ListWatcher_Changed(object sender, FileSystemEventArgs e)
//{
// Debug.Console(1, this, "folder modified: {0}", e.FullPath);
// if (e.FullPath.Equals(FilePath, StringComparison.OrdinalIgnoreCase))
// {
// Debug.Console(1, this, "File changed: {0}", e.ChangeType);
// LoadChannels();
// }
//}
}
if (_enterFunction != null)
{
Pulse(_enterFunction);
}
_dialIsRunning = false;
});
if (_setTopBox == null) return;
OnPresetRecalled(_setTopBox, chanNum);
}
public void Dial(int presetNum, ISetTopBoxNumericKeypad setTopBox)
{
if (presetNum <= PresetsList.Count)
{
Dial(PresetsList[presetNum - 1].Channel, setTopBox);
}
}
public void Dial(string chanNum, ISetTopBoxNumericKeypad setTopBox)
{
_dialFunctions = new Dictionary<char, Action<bool>>(10)
{
{'1', setTopBox.Digit1},
{'2', setTopBox.Digit2},
{'3', setTopBox.Digit3},
{'4', setTopBox.Digit4},
{'5', setTopBox.Digit5},
{'6', setTopBox.Digit6},
{'7', setTopBox.Digit7},
{'8', setTopBox.Digit8},
{'9', setTopBox.Digit9},
{'0', setTopBox.Digit0},
{'-', setTopBox.Dash}
};
_enterFunction = setTopBox.KeypadEnter;
OnPresetRecalled(setTopBox, chanNum);
Dial(chanNum);
}
private void OnPresetRecalled(ISetTopBoxNumericKeypad setTopBox, string channel)
{
var handler = PresetRecalled;
if (handler == null)
{
return;
}
handler(setTopBox, channel);
}
public void UpdatePreset(int index, PresetChannel preset)
{
if (index >= PresetsList.Count)
{
return;
}
PresetsList[index] = preset;
SavePresets();
OnPresetsSaved();
}
public void UpdatePresets(List<PresetChannel> presets)
{
PresetsList = presets;
SavePresets();
OnPresetsSaved();
}
private void SavePresets()
{
try
{
_fileOps.Enter();
var json = JsonConvert.SerializeObject(PresetsList);
using (var file = File.Open(_filePath, FileMode.Truncate))
{
file.Write(json, Encoding.UTF8);
}
}
finally
{
_fileOps.Leave();
}
}
private void OnPresetsSaved()
{
var handler = PresetsSaved;
if (handler == null) return;
handler(PresetsList);
}
private void Pulse(Action<bool> act)
{
act(true);
CrestronEnvironment.Sleep(PulseTime);
act(false);
}
}
}

View File

@@ -10,19 +10,22 @@ namespace PepperDash.Essentials.Core.Presets
public class PresetChannel
{
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always,PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always, PropertyName = "iconUrl")]
public string IconUrl { get; set; }
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always, PropertyName = "channel")]
public string Channel { get; set; }
}
public class PresetsList
{
[JsonProperty(Required=Required.Always)]
[JsonProperty(Required=Required.Always,PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(Required = Required.Always)]
[JsonProperty(Required = Required.Always, PropertyName = "channels")]
public List<PresetChannel> Channels { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
using System.Collections.Generic;
using Crestron.SimplSharp.Scheduler;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsRoomScheduledEventsConfig
{
[JsonProperty("scheduledEvents")]
public List<ScheduledEventConfig> ScheduledEvents;
}
public class ScheduledEventConfig
{
[JsonProperty("key")]
public string Key;
[JsonProperty("name")]
public string Name;
[JsonProperty("days")]
public ScheduledEventCommon.eWeekDays Days;
[JsonProperty("time")]
public string Time;
[JsonProperty("actions")]
public List<DeviceActionWrapper> Actions;
[JsonProperty("persistent")]
public bool Persistent;
[JsonProperty("acknowledgeable")]
public bool Acknowledgeable;
[JsonProperty("enable")]
public bool Enable;
}
}

View File

@@ -41,6 +41,14 @@ namespace PepperDash.Essentials.Core
}
/// <summary>
/// Simplified routing direct from source to destination
/// </summary>
public interface IRunDirectRouteAction
{
void RunDirectRoute(string sourceKey, string destinationKey);
}
/// <summary>
/// For rooms that default presentation only routing
/// </summary>

View File

@@ -49,7 +49,9 @@ namespace PepperDash.Essentials.DM
public BoolFeedback EnableAudioBreakawayFeedback { get; private set; }
public BoolFeedback EnableUsbBreakawayFeedback { get; private set; }
public Dictionary<uint, IntFeedback> InputCardHdcpStateFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> InputCardHdcpStateFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> InputStreamCardStateFeedbacks { get; private set; }
public Dictionary<uint, IntFeedback> OutputStreamCardStateFeedbacks { get; private set; }
public Dictionary<uint, eHdcpCapabilityType> InputCardHdcpCapabilityTypes { get; private set; }
@@ -223,7 +225,9 @@ namespace PepperDash.Essentials.DM
EnableUsbBreakawayFeedback =
new BoolFeedback(() => (Chassis as DmMDMnxn).EnableUSBBreakawayFeedback.BoolValue);
InputCardHdcpStateFeedbacks = new Dictionary<uint, IntFeedback>();
InputCardHdcpStateFeedbacks = new Dictionary<uint, IntFeedback>();
InputStreamCardStateFeedbacks = new Dictionary<uint, IntFeedback>();
OutputStreamCardStateFeedbacks = new Dictionary<uint, IntFeedback>();
InputCardHdcpCapabilityTypes = new Dictionary<uint, eHdcpCapabilityType>();
for (uint x = 1; x <= Chassis.NumberOfOutputs; x++)
@@ -307,6 +311,33 @@ namespace PepperDash.Essentials.DM
// return hdMdNxMHdmiOutput.HdmiOutputPort.DisabledByHdcpFeedback.BoolValue;
return false;
});
OutputStreamCardStateFeedbacks[tempX] = new IntFeedback(() =>
{
try
{
var outputCard = Chassis.Outputs[tempX];
if (outputCard.Card is DmcStroAV)
{
Debug.Console(2, "Found output stream card in slot: {0}.", tempX);
var streamCard = outputCard.Card as DmcStroAV;
if (streamCard.Control.StartFeedback.BoolValue == true)
return 1;
else if (streamCard.Control.StopFeedback.BoolValue == true)
return 2;
else if (streamCard.Control.PauseFeedback.BoolValue == true)
return 3;
else
return 0;
}
return 0;
}
catch (InvalidOperationException iopex)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "Error adding output stream card in slot: {0}. Error: {1}", tempX, iopex);
return 0;
}
});
}
@@ -406,6 +437,33 @@ namespace PepperDash.Essentials.DM
Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "The Input Card in slot: {0} supports HDCP 2. Please update the configuration value in the inputCardSupportsHdcp2 object to true. Error: {1}", tempX, iopex);
return 0;
}
});
InputStreamCardStateFeedbacks[tempX] = new IntFeedback(() =>
{
try
{
var inputCard = Chassis.Inputs[tempX];
if (inputCard.Card is DmcStr)
{
Debug.Console(2, "Found input stream card in slot: {0}.", tempX);
var streamCard = inputCard.Card as DmcStr;
if (streamCard.Control.StartFeedback.BoolValue == true)
return 1;
else if (streamCard.Control.StopFeedback.BoolValue == true)
return 2;
else if (streamCard.Control.PauseFeedback.BoolValue == true)
return 3;
else
return 0;
}
return 0;
}
catch (InvalidOperationException iopex)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning, "Error adding input stream card in slot: {0}. Error: {1}", tempX, iopex);
return 0;
}
});
}
}
@@ -915,6 +973,19 @@ namespace PepperDash.Essentials.DM
else
Debug.Console(1, this, "No index of {0} found in InputCardHdcpCapabilityFeedbacks");
break;
}
case DMInputEventIds.StartEventId:
case DMInputEventIds.StopEventId:
case DMInputEventIds.PauseEventId:
{
Debug.Console(2, this, "DM Input {0} Stream Status EventId", args.Number);
if (InputStreamCardStateFeedbacks[args.Number] != null)
{
InputStreamCardStateFeedbacks[args.Number].FireUpdate();
}
else
Debug.Console(2, this, "No index of {0} found in InputStreamCardStateFeedbacks");
break;
}
default:
{
@@ -1043,6 +1114,19 @@ namespace PepperDash.Essentials.DM
Debug.Console(2, this, "DM Output {0} DisabledByHdcpEventId", args.Number);
OutputDisabledByHdcpFeedbacks[args.Number].FireUpdate();
break;
}
case DMOutputEventIds.StartEventId:
case DMOutputEventIds.StopEventId:
case DMOutputEventIds.PauseEventId:
{
Debug.Console(2, this, "DM Output {0} Stream Status EventId", args.Number);
if (OutputStreamCardStateFeedbacks[args.Number] != null)
{
OutputStreamCardStateFeedbacks[args.Number].FireUpdate();
}
else
Debug.Console(2, this, "No index of {0} found in OutputStreamCardStateFeedbacks");
break;
}
default:
{
@@ -1242,13 +1326,16 @@ namespace PepperDash.Essentials.DM
}
else
{
LinkHdmiInputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
if (RxDictionary.ContainsKey(ioSlot))
{
LinkRxToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
LinkHdmiInputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
LinkStreamInputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
if (RxDictionary.ContainsKey(ioSlot))
{
LinkRxToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
else
LinkStreamOutputToApi(trilist, ioSlot, joinMap, ioSlotJoin);
}
}
@@ -1295,6 +1382,86 @@ namespace PepperDash.Essentials.DM
{
trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber + ioSlotJoin].UShortValue = 1;
}
}
private void LinkStreamInputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)
{
var inputPort = InputPorts[string.Format("inputCard{0}--streamIn", ioSlot)];
if (inputPort == null)
{
return;
}
var streamCard = Chassis.Inputs[ioSlot].Card as DmcStr;
var join = joinMap.InputStreamCardState.JoinNumber + ioSlotJoin;
Debug.Console(1, "Port value for input card {0} is set as a stream card", ioSlot);
trilist.SetUShortSigAction(join, s =>
{
if (s == 1)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to start", join, s);
streamCard.Control.Start();
}
else if (s == 2)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to stop", join, s);
streamCard.Control.Stop();
}
else if (s == 3)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to pause", join, s);
streamCard.Control.Pause();
}
else
{
Debug.Console(2, this, "Join {0} value {1}: Ignore stream state", join, s);
}
});
InputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]);
trilist.UShortInput[join].UShortValue = InputStreamCardStateFeedbacks[ioSlot].UShortValue;
}
private void LinkStreamOutputToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)
{
var outputPort = OutputPorts[string.Format("outputCard{0}--streamOut", ioSlot)];
if (outputPort == null)
{
return;
}
var streamCard = Chassis.Outputs[ioSlot].Card as DmcStroAV;
var join = joinMap.OutputStreamCardState.JoinNumber + ioSlotJoin;
Debug.Console(1, "Port value for output card {0} is set as a stream card", ioSlot);
trilist.SetUShortSigAction(join, s =>
{
if (s == 1)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to start", join, s);
streamCard.Control.Start();
}
else if (s == 2)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to stop", join, s);
streamCard.Control.Stop();
}
else if (s == 3)
{
Debug.Console(2, this, "Join {0} value {1}: Setting stream state to pause", join, s);
streamCard.Control.Pause();
}
else
{
Debug.Console(2, this, "Join {0} value {1}: Ignore stream state", join, s);
}
});
OutputStreamCardStateFeedbacks[ioSlot].LinkInputSig(trilist.UShortInput[join]);
trilist.UShortInput[join].UShortValue = OutputStreamCardStateFeedbacks[ioSlot].UShortValue;
}
private void LinkRxToApi(BasicTriList trilist, uint ioSlot, DmChassisControllerJoinMap joinMap, uint ioSlotJoin)

View File

@@ -516,12 +516,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Cisco
SendText("xconfiguration userinterface custommessage: \"Scan the QR code with a mobile phone to get started\"");
SendText("xconfiguration userinterface osd halfwakemessage: \"Tap the touch panel or scan the QR code with a mobile phone to get started\"");
var checksum = !String.IsNullOrEmpty(mcBridge.QrCodeChecksum)
? String.Format("checksum: {0} ", mcBridge.QrCodeChecksum)
: String.Empty;
SendText(String.Format(
"xcommand userinterface branding fetch type: branding url: {0}",
mcBridge.QrCodeUrl));
"xcommand userinterface branding fetch {1}type: branding url: {0}",
mcBridge.QrCodeUrl, checksum));
SendText(String.Format(
"xcommand userinterface branding fetch type: halfwakebranding url: {0}",
mcBridge.QrCodeUrl));
"xcommand userinterface branding fetch {1}type: halfwakebranding url: {0}",
mcBridge.QrCodeUrl, checksum));
}
private void SendBrandingUrl()