diff --git a/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs b/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs
index 8b82a771..053d3895 100644
--- a/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs
+++ b/src/PepperDash.Essentials.Core/Devices/DestinationListItem.cs
@@ -116,5 +116,12 @@ namespace PepperDash.Essentials.Core
///
[JsonProperty("supportsUsb")]
public bool SupportsUsb { get; set; }
+
+ ///
+ /// The key of the destination port associated with this destination item
+ /// This is used to identify the specific port on the destination device that this item refers to for advanced routing
+ ///
+ [JsonProperty("destinationPortKey")]
+ public string DestinationPortKey { get; set; }
}
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs b/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs
index ddd76d54..d4fac061 100644
--- a/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs
+++ b/src/PepperDash.Essentials.Core/Devices/SourceListItem.cs
@@ -183,6 +183,13 @@ namespace PepperDash.Essentials.Core
[JsonProperty("supportsUsb")]
public bool SupportsUsb { get; set; }
+ ///
+ /// The key of the source port associated with this source item
+ /// This is used to identify the specific port on the source device that this item refers to for advanced routing
+ ///
+ [JsonProperty("sourcePortKey")]
+ public string SourcePortKey { get; set; }
+
///
/// Default constructor for SourceListItem, initializes the Icon to "Blank"
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs
index f1176730..cec2f58b 100644
--- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs
@@ -3,35 +3,60 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
-
+using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Cameras
{
///
- /// Enumeration of eCameraControlMode values
+ /// Enum for camera control modes
///
public enum eCameraControlMode
- {
+ {
+ ///
+ /// Manual control mode, where the camera is controlled directly by the user or system
+ ///
Manual = 0,
+ ///
+ /// Off control mode, where the camera is turned off or disabled
+ ///
Off,
+ ///
+ /// Auto control mode, where the camera automatically adjusts settings based on the environment or conditions
+ ///
Auto
}
///
- /// Defines the contract for IHasCameras
+ /// Interface for devices that have cameras
///
- public interface IHasCameras
+ public interface IHasCameras : IKeyName
{
+ ///
+ /// Event that is raised when a camera is selected
+ ///
event EventHandler CameraSelected;
+ ///
+ /// List of cameras on the device. This should be a list of CameraBase objects
+ ///
List Cameras { get; }
+ ///
+ /// The currently selected camera. This should be a CameraBase object
+ ///
CameraBase SelectedCamera { get; }
+ ///
+ /// Feedback that indicates the currently selected camera
+ ///
StringFeedback SelectedCameraFeedback { get; }
+ ///
+ /// Selects a camera from the list of available cameras based on the provided key.
+ ///
+ /// The unique identifier or name of the camera to select.
void SelectCamera(string key);
}
@@ -48,7 +73,14 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraOff
{
+ ///
+ /// Feedback that indicates whether the camera is off
+ ///
BoolFeedback CameraIsOffFeedback { get; }
+
+ ///
+ /// Turns the camera off, blanking the near end video
+ ///
void CameraOff();
}
@@ -57,19 +89,40 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraMute
{
+ ///
+ /// Feedback that indicates whether the camera is muted
+ ///
BoolFeedback CameraIsMutedFeedback { get; }
+
+ ///
+ /// Mutes the camera video, preventing it from being sent to the far end
+ ///
void CameraMuteOn();
+
+ ///
+ /// Unmutes the camera video, allowing it to be sent to the far end
+ ///
void CameraMuteOff();
+
+ ///
+ /// Toggles the camera mute state. If the camera is muted, it will be unmuted, and vice versa.
+ ///
void CameraMuteToggle();
}
+ ///
+ /// Interface for devices that can mute and unmute their camera video, with an event for unmute requests
+ ///
public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute
{
+ ///
+ /// Event that is raised when a video unmute is requested, typically by the far end
+ ///
event EventHandler VideoUnmuteRequested;
}
///
- /// Represents a CameraSelectedEventArgs
+ /// Event arguments for the CameraSelected event
///
public class CameraSelectedEventArgs : EventArgs
{
@@ -78,6 +131,10 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public CameraBase SelectedCamera { get; private set; }
+ ///
+ /// Constructor for CameraSelectedEventArgs
+ ///
+ ///
public CameraSelectedEventArgs(CameraBase camera)
{
SelectedCamera = camera;
@@ -85,12 +142,18 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
///
- /// Defines the contract for IHasFarEndCameraControl
+ /// Interface for devices that have a far end camera control
///
public interface IHasFarEndCameraControl
{
+ ///
+ /// Gets the far end camera, which is typically a CameraBase object that represents the camera at the far end of a call
+ ///
CameraBase FarEndCamera { get; }
+ ///
+ /// Feedback that indicates whether the far end camera is being controlled
+ ///
BoolFeedback ControllingFarEndCameraFeedback { get; }
}
@@ -103,6 +166,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
}
+ ///
+ /// Interface for devices that have camera controls
+ ///
public interface IHasCameraControls
{
}
@@ -123,8 +189,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraPanControl : IHasCameraControls
{
+ ///
+ /// Pans the camera left
+ ///
void PanLeft();
+
+ ///
+ /// Pans the camera right
+ ///
void PanRight();
+
+ ///
+ /// Stops the camera pan movement
+ ///
void PanStop();
}
@@ -133,8 +210,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraTiltControl : IHasCameraControls
{
+ ///
+ /// Tilts the camera down
+ ///
void TiltDown();
+
+ ///
+ /// Tilts the camera up
+ ///
void TiltUp();
+
+ ///
+ /// Stops the camera tilt movement
+ ///
void TiltStop();
}
@@ -143,8 +231,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraZoomControl : IHasCameraControls
{
+ ///
+ /// Zooms the camera in
+ ///
void ZoomIn();
+
+ ///
+ /// Zooms the camera out
+ ///
void ZoomOut();
+
+ ///
+ /// Stops the camera zoom movement
+ ///
void ZoomStop();
}
@@ -153,28 +252,71 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
///
public interface IHasCameraFocusControl : IHasCameraControls
{
+ ///
+ /// Focuses the camera near
+ ///
void FocusNear();
+
+ ///
+ /// Focuses the camera far
+ ///
void FocusFar();
+
+ ///
+ /// Stops the camera focus movement
+ ///
void FocusStop();
+ ///
+ /// Triggers the camera's auto focus functionality, if available.
+ ///
void TriggerAutoFocus();
}
+ ///
+ /// Interface for devices that have auto focus mode control
+ ///
public interface IHasAutoFocusMode
{
+ ///
+ /// Sets the focus mode to auto or manual, or toggles between them.
+ ///
void SetFocusModeAuto();
+
+ ///
+ /// Sets the focus mode to manual, allowing for manual focus adjustments.
+ ///
void SetFocusModeManual();
+
+ ///
+ /// Toggles the focus mode between auto and manual.
+ ///
void ToggleFocusMode();
}
///
- /// Defines the contract for IHasCameraAutoMode
+ /// Interface for devices that have camera auto mode control
///
public interface IHasCameraAutoMode : IHasCameraControls
{
+ ///
+ /// Enables or disables the camera's auto mode, which may include automatic adjustments for focus, exposure, and other settings.
+ ///
void CameraAutoModeOn();
+
+ ///
+ /// Disables the camera's auto mode, allowing for manual control of camera settings.
+ ///
void CameraAutoModeOff();
+
+ ///
+ /// Toggles the camera's auto mode state. If the camera is in auto mode, it will switch to manual mode, and vice versa.
+ ///
void CameraAutoModeToggle();
+
+ ///
+ /// Feedback that indicates whether the camera's auto mode is currently enabled.
+ ///
BoolFeedback CameraAutoModeIsOnFeedback { get; }
}
diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs
index dc9dd947..e2e16b3e 100644
--- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs
@@ -1,13 +1,13 @@
-using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Cameras;
-using System;
-using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
///
- /// Represents a CameraBaseMessenger
+ /// Messenger for a CameraBase device
///
public class CameraBaseMessenger : MessengerBase
{
@@ -48,6 +48,9 @@ namespace PepperDash.Essentials.AppServer.Messengers
);
}
+ ///
+ /// Registers the actions for this messenger. This is called by the base class
+ ///
protected override void RegisterActions()
{
base.RegisterActions();
diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs
new file mode 100644
index 00000000..4fa0c5b1
--- /dev/null
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs
@@ -0,0 +1,104 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using PepperDash.Essentials.Devices.Common.Cameras;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PepperDash.Essentials.AppServer.Messengers
+{
+ ///
+ /// Messenger for devices that implement the IHasCameras interface.
+ ///
+ public class IHasCamerasMessenger : MessengerBase
+ {
+ ///
+ /// Device being bridged that implements IHasCameras interface.
+ ///
+ public IHasCameras CameraController { get; private set; }
+
+ ///
+ /// Messenger for devices that implement IHasCameras interface.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IHasCamerasMessenger(string key, string messagePath , IHasCameras cameraController)
+ : base(key, messagePath, cameraController)
+ {
+ CameraController = cameraController ?? throw new ArgumentNullException("cameraController");
+ CameraController.CameraSelected += CameraController_CameraSelected;
+ }
+
+ private void CameraController_CameraSelected(object sender, CameraSelectedEventArgs e)
+ {
+ PostStatusMessage(new IHasCamerasStateMessage
+ {
+ SelectedCamera = e.SelectedCamera
+ });
+ }
+
+ ///
+ /// Registers the actions for this messenger.
+ ///
+ ///
+ protected override void RegisterActions()
+ {
+ base.RegisterActions();
+
+ AddAction("/fullStatus", (id, context) =>
+ {
+ SendFullStatus(id);
+ });
+
+ AddAction("/selectCamera", (id, content) =>
+ {
+ var cameraKey = content?.ToObject();
+
+ if (!string.IsNullOrEmpty(cameraKey))
+ {
+ CameraController.SelectCamera(cameraKey);
+ }
+ else
+ {
+ throw new ArgumentException("Content must be a string representing the camera key");
+ }
+ });
+ }
+
+ private void SendFullStatus(string clientId)
+ {
+ var state = new IHasCamerasStateMessage
+ {
+ CameraList = CameraController.Cameras,
+ SelectedCamera = CameraController.SelectedCamera
+ };
+
+ PostStatusMessage(state, clientId);
+ }
+
+
+ }
+
+ ///
+ /// State message for devices that implement the IHasCameras interface.
+ ///
+ public class IHasCamerasStateMessage : DeviceStateMessageBase
+ {
+ ///
+ /// List of cameras available in the device.
+ ///
+ [JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)]
+ public List CameraList { get; set; }
+
+ ///
+ /// The currently selected camera on the device.
+ ///
+ [JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)]
+ public CameraBase SelectedCamera { get; set; }
+
+ }
+}
diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs
index 611abd3a..fea28e01 100644
--- a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs
+++ b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs
@@ -919,6 +919,19 @@ namespace PepperDash.Essentials
messengerAdded = true;
}
+ if (device is IHasCameras cameras)
+ {
+ this.LogVerbose("Adding IHasCamerasMessenger for {deviceKey}", device.Key
+ );
+ var messenger = new IHasCamerasMessenger(
+ $"{device.Key}-cameras-{Key}",
+ $"/device/{device.Key}",
+ cameras
+ );
+ AddDefaultDeviceMessenger(messenger);
+ messengerAdded = true;
+ }
+
this.LogVerbose("Trying to cast to generic device for device: {key}", device.Key);
if (device is EssentialsDevice)