diff --git a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
index d307d088..3897afa5 100644
--- a/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
+++ b/PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
@@ -120,14 +120,22 @@ namespace PepperDash.Essentials
/// 1206
///
public const uint VCRecentsVisible = 1206;
- ///
- /// 1207
- ///
- public const uint VCCameraVisible = 1207;
+
///
/// 1208
///
- public const uint VCSelfViewLayoutVisible = 1208;
+ public const uint VCCameraAutoVisible = 1208;
+
+ ///
+ /// 1209
+ ///
+ public const uint VCCameraManualVisible = 1209;
+
+ ///
+ /// 1210
+ ///
+ public const uint VCCameraOffVisible = 1210;
+
///
/// 1211 - 1215
///
@@ -225,6 +233,45 @@ namespace PepperDash.Essentials
///
public const uint VCMinMaxEnable = 1256;
+ ///
+ /// 1260
+ ///
+ public const uint VCCameraModeBarVisible = 1260;
+
+ ///
+ /// 1261
+ ///
+ public const uint VCCameraSelectBarWithoutModeVisible = 1261;
+
+
+ ///
+ /// 1271
+ ///
+ public const uint VCCameraZoomIn = 1271;
+ ///
+ /// 1272
+ ///
+ public const uint VCCameraZoomOut = 1272;
+
+
+ ///
+ /// 1280
+ ///
+ public const uint VCCameraPresetSavedLabelVisible = 1280;
+ ///
+ /// 1281
+ ///
+ public const uint VCCameraPreset1 = 1281;
+ ///
+ /// 1282
+ ///
+ public const uint VCCameraPreset2 = 1282;
+ ///
+ /// 1283
+ ///
+ public const uint VCCameraPreset3 = 1283;
+
+
// Letter joins start at 2921;
//******************************************************
diff --git a/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs b/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs
index 8da0b355..b48d78c9 100644
--- a/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs
+++ b/PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs
@@ -33,6 +33,21 @@
///
public const uint VCLayoutsList = 1205;
+ ///
+ /// 1206 VC Camera Mode horizontal list
+ ///
+ public const uint VCCameraMode = 1206;
+
+ ///
+ /// 1207 VC Camera Mode Dpad
+ ///
+ public const uint VCCameraDpad = 1207;
+
+ ///
+ /// 1208 VC Camera Select
+ ///
+ public const uint VCCameraSelect = 1208;
+
//******************************************************
// General
diff --git a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
index ea60526b..9b2b8a95 100644
--- a/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
+++ b/PepperDashEssentials/UI/JoinConstants/UIStringlJoin.cs
@@ -41,6 +41,21 @@ namespace PepperDash.Essentials
public const uint VCRecentListTimeTextStart = 1231;
// RANGE IN USE
public const uint VCRecentListTimeTextEnd = 1260;
+
+
+ ///
+ /// 1281
+ ///
+ public const uint VCCameraPresetLabel1 = 1281;
+ ///
+ /// 1282
+ ///
+ public const uint VCCameraPresetLabel2 = 1282;
+ ///
+ /// 1283
+ ///
+ public const uint VCCameraPresetLabel3 = 1283;
+
///
/// 1291 - the current layout mode
///
diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
index 55811d44..0c219426 100644
--- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
+++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
+using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using PepperDash.Core;
@@ -13,6 +14,7 @@ using PepperDash.Essentials.Core.SmartObjects;
using PepperDash.Essentials.Core.Touchpanels.Keyboards;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
+using PepperDash.Essentials.Devices.Common.Cameras;
namespace PepperDash.Essentials.UIDrivers.VC
{
@@ -41,6 +43,11 @@ namespace PepperDash.Essentials.UIDrivers.VC
///
JoinedSigInterlock VCControlsInterlock;
+ ///
+ /// For the camera control mode (auto/manual/off)
+ ///
+ JoinedSigInterlock VCCameraControlModeInterlock;
+
///
/// For the different staging bars: Active, inactive
///
@@ -58,6 +65,12 @@ namespace PepperDash.Essentials.UIDrivers.VC
SmartObjectDynamicList RecentCallsList;
SmartObjectDynamicList DirectoryList;
+
+ SmartObjectDPad CameraPtzPad;
+
+ SmartObjectDynamicList CameraModeList;
+
+ SmartObjectDynamicList CameraSelectList;
BoolFeedback DirectoryBackButtonVisibleFeedback;
@@ -76,6 +89,8 @@ namespace PepperDash.Essentials.UIDrivers.VC
bool CodecHasFavorites;
+ bool ShowCameraModeControls;
+
CTimer BackspaceTimer;
@@ -118,6 +133,9 @@ namespace PepperDash.Essentials.UIDrivers.VC
LocalPrivacyIsMuted = new BoolFeedback(() => false);
VCControlsInterlock = new JoinedSigInterlock(triList);
+ VCCameraControlModeInterlock = new JoinedSigInterlock(triList);
+
+
if (CodecHasFavorites)
VCControlsInterlock.SetButDontShow(UIBoolJoin.VCKeypadWithFavoritesVisible);
else
@@ -161,6 +179,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
SetupDirectoryList();
+
SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0);
SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]);
@@ -196,6 +215,8 @@ namespace PepperDash.Essentials.UIDrivers.VC
if(HeaderDriver.HeaderButtonsAreSetUp)
HeaderDriver.ComputeHeaderCallStatus(Codec);
+
+ SetupCameraControls();
}
void SetupAddresses()
@@ -450,6 +471,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
TriList.SetSigFalseAction(UIBoolJoin.VCStagingDirectoryPress, ShowDirectory);
TriList.SetSigFalseAction(UIBoolJoin.VCStagingKeypadPress, ShowKeypad);
TriList.SetSigFalseAction(UIBoolJoin.VCStagingRecentsPress, ShowRecents);
+ TriList.SetSigFalseAction(UIBoolJoin.VCStagingCameraPress, ShowCameraControls);
TriList.SetSigFalseAction(UIBoolJoin.VCStagingConnectPress, ConnectPress);
TriList.SetSigFalseAction(UIBoolJoin.CallEndPress, () =>
{
@@ -467,6 +489,365 @@ namespace PepperDash.Essentials.UIDrivers.VC
});
}
+ void SetupCameraControls()
+ {
+ CameraPtzPad = new SmartObjectDPad(TriList.SmartObjects[UISmartObjectJoin.VCCameraDpad], true);
+
+ // If the codec supports camera auto or off, we need to show the mode selector subpage
+ ShowCameraModeControls = Codec is IHasCameraAutoMode || Codec is IHasCameraOff;
+
+ if (ShowCameraModeControls)
+ {
+ CameraModeList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCCameraMode], true, 0);
+
+ VCControlsInterlock.StatusChanged += new EventHandler(VCControlsInterlock_StatusChanged);
+
+
+ var codecOffCameras = Codec as IHasCameraOff;
+
+ var codecAutoCameras = Codec as IHasCameraAutoMode;
+
+ if (codecAutoCameras != null)
+ {
+ CameraModeList.SetItemButtonAction(1,(b) => codecAutoCameras.CameraAutoModeOn());
+ TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 1 Visible"].BoolValue = true;
+ codecAutoCameras.CameraAutoModeIsOnFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 1 Selected"]);
+ //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 1 Pressed"].SetSigFalseAction(
+ //() => codecAutoCameras.CameraAutoModeOn());
+
+
+ codecAutoCameras.CameraAutoModeIsOnFeedback.OutputChange += (o, a) =>
+ {
+ if (a.BoolValue)
+ {
+ SetCameraManualModeButtonFeedback(false);
+
+ if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCCameraModeBarVisible)
+ {
+ VCCameraControlModeInterlock.ShowInterlocked(UIBoolJoin.VCCameraAutoVisible);
+ }
+ else
+ {
+ VCCameraControlModeInterlock.SetButDontShow(UIBoolJoin.VCCameraAutoVisible);
+ }
+ }
+ else
+ {
+ ShowCameraManualMode();
+ }
+
+ };
+ }
+
+ // Manual button always visible
+ CameraModeList.SetItemButtonAction(2, (b) => ShowCameraManualMode());
+
+ TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 2 Visible"].BoolValue = true;
+ //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 2 Pressed"].SetSigFalseAction(
+ // () => ShowCameraManualMode());
+
+ if (codecOffCameras != null)
+ {
+ TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 3 Visible"].BoolValue = true;
+ codecOffCameras.CameraIsOffFeedback.LinkInputSig(CameraModeList.SmartObject.BooleanInput["Item 3 Selected"]);
+ CameraModeList.SetItemButtonAction(3, (b) => codecOffCameras.CameraOff());
+ //TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanOutput["Item 3 Pressed"].SetSigFalseAction(
+ // () => codecOffCameras.CameraOff());
+
+ codecOffCameras.CameraIsOffFeedback.OutputChange += (o, a) =>
+ {
+ if (a.BoolValue)
+ {
+ SetCameraManualModeButtonFeedback(false);
+
+ if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCCameraModeBarVisible)
+ {
+ VCCameraControlModeInterlock.ShowInterlocked(UIBoolJoin.VCCameraOffVisible);
+ }
+ else
+ {
+ VCCameraControlModeInterlock.SetButDontShow(UIBoolJoin.VCCameraOffVisible);
+ }
+ }
+ else
+ {
+ ShowCameraManualMode();
+ }
+
+ };
+ }
+ }
+
+ var camerasCodec = Codec as IHasCameras;
+
+ if(camerasCodec != null)
+ {
+ //CameraSelectList = new SmartObjectDynamicList(TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect], true, 0);
+
+ var so = TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect];
+
+ so.SigChange += SmartObject_SigChange;
+
+ for (uint i = 1; i <= camerasCodec.Cameras.Count; i++)
+ {
+ var cameraKey = camerasCodec.Cameras[(int)i - 1].Key;
+ Debug.Console(1, "Setting up action for Camera {0} with Key: {1} for button Item {0} Pressed", i, cameraKey);
+
+ //TODO: Fix camera selection action. For some reson this action doesn't execute when the buttons are pressed
+
+ var sig = so.BooleanOutput[String.Format("Item {0} Pressed", i)];
+
+ so.BooleanOutput[string.Format("Item {0} Pressed", i)].SetSigFalseAction(
+ () => camerasCodec.SelectCamera(cameraKey));
+ }
+
+ so.UShortInput["Set Number of Items"].UShortValue = (ushort)camerasCodec.Cameras.Count;
+ //TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect].UShortOutput["Item Clicked"].SetUShortSigAction(
+ // (u) =>
+ // {
+ // var cameraKey = camerasCodec.Cameras[u - 1].Key;
+ // Debug.Console(1, "Selecting Camera {0} with Key: {1}", u, cameraKey);
+ // camerasCodec.SelectCamera(cameraKey);
+ // });
+
+
+ // Set the names for the cameras
+ for (int i = 1; i <= camerasCodec.Cameras.Count; i++)
+ {
+ so.StringInput[string.Format("Set Item {0} Text", i)].StringValue = camerasCodec.Cameras[i - 1].Name;
+ }
+
+ SetCameraSelectedFeedback();
+ camerasCodec.CameraSelected += camerasCodec_CameraSelected;
+ MapCameraActions();
+ }
+
+ SetupPresets();
+
+ }
+
+ void SmartObject_SigChange(GenericBase currentDevice, SmartObjectEventArgs args)
+ {
+ var uo = args.Sig.UserObject;
+ if (uo is Action)
+ (uo as Action)(args.Sig.BoolValue);
+ else if (uo is Action)
+ (uo as Action)(args.Sig.UShortValue);
+ else if (uo is Action)
+ (uo as Action)(args.Sig.StringValue);
+ }
+
+ void VCControlsInterlock_StatusChanged(object sender, StatusChangedEventArgs e)
+ {
+ // Need to hide the camera mode interlock if the mode bar gets hidden
+ if (e.PreviousJoin == UIBoolJoin.VCCameraModeBarVisible)
+ VCCameraControlModeInterlock.Hide();
+
+ // These deal with hiding/showing the camera select bar if no mode controls are visible (tied to manual controls being visible)
+ if(!ShowCameraModeControls)
+ {
+ if(e.PreviousJoin == UIBoolJoin.VCCameraManualVisible)
+ TriList.SetBool(UIBoolJoin.VCCameraSelectBarWithoutModeVisible, false);
+
+ if (e.NewJoin == UIBoolJoin.VCCameraManualVisible)
+ TriList.SetBool(UIBoolJoin.VCCameraSelectBarWithoutModeVisible, true);
+ }
+
+
+ }
+
+
+ ///
+ /// Shows the preset saved label for 2 seconds
+ ///
+ void ShowPresetStoreFeedback()
+ {
+ TriList.BooleanInput[UIBoolJoin.VCCameraPresetSavedLabelVisible].BoolValue = true;
+
+ var timer = new CTimer((o) => TriList.BooleanInput[UIBoolJoin.VCCameraPresetSavedLabelVisible].BoolValue = false, 2000);
+ }
+
+ void presetsCodec_CodecRoomPresetsListHasChanged(object sender, EventArgs e)
+ {
+ SetupPresets();
+ }
+
+
+ void camerasCodec_CameraSelected(object sender, CameraSelectedEventArgs e)
+ {
+ MapCameraActions();
+
+ SetCameraSelectedFeedback();
+ }
+
+ ///
+ /// Set the feedback for the button of the selected camera
+ ///
+ void SetCameraSelectedFeedback()
+ {
+ var camerasCodec = Codec as IHasCameras;
+
+ for (int i = 1; i <= camerasCodec.Cameras.Count; i++)
+ {
+ var cameraSelected = camerasCodec.SelectedCameraFeedback.StringValue;
+ var state = false;
+ if (cameraSelected == camerasCodec.Cameras[i - 1].Key)
+ {
+ state = true;
+ }
+
+ TriList.SmartObjects[UISmartObjectJoin.VCCameraSelect].BooleanInput[string.Format("Item {0} Selected", i)].BoolValue = state;
+ }
+
+ }
+
+ void SetupPresets()
+ {
+ var presetsCodec = Codec as IHasCodecRoomPresets;
+ if (presetsCodec != null)
+ {
+ uint holdTime = 5000;
+ presetsCodec.CodecRoomPresetsListHasChanged += new EventHandler(presetsCodec_CodecRoomPresetsListHasChanged);
+
+ TriList.BooleanOutput[UIBoolJoin.VCCameraPreset1].SetSigHeldAction(
+ holdTime, () => presetsCodec.CodecRoomPresetStore(1, presetsCodec.NearEndPresets[0].Description), ShowPresetStoreFeedback, () => presetsCodec.CodecRoomPresetSelect(1));
+ TriList.BooleanOutput[UIBoolJoin.VCCameraPreset2].SetSigHeldAction(
+ holdTime, () => presetsCodec.CodecRoomPresetStore(2, presetsCodec.NearEndPresets[1].Description), ShowPresetStoreFeedback, () => presetsCodec.CodecRoomPresetSelect(2));
+ TriList.BooleanOutput[UIBoolJoin.VCCameraPreset3].SetSigHeldAction(
+ holdTime, () => presetsCodec.CodecRoomPresetStore(3, presetsCodec.NearEndPresets[2].Description), ShowPresetStoreFeedback, () => presetsCodec.CodecRoomPresetSelect(3));
+
+ TriList.StringInput[UIStringJoin.VCCameraPresetLabel1].StringValue = presetsCodec.NearEndPresets[0].Description;
+ TriList.StringInput[UIStringJoin.VCCameraPresetLabel2].StringValue = presetsCodec.NearEndPresets[1].Description;
+ TriList.StringInput[UIStringJoin.VCCameraPresetLabel3].StringValue = presetsCodec.NearEndPresets[2].Description;
+
+ }
+ }
+
+ ///
+ /// Maps button actions to the selected camera
+ ///
+ void MapCameraActions()
+ {
+ // Now we setup the button actions for the manual controls
+ var camerasCodec = Codec as IHasCameras;
+
+ if (camerasCodec != null && camerasCodec.SelectedCamera != null)
+ {
+
+ var dpad = CameraPtzPad;
+
+ var camera = camerasCodec.SelectedCamera as IHasCameraPtzControl;
+ if (camera != null)
+ {
+ if (camerasCodec.SelectedCamera.CanTilt)
+ {
+ dpad.SigUp.SetBoolSigAction((b) =>
+ {
+ if (b)
+ camera.TiltUp();
+ else
+ camera.TiltStop();
+ });
+ dpad.SigDown.SetBoolSigAction((b) =>
+ {
+ if (b)
+ camera.TiltDown();
+ else
+ camera.TiltStop();
+ });
+ }
+
+ if (camerasCodec.SelectedCamera.CanPan)
+ {
+ dpad.SigLeft.SetBoolSigAction((b) =>
+ {
+ if (b)
+ camera.PanLeft();
+ else
+ camera.PanStop();
+ });
+ dpad.SigRight.SetBoolSigAction((b) =>
+ {
+ if (b)
+ camera.PanRight();
+ else
+ camera.PanStop();
+ });
+ }
+
+
+ //dpad.SigCenter.SetSigFalseAction(() => camera.PositionHome());
+
+ //var homeButton = dpad.BooleanOutput["Home"];
+ //if (homeButton != null)
+ //{
+ // homeButton.SetSigFalseAction(() => camera.PositionHome());
+ //}
+
+ if (camerasCodec.SelectedCamera.CanZoom)
+ {
+ TriList.BooleanOutput[UIBoolJoin.VCCameraZoomIn].SetBoolSigAction((b) =>
+ {
+ if (b)
+ camera.ZoomIn();
+ else
+ camera.ZoomStop();
+ });
+ TriList.BooleanOutput[UIBoolJoin.VCCameraZoomOut].SetBoolSigAction((b) =>
+ {
+ if (b)
+ camera.ZoomOut();
+ else
+ camera.ZoomStop();
+ });
+ }
+
+ }
+ }
+ }
+
+ // Determines if codec is in manual camera control mode and shows feedback
+ void ShowCameraManualMode()
+ {
+ var inManualMode = true;
+
+ var codecOffCameras = Codec as IHasCameraOff;
+
+ var codecAutoCameras = Codec as IHasCameraAutoMode;
+
+ if (codecOffCameras != null && codecOffCameras.CameraIsOffFeedback.BoolValue)
+ {
+ inManualMode = false;
+ }
+
+ // Clear auto mode
+ if (codecAutoCameras != null )
+ {
+ if (codecAutoCameras.CameraAutoModeIsOnFeedback.BoolValue)
+ {
+ codecAutoCameras.CameraAutoModeOff();
+ inManualMode = true;
+ }
+ }
+
+ if (inManualMode)
+ {
+ VCCameraControlModeInterlock.SetButDontShow(UIBoolJoin.VCCameraManualVisible);
+
+ if (VCControlsInterlock.CurrentJoin == UIBoolJoin.VCCameraModeBarVisible)
+ VCCameraControlModeInterlock.Show();
+ }
+
+ SetCameraManualModeButtonFeedback(inManualMode);
+
+ }
+
+ void SetCameraManualModeButtonFeedback(bool state)
+ {
+ // Set button feedback for manual mode
+ TriList.SmartObjects[UISmartObjectJoin.VCCameraMode].BooleanInput["Item 2 Selected"].BoolValue = state;
+ }
+
///
///
///
@@ -927,7 +1308,32 @@ namespace PepperDash.Essentials.UIDrivers.VC
///
void ShowCameraControls()
{
- VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraVisible);
+ if (ShowCameraModeControls)
+ {
+ VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraModeBarVisible);
+
+ if (VCCameraControlModeInterlock.CurrentJoin != 0)
+ {
+ VCCameraControlModeInterlock.Show();
+ }
+ else
+ {
+ var codecAutoCamera = Codec as IHasCameraAutoMode;
+ if (codecAutoCamera != null)
+ {
+ ShowCameraManualMode();
+ VCCameraControlModeInterlock.Show();
+ }
+ }
+ }
+ else
+ {
+ // Just show the manual camera control page
+ VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraManualVisible);
+ }
+
+
+
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingCameraPress);
}
@@ -960,7 +1366,7 @@ namespace PepperDash.Essentials.UIDrivers.VC
///
void ShowSelfViewLayout()
{
- VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCSelfViewLayoutVisible);
+ VCControlsInterlock.ShowInterlocked(UIBoolJoin.VCCameraAutoVisible);
StagingButtonsFeedbackInterlock.ShowInterlocked(UIBoolJoin.VCStagingSelfViewLayoutPress);
}
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs
index e2dfadbc..161cba45 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Remotes/Hrxx0WirelessRemoteController.cs
@@ -18,32 +18,29 @@ using PepperDash.Essentials.Core.Bridges;
namespace PepperDash.Essentials.Core
{
- [Description("Wrapper class for all HR-Series remotes")]
- public class Hrxx0WirelessRemoteController : EssentialsBridgeableDevice, IHasFeedback
+ [Description("Wrapper class for all HR-Series remotes")]
+ public class Hrxx0WirelessRemoteController : EssentialsBridgeableDevice, IHasFeedback, IHR52Button
{
private CenRfgwController _gateway;
private GatewayBase _gatewayBase;
-
- private Hr1x0WirelessRemoteBase _remote;
-
+ private Hr1x0WirelessRemoteBase _remote;
+
public FeedbackCollection Feedbacks { get; set; }
public CrestronCollection