Compare commits

..

25 Commits

Author SHA1 Message Date
Neil Dorin
59bfa354e4 feat(essentials): switches to userId argument 2021-11-04 16:15:59 -06:00
Neil Dorin
536e82ef22 feat(essentials): adds new features for ZoomRoom
Adds IHasMeetingLock and adds new methods to IHasParticipants
2021-11-04 16:11:26 -06:00
Andrew Welker
63cd322fd0 Merge pull request #858 from PepperDash/hotfix/add-logging-if-no-defaultAudioDevice-set
Adds more deliberate exception and logging for missing `defaultAudioKey` property value
2021-11-03 16:35:52 -06:00
Andrew Welker
489ba2da04 Merge branch 'main' into hotfix/add-logging-if-no-defaultAudioDevice-set 2021-11-03 14:56:27 -06:00
Neil Dorin
8087aa7a75 Adds more deliberate exception and logging for missing defaultAudioKey property value 2021-11-03 14:48:10 -06:00
Neil Dorin
a8d0dfb327 Merge pull request #852 from PepperDash/hotfix/dm-usb-routing
Hotfix/dm usb routing
2021-10-27 10:39:17 -06:00
Andrew Welker
cef9e0a9a6 Update UsbOutput routing 2021-10-27 07:46:50 -06:00
Andrew Welker
16369e31cf fix USB routing 2021-10-27 07:46:50 -06:00
Andrew Welker
38959414ff Fix USB Routing issue 2021-10-27 07:46:50 -06:00
Neil Dorin
bc3247297e Merge pull request #846 from PepperDash/hotfix/zoom-meetings-simpl 2021-10-07 12:48:32 -06:00
Andrew Welker
f7bf728263 fix(Devices_Common): Clear meeting list and fire event if no meetings are scheduled 2021-10-07 09:48:02 -06:00
Neil Dorin
025bf7adfb Merge pull request #840 from PepperDash/hotfix/PD-Core-update-initialize
Implement Initialize Method & Update PD Core
2021-09-28 13:09:25 -06:00
Andrew Welker
a6430a7bfe chore: Update PD Core to 1.1.0 2021-09-28 11:05:05 -06:00
Andrew Welker
b71c83bac0 feat: Update some internal Essentials devices to use Initialize method 2021-09-28 10:56:25 -06:00
Andrew Welker
5940ec17c2 feat: Add method call to constructor for EssentialsDevice 2021-09-28 10:56:24 -06:00
Andrew Welker
10445508b2 feat: Update Essentials Device to call Initialize method 2021-09-28 10:56:24 -06:00
Andrew Welker
66ecf43508 chore: Update PD Core to 1.0.48 2021-09-28 10:56:23 -06:00
Andrew Welker
77c4272219 Merge pull request #834 from PepperDash/hotfix/hd-md-outputname
Hotfix/hd md outputname
2021-09-21 15:47:20 -06:00
Andrew Welker
d78a378859 Merge branch 'main' into hotfix/hd-md-outputname 2021-09-21 15:21:47 -06:00
Jason DeVito
eec4484f78 fix: updates to resolve issues with routing and feedbacks in the HdMdNxM4kEBridgeableController class. 2021-09-21 16:11:13 -05:00
Andrew Welker
49e82f107b fix(Essentials_DM): Updates to try and fix some exceptions 2021-09-21 12:06:22 -06:00
Neil Dorin
c5162fb94d Merge pull request #831 from PepperDash/hotfix/dm-resolution-issues
DM Input Resolution not reporting over bridge
2021-09-21 10:32:45 -06:00
Andrew Welker
70d63a9f99 chore: Mark non-bridgeable class obsolete
Also add a debug message to give the new type to use.
2021-09-20 15:52:40 -06:00
Andrew Welker
30f63eee03 fix: Remove reference to DMOutput name sig
the HD-MD series of switchers appears to not populate the Name sig of the DMOutput, leading to a NullSig exception when attempting to set output names. This is probably because those names can't be set on the device itself, but some experimentation with hardware may be required to determine that completely.
2021-09-20 15:52:40 -06:00
Jason DeVito
9f1c512909 Updates to HdMdNxM4kEController.cs to implement regex pattern in place of substring on input definitions. Updated HdMdNxM4kEBridgeableController.cs to handle exception when constructing the device. 2021-09-20 15:52:39 -06:00
33 changed files with 1208 additions and 1851 deletions

View File

@@ -450,13 +450,14 @@ namespace PepperDash.Essentials
return;
}
uint fusionIpId = 0xf1;
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
{
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom;
if (room != null)
{
// default IPID
uint fusionIpId = 0xf1;
// default to no join map key
string fusionJoinMapKey = string.Empty;
@@ -477,7 +478,7 @@ namespace PepperDash.Essentials
{
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
@@ -489,7 +490,7 @@ namespace PepperDash.Essentials
{
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge...");
@@ -501,7 +502,7 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion");
DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey));
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
@@ -514,13 +515,9 @@ namespace PepperDash.Essentials
DeviceManager.AddDevice(room);
}
fusionIpId += 1;
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
}
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");

View File

@@ -150,7 +150,7 @@ namespace PepperDash.Essentials.Fusion
protected override void CreateSymbolAndBasicSigs(uint ipId)
{
Debug.Console(0, this, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId);
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();

View File

@@ -149,8 +149,7 @@
<Compile Include="Room\Types\EssentialsNDisplayRoomBase.cs" />
<Compile Include="Room\Config\EssentialsRoomConfig.cs" />
<Compile Include="Room\Types\EssentialsTechRoom.cs" />
<Compile Include="Room\Types\Interfaces\IEssentialsHuddleSpaceRoom.cs" />
<Compile Include="Room\Types\Interfaces\IEssentialsHuddleVtc1Room.cs" />
<Compile Include="Room\Types\IEssentialsHuddleSpaceRoom.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />

View File

@@ -214,17 +214,25 @@ namespace PepperDash.Essentials
VideoCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.VideoCodecKey) as
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
if (VideoCodec == null)
throw new ArgumentNullException("codec cannot be null");
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "No Video Codec set. Please check 'videoCodecKey' property in room config");
throw new ArgumentNullException("VideoCodec cannot be null");
}
AudioCodec = DeviceManager.GetDeviceForKey(PropertiesConfig.AudioCodecKey) as
PepperDash.Essentials.Devices.Common.AudioCodec.AudioCodecBase;
if (AudioCodec == null)
Debug.Console(0, this, "No Audio Codec Found");
DefaultAudioDevice = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultAudioKey) as IBasicVolumeControls;
if (DefaultAudioDevice == null)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "No Default Audio Device set. Please check 'defaultAudioKey' property in room config");
throw new ArgumentNullException("DefaultAudioDevice cannot be null");
}
InitializeRoom();
}

View File

@@ -1,24 +0,0 @@
using System;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay
{
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
IBasicVolumeControls CurrentVolumeControls { get; }
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
}
}

View File

@@ -1,25 +0,0 @@
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials
{
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }
new BoolFeedback InCallFeedback { get; }
new BoolFeedback PrivacyModeIsOnFeedback { get; }
string DefaultCodecRouteString { get; }
}
}

View File

