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)