@@ -1,326 +1,326 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Displays;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.UIDrivers
{
public class EssentialsHuddleTechPageDriver : PanelDriverBase
{
/// <summary>
///
/// </summary>
SmartObjectDynamicList MenuList;
/// <summary>
///
/// </summary>
SubpageReferenceList StatusList;
/// <summary>
/// The list of display controls
/// </summary>
SubpageReferenceList DisplayList;
/// <summary>
/// References lines in the list against device instances
/// </summary>
Dictionary<ICommunicationMonitor, uint> StatusListDeviceIndexes;
/// <summary>
///
/// </summary>
JoinedSigInterlock PagesInterlock;
/// <summary>
/// 1
/// </summary>
public const uint JoinText = 1;
CTimer PinAuthorizedTimer;
EssentialsRoomTechConfig Config;
StringBuilder PinEntryBuilder = new StringBuilder(4);
bool IsAuthorized;
SmartObjectNumeric PinKeypad;
/// <summary>
///
/// </summary>
/// <param name="trilist"></param>
/// <param name="parent"></param>
public EssentialsHuddleTechPageDriver(BasicTriListWithSmartObject trilist, EssentialsRoomTechConfig config)
: base(trilist)
{
Config = config;
PagesInterlock = new JoinedSigInterlock(trilist);
PagesInterlock.SetButDontShow(UIBoolJoin.TechSystemStatusVisible);
trilist.SetSigFalseAction(UIBoolJoin.TechExitButton, Hide);
MenuList = new SmartObjectDynamicList(trilist.SmartObjects[UISmartObjectJoin.TechMenuList],
true, 3100);
MenuList.SetFeedback(1, true); // initial fb
ushort count = 0;
MenuList.SetItemMainText(1, "System Status");
MenuList.SetItemButtonAction(1, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechSystemStatusVisible);
MenuList.SetFeedback(1, true);
});
MenuList.SetItemMainText(2, "Display Controls");
MenuList.SetItemButtonAction(2, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechDisplayControlsVisible);
MenuList.SetFeedback(2, true);
});
count = 2;
// Don't show panel setup on iPad or xpanel
if (TriList is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
{
count++;
MenuList.SetItemMainText(count, "Panel Setup");
MenuList.SetItemButtonAction(count, b =>
{
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechPanelSetupVisible);
MenuList.SetFeedback(count, true);
});
}
MenuList.Count = count;
BuildStatusList();
BuildDisplayList();
SetupPinModal();
}
/// <summary>
///
/// </summary>
public override void Show()
{
// divert to PIN if we need auth
if (IsAuthorized)
{
// Cancel the auth timer so we don't deauth after coming back in
if (PinAuthorizedTimer != null)
PinAuthorizedTimer.Stop();
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, true);
PagesInterlock.Show();
base.Show();
}
else
{
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, true);
}
}
/// <summary>
///
/// </summary>
public override void Hide()
{
// Leave it authorized for 60 seconds.
if (IsAuthorized)
PinAuthorizedTimer = new CTimer(o => {
IsAuthorized = false;
PinAuthorizedTimer = null;
}, 60000);
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, false);
PagesInterlock.Hide();
base.Hide();
}
/// <summary>
/// Wire up the keypad and buttons
/// </summary>
void SetupPinModal()
{
TriList.SetSigFalseAction(UIBoolJoin.PinDialogCancelPress, CancelPinDialog);
PinKeypad = new SmartObjectNumeric(TriList.SmartObjects[UISmartObjectJoin.TechPinDialogKeypad], true);
PinKeypad.Digit0.UserObject = new Action<bool>(b => { if (b)DialPinDigit('0'); });
PinKeypad.Digit1.UserObject = new Action<bool>(b => { if (b)DialPinDigit('1'); });
PinKeypad.Digit2.UserObject = new Action<bool>(b => { if (b)DialPinDigit('2'); });
PinKeypad.Digit3.UserObject = new Action<bool>(b => { if (b)DialPinDigit('3'); });
PinKeypad.Digit4.UserObject = new Action<bool>(b => { if (b)DialPinDigit('4'); });
PinKeypad.Digit5.UserObject = new Action<bool>(b => { if (b)DialPinDigit('5'); });
PinKeypad.Digit6.UserObject = new Action<bool>(b => { if (b)DialPinDigit('6'); });
PinKeypad.Digit7.UserObject = new Action<bool>(b => { if (b)DialPinDigit('7'); });
PinKeypad.Digit8.UserObject = new Action<bool>(b => { if (b)DialPinDigit('8'); });
PinKeypad.Digit9.UserObject = new Action<bool>(b => { if (b)DialPinDigit('9'); });
}
/// <summary>
///
/// </summary>
/// <param name="d"></param>
void DialPinDigit(char d)
{
PinEntryBuilder.Append(d);
var len = PinEntryBuilder.Length;
SetPinDotsFeedback(len);
// check it!
if (len == 4)
{
if (Config.Password == PinEntryBuilder.ToString())
{
IsAuthorized = true;
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
Show();
}
else
{
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, true);
new CTimer(o =>
{
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, false);
}, 1500);
}
PinEntryBuilder.Remove(0, len); // clear it either way
}
}
/// <summary>
/// Draws the dots as pin is entered
/// </summary>
/// <param name="len"></param>
void SetPinDotsFeedback(int len)
{
TriList.SetBool(UIBoolJoin.PinDialogDot1, len >= 1);
TriList.SetBool(UIBoolJoin.PinDialogDot2, len >= 2);
TriList.SetBool(UIBoolJoin.PinDialogDot3, len >= 3);
TriList.SetBool(UIBoolJoin.PinDialogDot4, len == 4);
}
/// <summary>
/// Does what it says
/// </summary>
void CancelPinDialog()
{
PinEntryBuilder.Remove(0, PinEntryBuilder.Length);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
}
/// <summary>
///
/// </summary>
void BuildStatusList()
{
StatusList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechStatusList, 3, 3, 3);
StatusListDeviceIndexes = new Dictionary<ICommunicationMonitor, uint>();
uint i = 0;
foreach (var d in DeviceManager.AllDevices)
{
// make sure it is both ICommunicationMonitor and a Device
var sd = d as ICommunicationMonitor;
if (sd == null)
continue;
var dd = sd as Device;
if(dd == null)
continue;
i++;
StatusList.StringInputSig(i, 1).StringValue = dd.Name;
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)sd.CommunicationMonitor.Status;
StatusListDeviceIndexes.Add(sd, i);
sd.CommunicationMonitor.StatusChange += CommunicationMonitor_StatusChange ;
}
StatusList.Count = (ushort)i;
}
/// <summary>
/// Builds the list of display controls
/// </summary>
void BuildDisplayList()
{
DisplayList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechDisplayControlsList, 10, 3, 3);
var devKeys = ConfigReader.ConfigObject.Devices.Where(d =>
d.Group.Equals("display", StringComparison.OrdinalIgnoreCase)
|| d.Group.Equals("projector", StringComparison.OrdinalIgnoreCase))
.Select(dd => dd.Key);
var disps = DeviceManager.AllDevices.Where(d =>
devKeys.Contains(d.Key));
ushort i = 0;
foreach (var disp in disps)
{
var display = disp as DisplayBase;
if (display != null)
{
i++;
DisplayList.StringInputSig(i, 1).StringValue = display.Name;
DisplayList.GetBoolFeedbackSig(i, 1).SetSigFalseAction(display.PowerOn);
DisplayList.GetBoolFeedbackSig(i, 2).SetSigFalseAction(display.PowerOff);
if (display is TwoWayDisplayBase)
{
var powerOnSig = DisplayList.BoolInputSig(i, 1);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkInputSig(powerOnSig);
var powerOffSig = DisplayList.BoolInputSig(1, 2);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkComplementInputSig(powerOffSig);
}
DisplayList.GetBoolFeedbackSig(i, 3).SetSigFalseAction(() =>
{ if (display is IInputHdmi1) (display as IInputHdmi1).InputHdmi1(); });
DisplayList.GetBoolFeedbackSig(i, 4).SetSigFalseAction(() =>
{ if (display is IInputHdmi2) (display as IInputHdmi2).InputHdmi2(); });
DisplayList.GetBoolFeedbackSig(i, 5).SetSigFalseAction(() =>
{ if (display is IInputHdmi3) (display as IInputHdmi3).InputHdmi3(); });
//DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
//{ if (display is IInputHdmi4) (display as IInputHdmi4).InputHdmi4(); });
DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
{ if (display is IInputDisplayPort1) (display as IInputDisplayPort1).InputDisplayPort1(); });
// Figure out some way to provide current input feedback
if (display is TwoWayDisplayBase)
{
(display as TwoWayDisplayBase).CurrentInputFeedback.OutputChange += CurrentInputFeedback_OutputChange;
}
}
}
DisplayList.Count = i;
}
void CurrentInputFeedback_OutputChange(object sender, EventArgs e)
{
}
/// <summary>
///
/// </summary>
void CommunicationMonitor_StatusChange(object sender, MonitorStatusChangeEventArgs e)
{
var c = sender as ICommunicationMonitor;
if (c != null && StatusListDeviceIndexes.ContainsKey(c))
{
var i = StatusListDeviceIndexes[c];
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
using PepperDash.Essentials;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Displays;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.UIDrivers
{
public class EssentialsHuddleTechPageDriver : PanelDriverBase
{
/// <summary>
///
/// </summary>
SmartObjectDynamicList MenuList;
/// <summary>
///
/// </summary>
SubpageReferenceList StatusList;
/// <summary>
/// The list of display controls
/// </summary>
SubpageReferenceList DisplayList;
/// <summary>
/// References lines in the list against device instances
/// </summary>
Dictionary<ICommunicationMonitor, uint> StatusListDeviceIndexes;
/// <summary>
///
/// </summary>
JoinedSigInterlock PagesInterlock;
/// <summary>
/// 1
/// </summary>
public const uint JoinText = 1;
CTimer PinAuthorizedTimer;
EssentialsRoomTechConfig Config;
StringBuilder PinEntryBuilder = new StringBuilder(4);
bool IsAuthorized;
SmartObjectNumeric PinKeypad;
/// <summary>
///
/// </summary>
/// <param name="trilist"></param>
/// <param name="parent"></param>
public EssentialsHuddleTechPageDriver(BasicTriListWithSmartObject trilist, EssentialsRoomTechConfig config)
: base(trilist)
{
Config = config;
PagesInterlock = new JoinedSigInterlock(trilist);
PagesInterlock.SetButDontShow(UIBoolJoin.TechSystemStatusVisible);
trilist.SetSigFalseAction(UIBoolJoin.TechExitButton, Hide);
MenuList = new SmartObjectDynamicList(trilist.SmartObjects[UISmartObjectJoin.TechMenuList],
true, 3100);
MenuList.SetFeedback(1, true); // initial fb
ushort count = 0;
MenuList.SetItemMainText(1, "System Status");
MenuList.SetItemButtonAction(1, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechSystemStatusVisible);
MenuList.SetFeedback(1, true);
});
MenuList.SetItemMainText(2, "Display Controls");
MenuList.SetItemButtonAction(2, b => {
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechDisplayControlsVisible);
MenuList.SetFeedback(2, true);
});
count = 2;
// Don't show panel setup on iPad or xpanel
if (TriList is Crestron.SimplSharpPro.DeviceSupport.TswFt5Button)
{
count++;
MenuList.SetItemMainText(count, "Panel Setup");
MenuList.SetItemButtonAction(count, b =>
{
if (b) PagesInterlock.ShowInterlocked(UIBoolJoin.TechPanelSetupVisible);
MenuList.SetFeedback(count, true);
});
}
MenuList.Count = count;
BuildStatusList();
BuildDisplayList();
SetupPinModal();
}
/// <summary>
///
/// </summary>
public override void Show()
{
// divert to PIN if we need auth
if (IsAuthorized)
{
// Cancel the auth timer so we don't deauth after coming back in
if (PinAuthorizedTimer != null)
PinAuthorizedTimer.Stop();
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, true);
PagesInterlock.Show();
base.Show();
}
else
{
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, true);
}
}
/// <summary>
///
/// </summary>
public override void Hide()
{
// Leave it authorized for 60 seconds.
if (IsAuthorized)
PinAuthorizedTimer = new CTimer(o => {
IsAuthorized = false;
PinAuthorizedTimer = null;
}, 60000);
TriList.SetBool(UIBoolJoin.TechCommonItemsVisbible, false);
PagesInterlock.Hide();
base.Hide();
}
/// <summary>
/// Wire up the keypad and buttons
/// </summary>
void SetupPinModal()
{
TriList.SetSigFalseAction(UIBoolJoin.PinDialogCancelPress, CancelPinDialog);
PinKeypad = new SmartObjectNumeric(TriList.SmartObjects[UISmartObjectJoin.TechPinDialogKeypad], true);
PinKeypad.Digit0.UserObject = new Action<bool>(b => { if (b)DialPinDigit('0'); });
PinKeypad.Digit1.UserObject = new Action<bool>(b => { if (b)DialPinDigit('1'); });
PinKeypad.Digit2.UserObject = new Action<bool>(b => { if (b)DialPinDigit('2'); });
PinKeypad.Digit3.UserObject = new Action<bool>(b => { if (b)DialPinDigit('3'); });
PinKeypad.Digit4.UserObject = new Action<bool>(b => { if (b)DialPinDigit('4'); });
PinKeypad.Digit5.UserObject = new Action<bool>(b => { if (b)DialPinDigit('5'); });
PinKeypad.Digit6.UserObject = new Action<bool>(b => { if (b)DialPinDigit('6'); });
PinKeypad.Digit7.UserObject = new Action<bool>(b => { if (b)DialPinDigit('7'); });
PinKeypad.Digit8.UserObject = new Action<bool>(b => { if (b)DialPinDigit('8'); });
PinKeypad.Digit9.UserObject = new Action<bool>(b => { if (b)DialPinDigit('9'); });
}
/// <summary>
///
/// </summary>
/// <param name="d"></param>
void DialPinDigit(char d)
{
PinEntryBuilder.Append(d);
var len = PinEntryBuilder.Length;
SetPinDotsFeedback(len);
// check it!
if (len == 4)
{
if (Config.Password == PinEntryBuilder.ToString())
{
IsAuthorized = true;
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
Show();
}
else
{
SetPinDotsFeedback(0);
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, true);
new CTimer(o =>
{
TriList.SetBool(UIBoolJoin.PinDialogErrorVisible, false);
}, 1500);
}
PinEntryBuilder.Remove(0, len); // clear it either way
}
}
/// <summary>
/// Draws the dots as pin is entered
/// </summary>
/// <param name="len"></param>
void SetPinDotsFeedback(int len)
{
TriList.SetBool(UIBoolJoin.PinDialogDot1, len >= 1);
TriList.SetBool(UIBoolJoin.PinDialogDot2, len >= 2);
TriList.SetBool(UIBoolJoin.PinDialogDot3, len >= 3);
TriList.SetBool(UIBoolJoin.PinDialogDot4, len == 4);
}
/// <summary>
/// Does what it says
/// </summary>
void CancelPinDialog()
{
PinEntryBuilder.Remove(0, PinEntryBuilder.Length);
TriList.SetBool(UIBoolJoin.PinDialog4DigitVisible, false);
}
/// <summary>
///
/// </summary>
void BuildStatusList()
{
StatusList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechStatusList, 3, 3, 3);
StatusListDeviceIndexes = new Dictionary<ICommunicationMonitor, uint>();
uint i = 0;
foreach (var d in DeviceManager.AllDevices)
{
// make sure it is both ICommunicationMonitor and a Device
var sd = d as ICommunicationMonitor;
if (sd == null)
continue;
var dd = sd as Device;
if(dd == null)
continue;
i++;
StatusList.StringInputSig(i, 1).StringValue = dd.Name;
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)sd.CommunicationMonitor.Status;
StatusListDeviceIndexes.Add(sd, i);
sd.CommunicationMonitor.StatusChange += CommunicationMonitor_StatusChange ;
}
StatusList.Count = (ushort)i;
}
/// <summary>
/// Builds the list of display controls
/// </summary>
void BuildDisplayList()
{
DisplayList = new SubpageReferenceList(TriList, UISmartObjectJoin.TechDisplayControlsList, 10, 3, 3);
var devKeys = ConfigReader.ConfigObject.Devices.Where(d =>
d.Group.Equals("display", StringComparison.OrdinalIgnoreCase)
|| d.Group.Equals("projector", StringComparison.OrdinalIgnoreCase))
.Select(dd => dd.Key);
var disps = DeviceManager.AllDevices.Where(d =>
devKeys.Contains(d.Key));
ushort i = 0;
foreach (var disp in disps)
{
var display = disp as DisplayBase;
if (display != null)
{
i++;
DisplayList.StringInputSig(i, 1).StringValue = display.Name;
DisplayList.GetBoolFeedbackSig(i, 1).SetSigFalseAction(display.PowerOn);
DisplayList.GetBoolFeedbackSig(i, 2).SetSigFalseAction(display.PowerOff);
if (display is TwoWayDisplayBase)
{
var powerOnSig = DisplayList.BoolInputSig(i, 1);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkInputSig(powerOnSig);
var powerOffSig = DisplayList.BoolInputSig(1, 2);
(display as TwoWayDisplayBase).PowerIsOnFeedback.LinkComplementInputSig(powerOffSig);
}
DisplayList.GetBoolFeedbackSig(i, 3).SetSigFalseAction(() =>
{ if (display is IInputHdmi1) (display as IInputHdmi1).InputHdmi1(); });
DisplayList.GetBoolFeedbackSig(i, 4).SetSigFalseAction(() =>
{ if (display is IInputHdmi2) (display as IInputHdmi2).InputHdmi2(); });
DisplayList.GetBoolFeedbackSig(i, 5).SetSigFalseAction(() =>
{ if (display is IInputHdmi3) (display as IInputHdmi3).InputHdmi3(); });
//DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
//{ if (display is IInputHdmi4) (display as IInputHdmi4).InputHdmi4(); });
DisplayList.GetBoolFeedbackSig(i, 6).SetSigFalseAction(() =>
{ if (display is IInputDisplayPort1) (display as IInputDisplayPort1).InputDisplayPort1(); });
// Figure out some way to provide current input feedback
if (display is TwoWayDisplayBase)
{
(display as TwoWayDisplayBase).CurrentInputFeedback.OutputChange += CurrentInputFeedback_OutputChange;
}
}
}
DisplayList.Count = i;
}
void CurrentInputFeedback_OutputChange(object sender, EventArgs e)
{
}
/// <summary>
///
/// </summary>
void CommunicationMonitor_StatusChange(object sender, MonitorStatusChangeEventArgs e)
{
var c = sender as ICommunicationMonitor;
if (c != null && StatusListDeviceIndexes.ContainsKey(c))
{
var i = StatusListDeviceIndexes[c];
StatusList.UShortInputSig(i, 1).UShortValue = (ushort)e.Status;
}
}
}
}

View File

@@ -60,7 +60,6 @@ namespace PepperDash.Essentials.Core
DeviceCriticalSection.Enter();
AddDeviceEnabled = false;
// PreActivate all devices
Debug.Console(0,"****PreActivation starting...****");
foreach (var d in Devices.Values)
{
try
@@ -70,12 +69,9 @@ namespace PepperDash.Essentials.Core
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device {1} PreActivation failure: {0}", e.Message, d.Key);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
Debug.Console(0, d, "ERROR: Device PreActivation failure:\r{0}", e);
}
}
Debug.Console(0, "****PreActivation complete****");
Debug.Console(0, "****Activation starting...****");
// Activate all devices
foreach (var d in Devices.Values)
@@ -87,14 +83,10 @@ namespace PepperDash.Essentials.Core
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device {1} Activation failure: {0}", e.Message, d.Key);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
Debug.Console(0, d, "ERROR: Device Activation failure:\r{0}", e);
}
}
Debug.Console(0, "****Activation complete****");
Debug.Console(0, "****PostActivation starting...****");
// PostActivate all devices
foreach (var d in Devices.Values)
{
@@ -105,13 +97,10 @@ namespace PepperDash.Essentials.Core
}
catch (Exception e)
{
Debug.Console(0, d, "ERROR: Device {1} PostActivation failure: {0}", e.Message, d.Key);
Debug.Console(1, d, "Stack Trace: {0}", e.StackTrace);
Debug.Console(0, d, "ERROR: Device PostActivation failure:\r{0}", e);
}
}
Debug.Console(0, "****PostActivation complete****");
OnAllDevicesActivated();
}
finally

View File

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

View File

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

View File

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

View File

@@ -119,21 +119,9 @@ namespace PepperDash.Essentials.Core.Fusion
var slot = Global.ControlSystem.ProgramNumber;
var guidFilePath = Global.FilePathPrefix +
string.Format(@"{0}-FusionGuids-{1:X2}.json", InitialParametersClass.ProgramIDTag, _ipId);
string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
var oldGuidFilePath = Global.FilePathPrefix +
string.Format(@"{0}-FusionGuids.json", InitialParametersClass.ProgramIDTag);
if (File.Exists(oldGuidFilePath))
{
Debug.Console(0, this, "Migrating from old Fusion GUID file to new Fusion GUID File");
File.Copy(oldGuidFilePath, guidFilePath);
File.Delete(oldGuidFilePath);
}
_guidFileExists = File.Exists(guidFilePath);
_guidFileExists = File.Exists(guidFilePath);
// Check if file exists
if (!_guidFileExists)
@@ -161,7 +149,19 @@ namespace PepperDash.Essentials.Core.Fusion
}
AddPostActivationAction(() => PostActivate(guidFilePath));
AddPostActivationAction(() =>
{
CreateSymbolAndBasicSigs(_ipId);
SetUpSources();
SetUpCommunitcationMonitors();
SetUpDisplay();
SetUpError();
ExecuteCustomSteps();
FusionRVI.GenerateFileForAllFusionDevices();
GenerateGuidFile(guidFilePath);
});
}
catch (Exception e)
{
@@ -169,20 +169,6 @@ namespace PepperDash.Essentials.Core.Fusion
}
}
private void PostActivate(string guidFilePath)
{
CreateSymbolAndBasicSigs(_ipId);
SetUpSources();
SetUpCommunitcationMonitors();
SetUpDisplay();
SetUpError();
ExecuteCustomSteps();
FusionRVI.GenerateFileForAllFusionDevices();
GenerateGuidFile(guidFilePath);
}
protected string RoomGuid
{
get { return _guiDs.RoomGuid; }
@@ -328,7 +314,7 @@ namespace PepperDash.Essentials.Core.Fusion
protected virtual void CreateSymbolAndBasicSigs(uint ipId)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0} and IP-ID {1:X2}", RoomGuid, ipId);
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();

View File

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

View File

@@ -13,13 +13,13 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.Core
{
[Description("Wrapper class for GLS Cresnet Partition Sensor")]
public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice, IPartitionStateProvider
public class GlsPartitionSensorController : CrestronGenericBridgeableBaseDevice
{
private GlsPartCn _partitionSensor;
public StringFeedback NameFeedback { get; private set; }
public BoolFeedback EnableFeedback { get; private set; }
public BoolFeedback PartitionPresentFeedback { get; private set; }
public BoolFeedback PartitionSensedFeedback { get; private set; }
public BoolFeedback PartitionNotSensedFeedback { get; private set; }
public IntFeedback SensitivityFeedback { get; private set; }
@@ -39,10 +39,10 @@ namespace PepperDash.Essentials.Core
RegisterCrestronGenericBase(_partitionSensor);
NameFeedback = new StringFeedback(() => Name);
EnableFeedback = new BoolFeedback(() => InTestMode ? TestEnableFeedback : _partitionSensor.EnableFeedback.BoolValue);
PartitionPresentFeedback = new BoolFeedback(() => InTestMode ? TestPartitionSensedFeedback : _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionNotSensedFeedback = new BoolFeedback(() => InTestMode ? !TestPartitionSensedFeedback : _partitionSensor.PartitionNotSensedFeedback.BoolValue);
SensitivityFeedback = new IntFeedback(() => InTestMode ? TestSensitivityFeedback : _partitionSensor.SensitivityFeedback.UShortValue);
EnableFeedback = new BoolFeedback(() => _partitionSensor.EnableFeedback.BoolValue);
PartitionSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionSensedFeedback.BoolValue);
PartitionNotSensedFeedback = new BoolFeedback(() => _partitionSensor.PartitionNotSensedFeedback.BoolValue);
SensitivityFeedback = new IntFeedback(() => _partitionSensor.SensitivityFeedback.UShortValue);
if (_partitionSensor != null) _partitionSensor.BaseEvent += PartitionSensor_BaseEvent;
});
@@ -61,7 +61,7 @@ namespace PepperDash.Essentials.Core
}
case (GlsPartCn.PartitionSensedFeedbackEventId):
{
PartitionPresentFeedback.FireUpdate();
PartitionSensedFeedback.FireUpdate();
break;
}
case (GlsPartCn.PartitionNotSensedFeedbackEventId):
@@ -93,9 +93,6 @@ namespace PepperDash.Essentials.Core
if (InTestMode)
{
TestEnableFeedback = state;
EnableFeedback.FireUpdate();
Debug.Console(1, this, "TestEnableFeedback: {0}", TestEnableFeedback.ToString());
return;
}
@@ -108,10 +105,6 @@ namespace PepperDash.Essentials.Core
if (InTestMode)
{
TestPartitionSensedFeedback = state;
PartitionPresentFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate();
Debug.Console(1, this, "TestPartitionSensedFeedback: {0}", TestPartitionSensedFeedback.ToString());
return;
}
@@ -124,8 +117,6 @@ namespace PepperDash.Essentials.Core
if (InTestMode)
{
TestSensitivityFeedback = value;
SensitivityFeedback.FireUpdate();
Debug.Console(1, this, "TestSensitivityFeedback: {0}", TestSensitivityFeedback);
return;
}
@@ -198,7 +189,7 @@ namespace PepperDash.Essentials.Core
// link output to simpl
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
EnableFeedback.LinkInputSig(trilist.BooleanInput[joinMap.Enable.JoinNumber]);
PartitionPresentFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionSensed.JoinNumber]);
PartitionNotSensedFeedback.LinkInputSig(trilist.BooleanInput[joinMap.PartitionNotSensed.JoinNumber]);
SensitivityFeedback.LinkInputSig(trilist.UShortInput[joinMap.Sensitivity.JoinNumber]);
@@ -228,7 +219,7 @@ namespace PepperDash.Essentials.Core
IsOnline.FireUpdate();
NameFeedback.FireUpdate();
EnableFeedback.FireUpdate();
PartitionPresentFeedback.FireUpdate();
PartitionSensedFeedback.FireUpdate();
PartitionNotSensedFeedback.FireUpdate();
SensitivityFeedback.FireUpdate();
}
@@ -269,7 +260,7 @@ namespace PepperDash.Essentials.Core
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new GlsPartitionSensorController Device");
Debug.Console(1, "Factory Attempting to create new C2N-RTHS Device");
return new GlsPartitionSensorController(dc.Key, GetGlsPartCnDevice, dc);
}

View File

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

View File

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

View File

@@ -1,264 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
public class EssentialsRoomCombiner : EssentialsDevice, IEssentialsRoomCombiner
{
private EssentialsRoomCombinerPropertiesConfig _propertiesConfig;
private IRoomCombinationScenario _currentScenario;
private List<IEssentialsRoom> _rooms;
private bool isInAutoMode;
private CTimer _scenarioChangeDebounceTimer;
private int _scenarioChangeDebounceTimeSeconds = 10; // default to 10s
public EssentialsRoomCombiner(string key, EssentialsRoomCombinerPropertiesConfig props)
: base(key)
{
_propertiesConfig = props;
Partitions = new List<IPartitionController>();
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
if (_propertiesConfig.ScenarioChangeDebounceTimeSeconds > 0)
{
_scenarioChangeDebounceTimeSeconds = _propertiesConfig.ScenarioChangeDebounceTimeSeconds;
}
IsInAutoModeFeedback = new BoolFeedback(() => isInAutoMode);
// default to auto mode
isInAutoMode = true;
if (_propertiesConfig.defaultToManualMode)
{
isInAutoMode = false;
}
IsInAutoModeFeedback.FireUpdate();
CreateScenarios();
AddPostActivationAction(() =>
{
SetupPartitionStateProviders();
SetRooms();
});
}
void CreateScenarios()
{
RoomCombinationScenarios = new List<IRoomCombinationScenario>();
foreach (var scenarioConfig in _propertiesConfig.Scenarios)
{
var scenario = new RoomCombinationScenario(scenarioConfig);
RoomCombinationScenarios.Add(scenario);
}
}
void SetRooms()
{
_rooms = new List<IEssentialsRoom>();
foreach (var roomKey in _propertiesConfig.RoomKeys)
{
var room = DeviceManager.GetDeviceForKey(roomKey) as IEssentialsRoom;
if (room != null)
{
_rooms.Add(room);
}
}
}
void SetupPartitionStateProviders()
{
foreach (var pConfig in _propertiesConfig.Partitions)
{
var sensor = DeviceManager.GetDeviceForKey(pConfig.DeviceKey) as IPartitionStateProvider;
var partition = new EssentialsPartitionController(pConfig.Key, pConfig.Name, sensor, _propertiesConfig.defaultToManualMode, pConfig.AdjacentRoomKeys);
partition.PartitionPresentFeedback.OutputChange += PartitionPresentFeedback_OutputChange;
Partitions.Add(partition);
}
}
void PartitionPresentFeedback_OutputChange(object sender, FeedbackEventArgs e)
{
StartDebounceTimer();
}
void StartDebounceTimer()
{
var time = _scenarioChangeDebounceTimeSeconds * 1000;
if (_scenarioChangeDebounceTimer == null)
{
_scenarioChangeDebounceTimer = new CTimer((o) => DetermineRoomCombinationScenario(), time);
}
else
{
_scenarioChangeDebounceTimer.Reset(time);
}
}
/// <summary>
/// Determines the current room combination scenario based on the state of the partition sensors
/// </summary>
void DetermineRoomCombinationScenario()
{
if (_scenarioChangeDebounceTimer != null)
{
_scenarioChangeDebounceTimer.Dispose();
_scenarioChangeDebounceTimer = null;
}
var currentScenario = RoomCombinationScenarios.FirstOrDefault((s) =>
{
// iterate the partition states
foreach (var partitionState in s.PartitionStates)
{
// get the partition by key
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
if (partition != null && partitionState.PartitionPresent != partition.PartitionPresentFeedback.BoolValue)
{
// the partition can't be found or the state doesn't match
return false;
}
}
// if it hasn't returned false by now we have the matching scenario
return true;
});
if (currentScenario != null)
{
CurrentScenario = currentScenario;
}
}
#region IEssentialsRoomCombiner Members
public event EventHandler<EventArgs> RoomCombinationScenarioChanged;
public IRoomCombinationScenario CurrentScenario
{
get
{
return _currentScenario;
}
set
{
if (value != _currentScenario)
{
_currentScenario = value;
Debug.Console(1, this, "Current Scenario: {0}", _currentScenario.Name);
var handler = RoomCombinationScenarioChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
}
public BoolFeedback IsInAutoModeFeedback { get; private set; }
public void SetAutoMode()
{
isInAutoMode = true;
IsInAutoModeFeedback.FireUpdate();
}
public void SetManualMode()
{
isInAutoMode = false;
IsInAutoModeFeedback.FireUpdate();
}
public void ToggleMode()
{
isInAutoMode = !isInAutoMode;
IsInAutoModeFeedback.FireUpdate();
}
public List<IRoomCombinationScenario> RoomCombinationScenarios { get; private set; }
public List<IPartitionController> Partitions { get; private set; }
public void TogglePartitionState(string partitionKey)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionKey)) as IPartitionController;
if (partition != null)
{
partition.ToggglePartitionState();
}
}
public void SetRoomCombinationScenario(string scenarioKey)
{
if (isInAutoMode)
{
Debug.Console(0, this, "Cannot set room combination scenario when in auto mode. Set to auto mode first.");
return;
}
// Get the scenario
var scenario = RoomCombinationScenarios.FirstOrDefault((s) => s.Key.Equals(scenarioKey));
// Set the parition states from the scenario manually
if (scenario != null)
{
foreach (var partitionState in scenario.PartitionStates)
{
var partition = Partitions.FirstOrDefault((p) => p.Key.Equals(partitionState.PartitionKey));
if (partition != null)
{
if (partitionState.PartitionPresent)
{
partition.SetPartitionStatePresent();
}
else
{
partition.SetPartitionStateNotPresent();
}
}
}
}
}
#endregion
}
public class EssentialsRoomCombinerFactory : EssentialsDeviceFactory<EssentialsRoomCombiner>
{
public EssentialsRoomCombinerFactory()
{
TypeNames = new List<string> { "essentialsroomcombiner" };
}
public override EssentialsDevice BuildDevice(PepperDash.Essentials.Core.Config.DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new EssentialsRoomCombiner Device");
var props = dc.Properties.ToObject<EssentialsRoomCombinerPropertiesConfig>();
return new EssentialsRoomCombiner(dc.Key, props);
}
}
}

View File

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

View File

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

View File

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

View File

@@ -16,8 +16,7 @@ using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.DM.Config;
namespace PepperDash.Essentials.DM
{
namespace PepperDash.Essentials.DM {
/// <summary>
/// Builds a controller for basic DM-RMCs with Com and IR ports and no control functions
///
@@ -76,10 +75,8 @@ namespace PepperDash.Essentials.DM
/// Factory method to create a new chassis controller from config data. Limited to 8x8 right now
/// </summary>
public static DmBladeChassisController GetDmChassisController(string key, string name,
string type, DMChassisPropertiesConfig properties)
{
try
{
string type, DMChassisPropertiesConfig properties) {
try {
type = type.ToLower();
uint ipid = properties.Control.IpIdInt;
@@ -88,8 +85,7 @@ namespace PepperDash.Essentials.DM
else if (type == "dmmd128x128") { chassis = new DmMd128x128(ipid, Global.ControlSystem); }
if (chassis == null)
{
if (chassis == null) {
return null;
}
@@ -97,13 +93,11 @@ namespace PepperDash.Essentials.DM
// add the cards and port names
foreach (var kvp in properties.InputSlots)
controller.AddInputBlade(kvp.Value, kvp.Key);
foreach (var kvp in properties.OutputSlots)
{
foreach (var kvp in properties.OutputSlots) {
controller.AddOutputBlade(kvp.Value, kvp.Key);
}
foreach (var kvp in properties.VolumeControls)
{
foreach (var kvp in properties.VolumeControls) {
// get the card
// check it for an audio-compatible type
// make a something-something that will make it work
@@ -129,8 +123,7 @@ namespace PepperDash.Essentials.DM
controller.PropertiesConfig = properties;
return controller;
}
catch (System.Exception e)
{
catch (System.Exception e) {
Debug.Console(0, "Error creating DM chassis:\r{0}", e);
}
return null;
@@ -144,8 +137,7 @@ namespace PepperDash.Essentials.DM
/// <param name="name"></param>
/// <param name="chassis"></param>
public DmBladeChassisController(string key, string name, BladeSwitch chassis)
: base(key, name, chassis)
{
: base(key, name, chassis) {
Chassis = chassis;
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
@@ -169,87 +161,68 @@ namespace PepperDash.Essentials.DM
InputCardHdcpCapabilityFeedbacks = new Dictionary<uint, IntFeedback>();
InputCardHdcpCapabilityTypes = new Dictionary<uint, eHdcpCapabilityType>();
for (uint x = 1; x <= Chassis.NumberOfOutputs; x++)
{
for (uint x = 1; x <= Chassis.NumberOfOutputs; x++) {
var tempX = x;
if (Chassis.Outputs[tempX] != null)
{
VideoOutputFeedbacks[tempX] = new IntFeedback(() =>
{
if (Chassis.Outputs[tempX] != null) {
VideoOutputFeedbacks[tempX] = new IntFeedback(() => {
if (Chassis.Outputs[tempX].VideoOutFeedback != null) { return (ushort)Chassis.Outputs[tempX].VideoOutFeedback.Number; }
else { return 0; };
});
OutputNameFeedbacks[tempX] = new StringFeedback(() =>
{
if (Chassis.Outputs[tempX].NameFeedback != null)
{
OutputNameFeedbacks[tempX] = new StringFeedback(() => {
if (Chassis.Outputs[tempX].NameFeedback != null) {
return Chassis.Outputs[tempX].NameFeedback.StringValue;
}
else
{
else {
return "";
}
});
OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() =>
{
if (Chassis.Outputs[tempX].VideoOutFeedback != null)
{
OutputVideoRouteNameFeedbacks[tempX] = new StringFeedback(() => {
if (Chassis.Outputs[tempX].VideoOutFeedback != null) {
return Chassis.Outputs[tempX].VideoOutFeedback.NameFeedback.StringValue;
}
else
{
else {
return "";
}
});
OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() =>
{
OutputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => {
//if (Chassis.Outputs[tempX].Endpoint != null)
// return Chassis.Outputs[tempX].Endpoint.IsOnline;
//else
return Chassis.Outputs[tempX].EndpointOnlineFeedback;
return Chassis.Outputs[tempX].EndpointOnlineFeedback;
});
}
if (Chassis.Inputs[tempX] != null)
{
UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() =>
{
if (Chassis.Inputs[tempX] != null) {
UsbInputRoutedToFeebacks[tempX] = new IntFeedback(() => {
if (Chassis.Inputs[tempX].USBRoutedToFeedback != null) { return (ushort)Chassis.Inputs[tempX].USBRoutedToFeedback.Number; }
else { return 0; };
});
VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() =>
{
VideoInputSyncFeedbacks[tempX] = new BoolFeedback(() => {
if (Chassis.Inputs[tempX].VideoDetectedFeedback != null)
return Chassis.Inputs[tempX].VideoDetectedFeedback.BoolValue;
else
return false;
});
InputNameFeedbacks[tempX] = new StringFeedback(() =>
{
if (Chassis.Inputs[tempX].NameFeedback != null)
{
InputNameFeedbacks[tempX] = new StringFeedback(() => {
if (Chassis.Inputs[tempX].NameFeedback != null) {
return Chassis.Inputs[tempX].NameFeedback.StringValue;
}
else
{
else {
return "";
}
});
InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() =>
{
InputEndpointOnlineFeedbacks[tempX] = new BoolFeedback(() => {
return Chassis.Inputs[tempX].EndpointOnlineFeedback;
});
InputCardHdcpCapabilityFeedbacks[tempX] = new IntFeedback(() =>
{
InputCardHdcpCapabilityFeedbacks[tempX] = new IntFeedback(() => {
var inputCard = Chassis.Inputs[tempX];
if (inputCard.Card is DmHdmi4kInputBladeCard)
{
if (inputCard.Card is DmHdmi4kInputBladeCard) {
InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support;
if ((inputCard.Card as DmHdmi4kInputBladeCard).Hdmi4kInput.HdcpSupportOnFeedback.BoolValue)
@@ -258,8 +231,7 @@ namespace PepperDash.Essentials.DM
return 0;
}
if (inputCard.Card is DmC4kInputBladeCard)
{
if (inputCard.Card is DmC4kInputBladeCard) {
InputCardHdcpCapabilityTypes[tempX] = eHdcpCapabilityType.Hdcp2_2Support;
if ((inputCard.Card as DmC4kInputBladeCard).DmInput.HdcpCapabilityFeedback.Equals(eHdcpCapabilityType.HdcpSupportOff))
@@ -280,56 +252,45 @@ namespace PepperDash.Essentials.DM
/// </summary>
/// <param name="type"></param>
/// <param name="number"></param>
public void AddInputBlade(string type, uint number)
{
public void AddInputBlade(string type, uint number) {
Debug.Console(2, this, "Adding input blade '{0}', slot {1}", type, number);
type = type.ToLower();
if (type == "dmb4kihd")
{
if (type == "dmb4kihd") {
var inputBlade = new Dmb4kIHd(number, this.Chassis);
foreach (var item in inputBlade.Inputs)
{
foreach (var item in inputBlade.Inputs) {
var card = (item.Card as DmHdmi4kInputBladeCard).Hdmi4kInput;
var cecPort = card as ICec;
AddHdmiInBladePorts(item.Number, cecPort);
}
}
else if (type == "dmb4kihddnt")
{
else if (type == "dmb4kihddnt") {
var inputBlade = new Dmb4kIHd(number, this.Chassis);
foreach (var item in inputBlade.Inputs)
{
foreach (var item in inputBlade.Inputs) {
var card = (item.Card as DmHdmi4kInputBladeCard).Hdmi4kInput;
var cecPort = card as ICec;
AddHdmiInBladePorts(item.Number, cecPort);
}
}
else if (type == "dmb4kic")
{
else if (type == "dmb4kic") {
var inputBlade = new Dmb4kIC(number, this.Chassis);
foreach (var item in inputBlade.Inputs)
{
foreach (var item in inputBlade.Inputs) {
AddDmInBladePorts(item.Number);
}
}
else if (type == "dmbis")
{
else if (type == "dmbis") {
var inputBlade = new DmbIS(number, this.Chassis);
foreach (var item in inputBlade.Inputs)
{
foreach (var item in inputBlade.Inputs) {
AddDmInMmFiberPorts(item.Number);
}
}
else if (type == "dmbis2")
{
else if (type == "dmbis2") {
var inputBlade = new DmbIS2(number, this.Chassis);
foreach (var item in inputBlade.Inputs)
{
foreach (var item in inputBlade.Inputs) {
AddDmInSmFiberPorts(item.Number);
}
}
@@ -343,26 +304,22 @@ namespace PepperDash.Essentials.DM
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
}
void AddHdmiInBladePorts(uint number, ICec cecPort)
{
void AddHdmiInBladePorts(uint number, ICec cecPort) {
AddInputPortWithDebug(number, "hdmiIn", eRoutingSignalType.Audio | eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, cecPort);
}
void AddDmInBladePorts(uint number)
{
void AddDmInBladePorts(uint number) {
AddInputPortWithDebug(number, "dmCIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat);
}
void AddDmInMmFiberPorts(uint number)
{
void AddDmInMmFiberPorts(uint number) {
AddInputPortWithDebug(number, "dmMmIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber);
}
void AddDmInSmFiberPorts(uint number)
{
void AddDmInSmFiberPorts(uint number) {
AddInputPortWithDebug(number, "dmSmIn", eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber);
}
@@ -371,81 +328,64 @@ namespace PepperDash.Essentials.DM
/// </summary>
/// <param name="type"></param>
/// <param name="number"></param>
public void AddOutputBlade(string type, uint number)
{
public void AddOutputBlade(string type, uint number) {
type = type.ToLower();
Debug.Console(2, this, "Adding output blade '{0}', slot {1}", type, number);
if (type == "dmb4kohd")
{
if (type == "dmb4kohd") {
var outputBlade = new Dmb4KOHD(number, Chassis);
foreach (var item in outputBlade.Outputs)
{
foreach (var item in outputBlade.Outputs) {
AddHdmiOutBladePorts(item.Number);
}
}
else if (type == "dmb4kohddnt")
{
else if (type == "dmb4kohddnt") {
var outputBlade = new Dmb4KOHD(number, Chassis);
foreach (var item in outputBlade.Outputs)
{
foreach (var item in outputBlade.Outputs) {
AddHdmiOutBladePorts(item.Number);
}
}
else if (type == "dmb4koc")
{
else if (type == "dmb4koc") {
var outputBlade = new Dmb4KOC(number, Chassis);
foreach (var item in outputBlade.Outputs)
{
foreach (var item in outputBlade.Outputs) {
AddDmOutBladePorts(item.Number);
}
}
else if (type == "dmb4koc")
{
else if (type == "dmb4koc") {
var outputBlade = new Dmb4KOC(number, Chassis);
foreach (var item in outputBlade.Outputs)
{
foreach (var item in outputBlade.Outputs) {
AddDmOutBladePorts(item.Number);
}
}
else if (type == "dmbos")
{
else if (type == "dmbos") {
var outputBlade = new DmbOS(number, Chassis);
foreach (var item in outputBlade.Outputs)
{
foreach (var item in outputBlade.Outputs) {
AddDmOutMmFiberBladePorts(item.Number);
}
}
else if (type == "dmbos2")
{
else if (type == "dmbos2") {
var outputBlade = new DmbOS2(number, Chassis);
foreach (var item in outputBlade.Outputs)
{
foreach (var item in outputBlade.Outputs) {
AddDmOutSmFiberBladePorts(item.Number);
}
}
}
void AddHdmiOutBladePorts(uint number)
{
AddOutputPortWithDebug(number, "hdmiOut", eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, Chassis.Outputs[number]);
void AddHdmiOutBladePorts(uint number) {
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("hdmiOut{0}", number) , eRoutingSignalType.Video, eRoutingPortConnectionType.Hdmi, Chassis.Outputs[number]);
}
void AddDmOutBladePorts(uint number)
{
AddOutputPortWithDebug(number, "dmOut", eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, Chassis.Outputs[number]);
void AddDmOutBladePorts(uint number) {
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("dmOut{0}", number), eRoutingSignalType.Video, eRoutingPortConnectionType.DmCat, Chassis.Outputs[number]);
}
void AddDmOutMmFiberBladePorts(uint number)
{
AddOutputPortWithDebug(number, "dmMmOut", eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[number]);
void AddDmOutMmFiberBladePorts(uint number) {
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("dmOut{0}", number), eRoutingSignalType.Video, eRoutingPortConnectionType.DmMmFiber, Chassis.Outputs[number]);
}
void AddDmOutSmFiberBladePorts(uint number)
{
AddOutputPortWithDebug(number, "dmSmOut", eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[number]);
void AddDmOutSmFiberBladePorts(uint number) {
AddOutputPortWithDebug(String.Format("outputBlade{0}", (number / 8 > 0 ? 1 : number / 8)), String.Format("dmOut{0}", number), eRoutingSignalType.Video, eRoutingPortConnectionType.DmSmFiber, Chassis.Outputs[number]);
}
@@ -477,44 +417,23 @@ namespace PepperDash.Essentials.DM
}
/*void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) {
/// <summary>
/// Adds OutputPort
/// </summary>
void AddOutputPortWithDebug(string cardName, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector) {
var portKey = string.Format("{0}--{1}", cardName, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
OutputPorts.Add(new RoutingOutputPort(portKey, sigType, portType, selector, this)
{
FeedbackMatchObject = Chassis.Outputs[(uint)selector]
});
}*/
/// <summary>
/// Adds OutputPort
/// </summary>
void AddOutputPortWithDebug(uint cardNum, string portName, eRoutingSignalType sigType, eRoutingPortConnectionType portType, object selector)
{
try
{
var portKey = string.Format("outputCard{0}--{1}", cardNum, portName);
Debug.Console(2, this, "Adding output port '{0}'", portKey);
var outputPort = new RoutingOutputPort(portKey, sigType, portType, selector, this)
{
FeedbackMatchObject = Chassis.Outputs[cardNum]
};
OutputPorts.Add(outputPort);
}
catch (Exception ex)
{
Debug.Console(0, this, "Exception : {0}", ex);
}
}
/// <summary>
///
/// </summary>
void AddVolumeControl(uint number, Audio.Output audio)
{
void AddVolumeControl(uint number, Audio.Output audio) {
VolumeControls.Add(number, new DmCardAudioOutputController(audio));
}
@@ -524,43 +443,35 @@ namespace PepperDash.Essentials.DM
//}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
void Chassis_DMInputChange(Switch device, DMInputEventArgs args) {
switch (args.EventId)
{
case DMInputEventIds.EndpointOnlineEventId:
{
switch (args.EventId) {
case DMInputEventIds.EndpointOnlineEventId: {
Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback);
InputEndpointOnlineFeedbacks[args.Number].FireUpdate();
break;
}
case DMInputEventIds.OnlineFeedbackEventId:
{
case DMInputEventIds.OnlineFeedbackEventId: {
Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback);
InputEndpointOnlineFeedbacks[args.Number].FireUpdate();
break;
}
case DMInputEventIds.VideoDetectedEventId:
{
case DMInputEventIds.VideoDetectedEventId: {
Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number);
VideoInputSyncFeedbacks[args.Number].FireUpdate();
break;
}
case DMInputEventIds.InputNameEventId:
{
case DMInputEventIds.InputNameEventId: {
Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number);
InputNameFeedbacks[args.Number].FireUpdate();
break;
}
case DMInputEventIds.HdcpCapabilityFeedbackEventId:
{
case DMInputEventIds.HdcpCapabilityFeedbackEventId: {
Debug.Console(2, this, "DM Input {0} HdcpCapabilityFeedbackEventId", args.Number);
InputCardHdcpCapabilityFeedbacks[args.Number].FireUpdate();
break;
}
default:
{
default: {
Debug.Console(2, this, "DMInputChange fired for Input {0} with Unhandled EventId: {1}", args.Number, args.EventId);
break;
}
@@ -576,74 +487,74 @@ namespace PepperDash.Essentials.DM
switch (args.EventId)
{
case DMOutputEventIds.VolumeEventId:
{
if (VolumeControls.ContainsKey(output))
{
if (VolumeControls.ContainsKey(output))
{
VolumeControls[args.Number].VolumeEventFromChassis();
}
break;
VolumeControls[args.Number].VolumeEventFromChassis();
}
break;
}
case DMOutputEventIds.EndpointOnlineEventId:
{
{
Debug.Console(2, this,
"Output {0} DMOutputEventIds.EndpointOnlineEventId fired. EndpointOnlineFeedback State: {1}",
args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
if (Chassis.Outputs[output].Endpoint != null)
Debug.Console(2, this,
"Output {0} DMOutputEventIds.EndpointOnlineEventId fired. EndpointOnlineFeedback State: {1}",
args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
if (Chassis.Outputs[output].Endpoint != null)
Debug.Console(2, this,
"Output {0} DMOutputEventIds.EndpointOnlineEventId fired. Endpoint.IsOnline State: {1}",
args.Number, Chassis.Outputs[output].Endpoint.IsOnline);
"Output {0} DMOutputEventIds.EndpointOnlineEventId fired. Endpoint.IsOnline State: {1}",
args.Number, Chassis.Outputs[output].Endpoint.IsOnline);
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.OnlineFeedbackEventId:
{
Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}",
args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
{
Debug.Console(2, this, "Output {0} DMInputEventIds.OnlineFeedbackEventId fired. State: {1}",
args.Number, Chassis.Outputs[output].EndpointOnlineFeedback);
OutputEndpointOnlineFeedbacks[output].FireUpdate();
break;
}
case DMOutputEventIds.VideoOutEventId:
{
var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.Outputs[output].VideoOutFeedback.Number;
Debug.Console(2, this, "DMSwitchAudioVideo:{0} Routed Input:{1} Output:{2}'", this.Name,
inputNumber, output);
if (VideoOutputFeedbacks.ContainsKey(output))
{
var inputNumber = Chassis.Outputs[output].VideoOutFeedback == null ? 0 : Chassis.Outputs[output].VideoOutFeedback.Number;
Debug.Console(2, this, "DMSwitchAudioVideo:{0} Routed Input:{1} Output:{2}'", this.Name,
inputNumber, output);
if (VideoOutputFeedbacks.ContainsKey(output))
{
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].VideoOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == Chassis.Outputs[output]);
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == Chassis.Outputs[output].VideoOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput) p.FeedbackMatchObject == Chassis.Outputs[output]);
VideoOutputFeedbacks[output].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output,
inputNumber,
localOutputPort,
localInputPort,
eRoutingSignalType.AudioVideo));
VideoOutputFeedbacks[output].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output,
inputNumber,
localOutputPort,
localInputPort,
eRoutingSignalType.AudioVideo));
}
if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
{
OutputVideoRouteNameFeedbacks[output].FireUpdate();
}
break;
}
if (OutputVideoRouteNameFeedbacks.ContainsKey(output))
{
OutputVideoRouteNameFeedbacks[output].FireUpdate();
}
break;
}
case DMOutputEventIds.OutputNameEventId:
{
Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output);
OutputNameFeedbacks[output].FireUpdate();
break;
}
{
Debug.Console(2, this, "DM Output {0} NameFeedbackEventId", output);
OutputNameFeedbacks[output].FireUpdate();
break;
}
default:
{
Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}",
args.Number, args.EventId);
break;
}
{
Debug.Console(2, this, "DMOutputChange fired for Output {0} with Unhandled EventId: {1}",
args.Number, args.EventId);
break;
}
}
}
@@ -653,8 +564,7 @@ namespace PepperDash.Essentials.DM
///
/// </summary>
/// <param name="pnt"></param>
void StartOffTimer(PortNumberType pnt)
{
void StartOffTimer(PortNumberType pnt) {
if (RouteOffTimers.ContainsKey(pnt))
return;
RouteOffTimers[pnt] = new CTimer(o => ExecuteSwitch(null, pnt.Selector, pnt.Type), RouteOffTime);
@@ -662,10 +572,8 @@ namespace PepperDash.Essentials.DM
// Send out sigs when coming online
void IsOnline_OutputChange(object sender, EventArgs e)
{
if (IsOnline.BoolValue)
{
void IsOnline_OutputChange(object sender, EventArgs e) {
if (IsOnline.BoolValue) {
Chassis.EnableUSBBreakaway.BoolValue = true;
if (InputNames != null)
@@ -679,13 +587,12 @@ namespace PepperDash.Essentials.DM
#region IRouting Members
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType)
{
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType sigType) {
Debug.Console(2, this, "Making an awesome DM route from {0} to {1} {2}", inputSelector, outputSelector, sigType);
var input = inputSelector as DMInput; // Cast can sometimes fail
var output = outputSelector as DMOutput;
if (output == null)
{
@@ -698,14 +605,11 @@ namespace PepperDash.Essentials.DM
// Check to see if there's an off timer waiting on this and if so, cancel
var key = new PortNumberType(output, sigType);
if (input == null)
{
if (input == null) {
StartOffTimer(key);
}
else
{
if (RouteOffTimers.ContainsKey(key))
{
else {
if (RouteOffTimers.ContainsKey(key)) {
Debug.Console(2, this, "{0} cancelling route off due to new source", output);
RouteOffTimers[key].Stop();
RouteOffTimers.Remove(key);
@@ -767,7 +671,7 @@ namespace PepperDash.Essentials.DM
var ioSlotJoin = ioSlot - 1;
// Control
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteNumericSwitch(o, (ushort)ioSlot, eRoutingSignalType.Video));
trilist.SetUShortSigAction(joinMap.OutputVideo.JoinNumber + ioSlotJoin, o => ExecuteNumericSwitch(o, (ushort) ioSlot, eRoutingSignalType.Video));
if (TxDictionary.ContainsKey(ioSlot))
{

View File

@@ -1285,7 +1285,10 @@ namespace PepperDash.Essentials.DM
var output = outputSelector as DMOutput;
if (output == null)
var isUsbInput = (sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput;
var isUsbOutput = (sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput;
if (output == null && !(isUsbOutput || isUsbInput))
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning,
"Unable to execute switch for inputSelector {0} to outputSelector {1}", inputSelector,
@@ -1316,7 +1319,10 @@ namespace PepperDash.Essentials.DM
if ((sigType & eRoutingSignalType.Video) == eRoutingSignalType.Video)
{
Chassis.VideoEnter.BoolValue = true;
output.VideoOut = input; //Chassis.Outputs[output].VideoOut = inCard;
if (output != null)
{
output.VideoOut = input; //Chassis.Outputs[output].VideoOut = inCard;
}
}
if ((sigType & eRoutingSignalType.Audio) == eRoutingSignalType.Audio)
@@ -1326,17 +1332,66 @@ namespace PepperDash.Essentials.DM
{
dmMdMnxn.AudioEnter.BoolValue = true;
}
output.AudioOut = input;
//Chassis.Outputs[output].AudioOut = inCard;
if (output != null)
{
output.AudioOut = input;
}
}
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput || (sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
{
Chassis.USBEnter.BoolValue = true;
output.USBRoutedTo = input;
Chassis.USBEnter.BoolValue = true;
if (inputSelector == null && output != null)
{
//clearing the route is intended
output.USBRoutedTo = null;
return;
}
if (inputSelector != null && input == null)
{
//input selector is DMOutput...we're doing a out to out route
var tempInput = inputSelector as DMOutput;
if (tempInput == null || output == null)
{
return;
}
output.USBRoutedTo = tempInput;
return;
}
if (input != null & output != null)
{
output.USBRoutedTo = input;
}
}
if((sigType & eRoutingSignalType.UsbInput) != eRoutingSignalType.UsbInput)
{
return;
}
Chassis.USBEnter.BoolValue = true;
if (output != null)
{
output.USBRoutedTo = input;
return;
}
var tempOutput = outputSelector as DMInput;
if (tempOutput == null)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Warning,
"Unable to execute switch for inputSelector {0} to outputSelector {1}", inputSelector,
outputSelector);
return;
}
tempOutput.USBRoutedTo = input;
}
#endregion
#region IRoutingNumeric Members
@@ -1349,8 +1404,10 @@ namespace PepperDash.Essentials.DM
DMInputOutputBase dmCard;
//Routing Input to Input or Output to Input
if ((sigType & eRoutingSignalType.UsbInput) == eRoutingSignalType.UsbInput)
{
Debug.Console(2, this, "Executing USB Input switch.\r\n in:{0} output: {1}", inputSelector, outputSelector);
if (outputSelector > chassisSize)
{
uint outputIndex;
@@ -1370,13 +1427,14 @@ namespace PepperDash.Essentials.DM
dmCard = Chassis.Inputs[inputSelector];
}
ExecuteSwitch(dmCard, Chassis.Outputs[outputSelector], sigType);
ExecuteSwitch(dmCard, Chassis.Inputs[outputSelector], sigType);
return;
}
if ((sigType & eRoutingSignalType.UsbOutput) == eRoutingSignalType.UsbOutput)
{
Debug.Console(2, this, "Executing USB Output switch.\r\n in:{0} output: {1}", inputSelector, outputSelector);
//routing Output to Output or Input to Output
if (inputSelector > chassisSize)
{
//wanting to route an output to an output. Subtract chassis size and get output, unless it's 8x8

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
@@ -15,421 +16,489 @@ using PepperDash.Essentials.Core.Config;
namespace PepperDash.Essentials.DM.Chassis
{
[Description("Wrapper class for all HdMdNxM4E switchers")]
public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback
{
private HdMdNxM _Chassis;
private HdMd4x14kE _Chassis4x1;
[Description("Wrapper class for all HdMdNxM4E switchers")]
public class HdMdNxM4kEBridgeableController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback
{
private HdMdNxM _Chassis;
private HdMd4x14kE _Chassis4x1;
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
//IroutingNumericEvent
public event EventHandler<RoutingNumericEventArgs> NumericSwitchChange;
public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; }
public Dictionary<uint, string> InputNames { get; set; }
public Dictionary<uint, string> OutputNames { get; set; }
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
public RoutingPortCollection<RoutingOutputPort> OutputPorts { get; private set; }
public FeedbackCollection<BoolFeedback> VideoInputSyncFeedbacks { get; private set; }
public FeedbackCollection<IntFeedback> VideoOutputRouteFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> InputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputRouteNameFeedbacks { get; private set; }
public FeedbackCollection<BoolFeedback> InputHdcpEnableFeedback { get; private set; }
public FeedbackCollection<StringFeedback> DeviceNameFeedback { get; private set; }
public FeedbackCollection<BoolFeedback> AutoRouteFeedback { get; private set; }
public FeedbackCollection<BoolFeedback> VideoInputSyncFeedbacks { get; private set; }
public FeedbackCollection<IntFeedback> VideoOutputRouteFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> InputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputNameFeedbacks { get; private set; }
public FeedbackCollection<StringFeedback> OutputRouteNameFeedbacks { get; private set; }
public FeedbackCollection<BoolFeedback> InputHdcpEnableFeedback { get; private set; }
public StringFeedback DeviceNameFeedback { get; private set; }
public BoolFeedback AutoRouteFeedback { get; private set; }
#region Constructor
#region Constructor
public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis,
HdMdNxM4kEBridgeablePropertiesConfig props)
: base(key, name, chassis)
{
_Chassis = chassis;
var _props = props;
public HdMdNxM4kEBridgeableController(string key, string name, HdMdNxM chassis,
HdMdNxM4kEBridgeablePropertiesConfig props)
: base(key, name, chassis)
{
_Chassis = chassis;
Name = name;
InputNames = props.Inputs;
OutputNames = props.Outputs;
if (props == null)
{
Debug.Console(1, this, "HdMdNx4keBridgeableController properties are null, failed to build the device");
return;
}
VideoInputSyncFeedbacks = new FeedbackCollection<BoolFeedback>();
VideoOutputRouteFeedbacks = new FeedbackCollection<IntFeedback>();
InputNameFeedbacks = new FeedbackCollection<StringFeedback>();
OutputNameFeedbacks = new FeedbackCollection<StringFeedback>();
OutputRouteNameFeedbacks = new FeedbackCollection<StringFeedback>();
InputHdcpEnableFeedback = new FeedbackCollection<BoolFeedback>();
DeviceNameFeedback = new FeedbackCollection<StringFeedback>();
AutoRouteFeedback = new FeedbackCollection<BoolFeedback>();
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
if (props.Inputs != null)
{
foreach (var kvp in props.Inputs)
{
Debug.Console(1, this, "props.Inputs: {0}-{1}", kvp.Key, kvp.Value);
}
InputNames = props.Inputs;
}
if (props.Outputs != null)
{
foreach (var kvp in props.Outputs)
{
Debug.Console(1, this, "props.Outputs: {0}-{1}", kvp.Key, kvp.Value);
}
OutputNames = props.Outputs;
}
DeviceNameFeedback.Add(new StringFeedback(this.Name, () => this.Name));
DeviceNameFeedback = new StringFeedback(()=>Name);
if (_Chassis.NumberOfInputs == 1)
{
_Chassis4x1 = _Chassis as HdMd4x14kE;
AutoRouteFeedback.Add(new BoolFeedback(this.Name + "-" + InputNames[1], () => _Chassis4x1.AutoModeOnFeedback.BoolValue));
}
VideoInputSyncFeedbacks = new FeedbackCollection<BoolFeedback>();
VideoOutputRouteFeedbacks = new FeedbackCollection<IntFeedback>();
InputNameFeedbacks = new FeedbackCollection<StringFeedback>();
OutputNameFeedbacks = new FeedbackCollection<StringFeedback>();
OutputRouteNameFeedbacks = new FeedbackCollection<StringFeedback>();
InputHdcpEnableFeedback = new FeedbackCollection<BoolFeedback>();
InputPorts = new RoutingPortCollection<RoutingInputPort>();
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
var index = i;
var inputName = InputNames[index];
_Chassis.Inputs[index].Name.StringValue = inputName;
if (_Chassis.NumberOfInputs == 1)
{
_Chassis4x1 = _Chassis as HdMd4x14kE;
AutoRouteFeedback = new BoolFeedback(() => _Chassis4x1.AutoModeOnFeedback.BoolValue);
}
InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, index, this)
{
FeedbackMatchObject = _Chassis.HdmiInputs[index]
});
VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue));
InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].Name.StringValue));
InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
}
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
var index = i;
var inputName = InputNames[index];
//_Chassis.Inputs[index].Name.StringValue = inputName;
_Chassis.HdmiInputs[index].Name.StringValue = inputName;
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var index = i;
var outputName = OutputNames[index];
_Chassis.Outputs[i].Name.StringValue = outputName;
InputPorts.Add(new RoutingInputPort(inputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, _Chassis.HdmiInputs[index], this)
{
FeedbackMatchObject = _Chassis.HdmiInputs[index]
});
VideoInputSyncFeedbacks.Add(new BoolFeedback(inputName, () => _Chassis.Inputs[index].VideoDetectedFeedback.BoolValue));
//InputNameFeedbacks.Add(new StringFeedback(inputName, () => _Chassis.Inputs[index].NameFeedback.StringValue));
InputNameFeedbacks.Add(new StringFeedback(inputName, () => InputNames[index]));
InputHdcpEnableFeedback.Add(new BoolFeedback(inputName, () => _Chassis.HdmiInputs[index].HdmiInputPort.HdcpSupportOnFeedback.BoolValue));
}
OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, index, this)
{
FeedbackMatchObject = _Chassis.HdmiOutputs[index]
});
VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => (int)_Chassis.Outputs[index].VideoOutFeedback.Number));
OutputNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].Name.StringValue));
OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue));
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var index = i;
var outputName = OutputNames[index];
//_Chassis.Outputs[index].Name.StringValue = outputName;
//_Chassis.HdmiOutputs[index].Name.StringValue = outputName;
_Chassis.DMInputChange += new DMInputEventHandler(Chassis_DMInputChange);
_Chassis.DMOutputChange += new DMOutputEventHandler(Chassis_DMOutputChange);
OutputPorts.Add(new RoutingOutputPort(outputName, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, _Chassis.HdmiOutputs[index], this)
{
FeedbackMatchObject = _Chassis.HdmiOutputs[index]
});
VideoOutputRouteFeedbacks.Add(new IntFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback == null ? 0 : (int)_Chassis.Outputs[index].VideoOutFeedback.Number));
OutputNameFeedbacks.Add(new StringFeedback(outputName, () => OutputNames[index]));
OutputRouteNameFeedbacks.Add(new StringFeedback(outputName, () => _Chassis.Outputs[index].VideoOutFeedback.NameFeedback.StringValue));
}
AddPostActivationAction(AddFeedbackCollections);
}
_Chassis.DMInputChange += Chassis_DMInputChange;
_Chassis.DMOutputChange += Chassis_DMOutputChange;
#endregion
AddPostActivationAction(AddFeedbackCollections);
}
#region Methods
#endregion
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
#region Methods
public void EnableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
/// <summary>
/// Raise an event when the status of a switch object changes.
/// </summary>
/// <param name="e">Arguments defined as IKeyName sender, output, input, and eRoutingSignalType</param>
private void OnSwitchChange(RoutingNumericEventArgs e)
{
var newEvent = NumericSwitchChange;
if (newEvent != null) newEvent(this, e);
}
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
public void EnableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
public void DisableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOn();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
public void DisableHdcp(uint port)
{
if (port > _Chassis.NumberOfInputs) return;
if (port <= 0) return;
public void EnableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis.HdmiInputs[port].HdmiInputPort.HdcpSupportOff();
InputHdcpEnableFeedback[InputNames[port]].FireUpdate();
}
if (_Chassis4x1 == null) return;
public void EnableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis4x1.AutoModeOn();
}
if (_Chassis4x1 == null) return;
public void DisableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis4x1.AutoModeOn();
}
if (_Chassis4x1 == null) return;
public void DisableAutoRoute()
{
if (_Chassis.NumberOfInputs != 1) return;
_Chassis4x1.AutoModeOff();
}
if (_Chassis4x1 == null) return;
#region PostActivate
_Chassis4x1.AutoModeOff();
}
public void AddFeedbackCollections()
{
AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback);
AddCollectionsToList(VideoOutputRouteFeedbacks);
AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks, DeviceNameFeedback);
}
#region PostActivate
#endregion
public void AddFeedbackCollections()
{
AddFeedbackToList(DeviceNameFeedback);
AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback);
AddCollectionsToList(VideoOutputRouteFeedbacks);
AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedbacks);
}
#region FeedbackCollection Methods
#endregion
//Add arrays of collections
public void AddCollectionsToList(params FeedbackCollection<BoolFeedback>[] newFbs)
{
foreach (FeedbackCollection<BoolFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
public void AddCollectionsToList(params FeedbackCollection<IntFeedback>[] newFbs)
{
foreach (FeedbackCollection<IntFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
#region FeedbackCollection Methods
public void AddCollectionsToList(params FeedbackCollection<StringFeedback>[] newFbs)
{
foreach (FeedbackCollection<StringFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
//Add arrays of collections
public void AddCollectionsToList(params FeedbackCollection<BoolFeedback>[] newFbs)
{
foreach (FeedbackCollection<BoolFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
public void AddCollectionsToList(params FeedbackCollection<IntFeedback>[] newFbs)
{
foreach (FeedbackCollection<IntFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
//Add Collections
public void AddCollectionToList(FeedbackCollection<BoolFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
public void AddCollectionsToList(params FeedbackCollection<StringFeedback>[] newFbs)
{
foreach (FeedbackCollection<StringFeedback> fbCollection in newFbs)
{
foreach (var item in newFbs)
{
AddCollectionToList(item);
}
}
}
AddFeedbackToList(f);
}
}
//Add Collections
public void AddCollectionToList(FeedbackCollection<BoolFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
public void AddCollectionToList(FeedbackCollection<IntFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
AddFeedbackToList(f);
}
}
AddFeedbackToList(f);
}
}
public void AddCollectionToList(FeedbackCollection<IntFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
public void AddCollectionToList(FeedbackCollection<StringFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
AddFeedbackToList(f);
}
}
AddFeedbackToList(f);
}
}
public void AddCollectionToList(FeedbackCollection<StringFeedback> newFbs)
{
foreach (var f in newFbs)
{
if (f == null) continue;
//Add Individual Feedbacks
public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb)
{
if (newFb == null) return;
AddFeedbackToList(f);
}
}
if (!Feedbacks.Contains(newFb))
{
Feedbacks.Add(newFb);
}
}
//Add Individual Feedbacks
public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback newFb)
{
if (newFb == null) return;
#endregion
if (!Feedbacks.Contains(newFb))
{
Feedbacks.Add(newFb);
}
}
#region IRouting Members
#endregion
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
{
// Try to make switch only when necessary. The unit appears to toggle when already selected.
var current = _Chassis.HdmiOutputs[(uint)outputSelector].VideoOut;
if (current != _Chassis.HdmiInputs[(uint)inputSelector])
_Chassis.HdmiOutputs[(uint)outputSelector].VideoOut = _Chassis.HdmiInputs[(uint)inputSelector];
}
#region IRouting Members
#endregion
public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType)
{
var input = inputSelector as HdMdNxMHdmiInput; //changed from HdMdNxM4kzEHdmiInput;
var output = outputSelector as HdMdNxMHdmiOutput;
Debug.Console(2, this, "ExecuteSwitch: input={0} output={1}", input, output);
#region IRoutingNumeric Members
if (output == null)
{
Debug.Console(0, this, "Unable to make switch. output selector is not HdMdNxMHdmiOutput");
return;
}
public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType)
{
ExecuteSwitch(inputSelector, outputSelector, signalType);
}
// Try to make switch only when necessary. The unit appears to toggle when already selected.
var current = output.VideoOut;
if (current != input)
output.VideoOut = input;
}
#endregion
#endregion
#endregion
#region IRoutingNumeric Members
#region Bridge Linking
public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType)
{
var input = inputSelector == 0 ? null : _Chassis.HdmiInputs[inputSelector];
var output = _Chassis.HdmiOutputs[outputSelector];
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new HdMdNxM4kEControllerJoinMap(joinStart);
Debug.Console(2, this, "ExecuteNumericSwitch: input={0} output={1}", input, output);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
ExecuteSwitch(input, output, signalType);
}
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<HdMdNxM4kEControllerJoinMap>(joinMapSerialized);
#endregion
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
#endregion
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
DeviceNameFeedback[this.Name].LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]);
#region Bridge Linking
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new HdMdNxM4kEControllerJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<HdMdNxM4kEControllerJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
DeviceNameFeedback.LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]);
if (_Chassis4x1 != null)
{
trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOn());
trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOff());
AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]);
}
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
var joinIndex = i - 1;
var input = i;
//Digital
VideoInputSyncFeedbacks[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[input]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[input]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]);
trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(input));
trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(input));
//Serial
InputNameFeedbacks[InputNames[input]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]);
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var joinIndex = i - 1;
var output = i;
//Analog
VideoOutputRouteFeedbacks[OutputNames[output]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]);
trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo));
//Serial
OutputNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]);
OutputRouteNameFeedbacks[OutputNames[output]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]);
}
_Chassis.OnlineStatusChange += Chassis_OnlineStatusChange;
trilist.OnlineStatusChange += (d, args) =>
{
if (!args.DeviceOnLine) return;
// feedback updates was moved to the Chassis_OnlineStatusChange
// due to the amount of time it takes for the device to come online
};
}
#endregion
#region Events
void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args)
{
IsOnline.FireUpdate();
if (!args.DeviceOnLine) return;
foreach (var feedback in Feedbacks)
{
feedback.FireUpdate();
}
if (_Chassis4x1 != null)
{
trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOn());
trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _Chassis4x1.AutoModeOff());
AutoRouteFeedback[this.Name + "-" + InputNames[1]].LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]);
}
AutoRouteFeedback.FireUpdate();
}
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
var joinIndex = i - 1;
//Digital
VideoInputSyncFeedbacks[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[i]].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + joinIndex]);
InputHdcpEnableFeedback[InputNames[i]].LinkComplementInputSig(trilist.BooleanInput[joinMap.DisableInputHdcp.JoinNumber + joinIndex]);
trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + joinIndex, () => EnableHdcp(i));
trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + joinIndex, () => DisableHdcp(i));
void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
if (args.EventId != DMOutputEventIds.VideoOutEventId) return;
//Serial
InputNameFeedbacks[InputNames[i]].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + joinIndex]);
}
var output = args.Number;
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
var joinIndex = i - 1;
//Analog
VideoOutputRouteFeedbacks[OutputNames[i]].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + joinIndex]);
trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + joinIndex, (a) => ExecuteSwitch(a, i, eRoutingSignalType.AudioVideo));
var inputNumber = _Chassis.HdmiOutputs[output].VideoOutFeedback == null
? 0
: _Chassis.HdmiOutputs[output].VideoOutFeedback.Number;
//Serial
OutputNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + joinIndex]);
OutputRouteNameFeedbacks[OutputNames[i]].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + joinIndex]);
}
var outputName = OutputNames[output];
_Chassis.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler(Chassis_OnlineStatusChange);
var feedback = VideoOutputRouteFeedbacks[outputName];
trilist.OnlineStatusChange += new Crestron.SimplSharpPro.OnlineStatusChangeEventHandler((d, args) =>
{
if (args.DeviceOnLine)
{
foreach (var feedback in Feedbacks)
if (feedback == null)
{
return;
}
var inPort =
InputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.HdmiOutputs[output].VideoOutFeedback);
var outPort = OutputPorts.FirstOrDefault(p => p.FeedbackMatchObject == _Chassis.HdmiOutputs[output]);
feedback.FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs(output, inputNumber, outPort, inPort, eRoutingSignalType.AudioVideo));
}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
switch (args.EventId)
{
case DMInputEventIds.VideoDetectedEventId:
{
Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", args.EventId);
foreach (var item in VideoInputSyncFeedbacks)
{
feedback.FireUpdate();
item.FireUpdate();
}
}
});
}
break;
}
case DMInputEventIds.InputNameFeedbackEventId:
case DMInputEventIds.InputNameEventId:
case DMInputEventIds.NameFeedbackEventId:
{
Debug.Console(1, this, "Event ID {0}: Updating name feedbacks.", args.EventId);
Debug.Console(1, this, "Input {0} Name {1}", args.Number,
_Chassis.HdmiInputs[args.Number].NameFeedback.StringValue);
foreach (var item in InputNameFeedbacks)
{
item.FireUpdate();
}
break;
}
default:
{
Debug.Console(1, this, "Unhandled DM Input Event ID {0}", args.EventId);
break;
}
}
}
#endregion
#region Factory
public class HdMdNxM4kEControllerFactory : EssentialsDeviceFactory<HdMdNxM4kEBridgeableController>
{
public HdMdNxM4kEControllerFactory()
{
TypeNames = new List<string>() { "hdmd4x14ke-bridgeable", "hdmd4x24ke", "hdmd6x24ke" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new HD-MD-NxM-4K-E Device");
var props = JsonConvert.DeserializeObject<HdMdNxM4kEBridgeablePropertiesConfig>(dc.Properties.ToString());
var type = dc.Type.ToLower();
var control = props.Control;
var ipid = control.IpIdInt;
var address = control.TcpSshProperties.Address;
switch (type)
{
case ("hdmd4x14ke-bridgeable"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x14kE(ipid, address, Global.ControlSystem), props);
case ("hdmd4x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x24kE(ipid, address, Global.ControlSystem), props);
case ("hdmd6x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd6x24kE(ipid, address, Global.ControlSystem), props);
default:
return null;
}
}
}
#endregion
#endregion
#region Events
void Chassis_OnlineStatusChange(Crestron.SimplSharpPro.GenericBase currentDevice, Crestron.SimplSharpPro.OnlineOfflineEventArgs args)
{
if (!args.DeviceOnLine) return;
for (uint i = 1; i <= _Chassis.NumberOfInputs; i++)
{
_Chassis.Inputs[i].Name.StringValue = InputNames[i];
}
for (uint i = 1; i <= _Chassis.NumberOfOutputs; i++)
{
_Chassis.Outputs[i].Name.StringValue = OutputNames[i];
}
foreach (var feedback in Feedbacks)
{
feedback.FireUpdate();
}
}
void Chassis_DMOutputChange(Switch device, DMOutputEventArgs args)
{
if (args.EventId != DMOutputEventIds.VideoOutEventId) return;
for (var i = 0; i < VideoOutputRouteFeedbacks.Count; i++)
{
var index = i;
var localInputPort = InputPorts.FirstOrDefault(p => (DMInput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1].VideoOutFeedback);
var localOutputPort =
OutputPorts.FirstOrDefault(p => (DMOutput)p.FeedbackMatchObject == _Chassis.HdmiOutputs[(uint)index + 1]);
VideoOutputRouteFeedbacks[i].FireUpdate();
OnSwitchChange(new RoutingNumericEventArgs((ushort)i, VideoOutputRouteFeedbacks[i].UShortValue, localOutputPort, localInputPort, eRoutingSignalType.AudioVideo));
}
}
void Chassis_DMInputChange(Switch device, DMInputEventArgs args)
{
if (args.EventId != DMInputEventIds.VideoDetectedEventId) return;
foreach (var item in VideoInputSyncFeedbacks)
{
item.FireUpdate();
}
}
#endregion
#region Factory
public class HdMdNxM4kEControllerFactory : EssentialsDeviceFactory<HdMdNxM4kEBridgeableController>
{
public HdMdNxM4kEControllerFactory()
{
TypeNames = new List<string>() { "hdmd4x14ke-bridgeable", "hdmd4x24ke", "hdmd6x24ke" };
}
public override EssentialsDevice BuildDevice(DeviceConfig dc)
{
Debug.Console(1, "Factory Attempting to create new HD-MD-NxM-4K-E Device");
var props = JsonConvert.DeserializeObject<HdMdNxM4kEBridgeablePropertiesConfig>(dc.Properties.ToString());
var type = dc.Type.ToLower();
var control = props.Control;
var ipid = control.IpIdInt;
var address = control.TcpSshProperties.Address;
switch (type)
{
case ("hdmd4x14ke-bridgeable"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x14kE(ipid, address, Global.ControlSystem), props);
case ("hdmd4x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd4x24kE(ipid, address, Global.ControlSystem), props);
case ("hdmd6x24ke"):
return new HdMdNxM4kEBridgeableController(dc.Key, dc.Name, new HdMd6x24kE(ipid, address, Global.ControlSystem), props);
default:
return null;
}
}
}
#endregion
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DM;
using Newtonsoft.Json;
@@ -13,6 +14,7 @@ using PepperDash.Essentials.DM.Config;
namespace PepperDash.Essentials.DM.Chassis
{
[Obsolete("Please use HdMdNxM4kEBridgeable Controller")]
public class HdMdNxM4kEController : CrestronGenericBaseDevice, IRoutingInputsOutputs, IRouting
{
public HdMdNxM Chassis { get; private set; }
@@ -31,6 +33,7 @@ namespace PepperDash.Essentials.DM.Chassis
HdMdNxM4kEPropertiesConfig props)
: base(key, name, chassis)
{
Debug.Console(0, this, "Type hdmd4x14ke is obsolete. Please use hdmd4x14ke-bridgeable");
Chassis = chassis;
// logical ports
@@ -43,14 +46,19 @@ namespace PepperDash.Essentials.DM.Chassis
OutputPorts = new RoutingPortCollection<RoutingOutputPort>();
OutputPorts.Add(new RoutingOutputPort(DmPortName.HdmiOut, eRoutingSignalType.Audio | eRoutingSignalType.Video,
eRoutingPortConnectionType.Hdmi, null, this));
// physical settings
if (props != null && props.Inputs != null)
{
var inputRegex = new Regex(@"(?<InputNum>\d)", RegexOptions.IgnoreCase);
foreach (var kvp in props.Inputs)
{
// strip "hdmiIn"
var inputNum = Convert.ToUInt32(kvp.Key.Substring(6));
// get numnbers from key and convert to int
//var inputNum = Convert.ToUInt32(kvp.Key.Substring(6));
var inputMatch = inputRegex.Match(kvp.Key);
if (inputMatch == null) continue;
var inputNum = Convert.ToUInt32(inputMatch.Groups["InputNum"].Value);
var port = chassis.HdmiInputs[inputNum].HdmiInputPort;
// set hdcp disables

View File

@@ -216,10 +216,20 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
var presetsCamera = cameraDevice as IHasCameraPresets;
presetsCamera.PresetsListHasChanged += new EventHandler<EventArgs>((o, a) =>
{
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
});
for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++)
{
int tempNum = i - 1;
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
string label = "";
var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i));
if (preset != null)
label = preset.Description;
trilist.SetString((ushort) (joinMap.PresetLabelStart.JoinNumber + tempNum), label);
}
});
for (int i = 0; i < joinMap.NumberOfPresets.JoinNumber; i++)
{
@@ -236,35 +246,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
presetsCamera.PresetStore(tempNum, label);
});
}
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine)
{ return; }
SendCameraPresetNamesToApi(presetsCamera, joinMap, trilist);
};
}
}
private void SendCameraPresetNamesToApi(IHasCameraPresets presetsCamera, CameraControllerJoinMap joinMap, BasicTriList trilist)
{
for (int i = 1; i <= joinMap.NumberOfPresets.JoinNumber; i++)
{
int tempNum = i - 1;
string label = "";
var preset = presetsCamera.Presets.FirstOrDefault(p => p.ID.Equals(i));
if (preset != null)
label = preset.Description;
trilist.SetString((ushort)(joinMap.PresetLabelStart.JoinNumber + tempNum), label);
}
}
}
public class CameraPreset : PresetBase
{
public CameraPreset(int id, string description, bool isDefined, bool isDefinable)

View File

@@ -525,15 +525,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
public event EventHandler<EventArgs> PresetsListHasChanged;
protected void OnPresetsListHasChanged()
{
var handler = PresetsListHasChanged;
if (handler == null)
return;
handler.Invoke(this, EventArgs.Empty);
}
public List<CameraPreset> Presets { get; private set; }
public void PresetSelect(int preset)
@@ -546,7 +537,6 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
SavePreset(preset);
}
#endregion
#region IHasCameraFocusControl Members

View File

@@ -121,6 +121,7 @@
<Compile Include="Cameras\CameraControl.cs" />
<Compile Include="Display\PanasonicThDisplay.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingInfo.cs" />
<Compile Include="VideoCodec\Interfaces\IHasMeetingLock.cs" />
<Compile Include="VideoCodec\Interfaces\IHasParticipants.cs" />
<Compile Include="VideoCodec\Interfaces\IHasPresentationOnlyMeeting.cs" />
<Compile Include="VideoCodec\Interfaces\IHasSelfviewPosition.cs" />

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
{
public interface IHasMeetingLock
{
BoolFeedback MeetingIsLockedFeedback { get; }
void LockMeeting();
void UnLockMeeting();
void ToggleMeetingLock();
}
}

View File

@@ -12,6 +12,18 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
public interface IHasParticipants
{
CodecParticipants Participants { get; }
/// <summary>
/// Removes the participant from the meeting
/// </summary>
/// <param name="participant"></param>
void RemoveParticipant(int userId);
/// <summary>
/// Sets the participant as the new host
/// </summary>
/// <param name="participant"></param>
void SetParticipantAsHost(int userId);
}
/// <summary>
@@ -29,6 +41,11 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.Interfaces
/// </summary>
public interface IHasParticipantAudioMute : IHasParticipantVideoMute
{
/// <summary>
/// Mute audio of all participants
/// </summary>
void MuteAudioForAllParticipants();
void MuteAudioForParticipant(int userId);
void UnmuteAudioForParticipant(int userId);
void ToggleAudioForParticipant(int userId);

View File

@@ -298,6 +298,13 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec
}
LinkVideoCodecToApi(codec, trilist, joinMap);
trilist.OnlineStatusChange += (device, args) =>
{
if (!args.DeviceOnLine) return;
trilist.SetString(joinMap.Schedule.JoinNumber, "\xFC");
};
}
/// <summary>
@@ -785,6 +792,16 @@ ScreenIndexIsPinnedTo: {8} (a{17})
_currentMeetings = codec.CodecSchedule.Meetings.Where(m => m.StartTime >= currentTime || m.EndTime >= currentTime).ToList();
if (_currentMeetings.Count == 0)
{
var emptyXSigByteArray = XSigHelpers.ClearOutputs();
var emptyXSigString = Encoding.GetEncoding(XSigEncoding)
.GetString(emptyXSigByteArray, 0, emptyXSigByteArray.Length);
trilist.SetString(joinMap.Schedule.JoinNumber, emptyXSigString);
return;
}
var meetingsData = UpdateMeetingsListXSig(_currentMeetings);
trilist.SetString(joinMap.Schedule.JoinNumber, meetingsData);
trilist.SetUshort(joinMap.MeetingCount.JoinNumber, (ushort)_currentMeetings.Count);

View File

@@ -1123,9 +1123,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
public class Lock
public class Lock : NotifiableObject
{
public bool Enable { get; set; }
private bool _enable;
public bool Enable
{
get
{
return _enable;
}
set
{
if (value != _enable)
{
_enable = value;
NotifyPropertyChanged("Enable");
}
}
}
}
public class ClosedCaption

View File

@@ -26,7 +26,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
IRouting,
IHasScheduleAwareness, IHasCodecCameras, IHasParticipants, IHasCameraOff, IHasCameraMute, IHasCameraAutoMode,
IHasFarEndContentStatus, IHasSelfviewPosition, IHasPhoneDialing, IHasZoomRoomLayouts, IHasParticipantPinUnpin,
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting
IHasParticipantAudioMute, IHasSelfviewSize, IPasswordPrompt, IHasStartMeeting, IHasMeetingInfo, IHasPresentationOnlyMeeting, IHasMeetingLock
{
private const long MeetingRefreshTimer = 60000;
public uint DefaultMeetingDurationMin { get; private set; }
@@ -147,6 +147,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
ContentSwappedWithThumbnailFeedback = new BoolFeedback(ContentSwappedWithThumbnailFeedbackFunc);
NumberOfScreensFeedback = new IntFeedback(NumberOfScreensFeedbackFunc);
MeetingIsLockedFeedback = new BoolFeedback(() => Configuration.Call.Lock.Enable );
}
public CommunicationGather PortGather { get; private set; }
@@ -597,6 +599,14 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
};
Configuration.Call.Lock.PropertyChanged += (o, a) =>
{
if (a.PropertyName == "Enable")
{
MeetingIsLockedFeedback.FireUpdate();
}
};
// This is to deal with incorrect object structure coming back from the Zoom Room on v 5.6.3
Configuration.Client.Call.Layout.PropertyChanged += (o, a) =>
{
@@ -1306,11 +1316,16 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
var codecBookings = JsonConvert.DeserializeObject<List<zCommand.BookingsListResult>>(
responseObj.ToString());
if (codecBookings != null && codecBookings.Count > 0)
{
CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult(
codecBookings, CodecSchedule.MeetingWarningMinutes);
}
if (codecBookings != null && codecBookings.Count > 0)
{
CodecSchedule.Meetings = zCommand.GetGenericMeetingsFromBookingResult(
codecBookings, CodecSchedule.MeetingWarningMinutes);
}
else
{
//need to clear the list if it's empty
CodecSchedule.Meetings = new List<Meeting>();
}
break;
}
@@ -2329,6 +2344,56 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
}
/// <summary>
/// Invites contacts to a new meeting for a specified duration
/// </summary>
/// <param name="contacts"></param>
/// <param name="duration"></param>
public void InviteContactsToNewMeeting(InvitableDirectoryContact[] contacts, uint duration)
{
if(duration == 0)
{
duration = DefaultMeetingDurationMin;
}
StringBuilder message = new StringBuilder();
// Add the prefix
message.Append(string.Format("zCommand Invite Duration: {0}", duration));
// Add each invitee
foreach (var contact in contacts)
{
var invitee = string.Format(" user: {0}", contact.ContactId);
message.Append(invitee);
}
SendText(message.ToString());
}
/// <summary>
/// Invites contacts to an existing meeting
/// </summary>
/// <param name="contacts"></param>
public void InviteContactsToExistingMeeting(InvitableDirectoryContact[] contacts)
{
StringBuilder message = new StringBuilder();
// Add the prefix
message.Append(string.Format("zCommand Call Invite"));
// Add each invitee
foreach (var contact in contacts)
{
var invitee = string.Format(" user: {0}", contact.ContactId);
message.Append(invitee);
}
SendText(message.ToString());
}
/// <summary>
/// Starts a PMI Meeting for the specified duration (or default meeting duration if 0 is specified)
@@ -2464,10 +2529,25 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
public CodecParticipants Participants { get; private set; }
public void RemoveParticipant(int userId)
{
SendText(string.Format("zCommand Call Expel Id: {0}", userId));
}
public void SetParticipantAsHost(int userId)
{
SendText(string.Format("zCommand Call HostChange Id: {0}", userId));
}
#endregion
#region IHasParticipantAudioMute Members
public void MuteAudioForAllParticipants()
{
SendText(string.Format("zCommand Call MuteAll Mute: on"));
}
public void MuteAudioForParticipant(int userId)
{
SendText(string.Format("zCommand Call MuteParticipant Mute: on Id: {0}", userId));
@@ -3029,7 +3109,35 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom
}
#endregion
}
#region IHasMeetingLock Members
public BoolFeedback MeetingIsLockedFeedback { get; private set; }
public void LockMeeting()
{
SendText(string.Format("zConfiguration Call Lock Enable: on"));
}
public void UnLockMeeting()
{
SendText(string.Format("zConfiguration Call Lock Enable: off"));
}
public void ToggleMeetingLock()
{
if (MeetingIsLockedFeedback.BoolValue)
{
UnLockMeeting();
}
else
{
LockMeeting();
}
}
#endregion
}
/// <summary>
/// Zoom Room specific info object

View File

@@ -1,3 +1,3 @@
<packages>
<package id="PepperDashCore" version="1.0.48" targetFramework="net35" allowedVersions="[1.0,1.1)"/>
<package id="PepperDashCore" version="1.1.0" targetFramework="net35" allowedVersions="[1.0,2.0)"/>
</packages>