diff --git a/src/PepperDash.Core/Comm/GenericUdpServer.cs b/src/PepperDash.Core/Comm/GenericUdpServer.cs
index 61bebf8d..52ac627a 100644
--- a/src/PepperDash.Core/Comm/GenericUdpServer.cs
+++ b/src/PepperDash.Core/Comm/GenericUdpServer.cs
@@ -131,14 +131,14 @@ namespace PepperDash.Core
///
///
///
- ///
- public GenericUdpServer(string key, string address, int port, int buffefSize)
+ ///
+ public GenericUdpServer(string key, string address, int port, int bufferSize)
: base(key)
{
StreamDebugging = new CommunicationStreamDebugging(key);
Hostname = address;
Port = port;
- BufferSize = buffefSize;
+ BufferSize = bufferSize;
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler);
@@ -194,7 +194,21 @@ namespace PepperDash.Core
{
if (Server == null)
{
- Server = new UDPServer();
+ try
+ {
+ var address = IPAddress.Parse(Hostname);
+
+ Server = new UDPServer(address, Port, BufferSize);
+
+ }
+ catch (Exception ex)
+ {
+ this.LogError("Error parsing IP Address '{ipAddress}': message: {message}", Hostname, ex.Message);
+ this.LogInformation("Creating UDPServer with default buffersize");
+
+ Server = new UDPServer();
+ }
+
}
if (string.IsNullOrEmpty(Hostname))
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs
deleted file mode 100644
index e2120638..00000000
--- a/src/PepperDash.Essentials.Devices.Common/Cameras/CameraControl.cs
+++ /dev/null
@@ -1,323 +0,0 @@
-using System;
-using System.Collections.Generic;
-using PepperDash.Core;
-using PepperDash.Essentials.Core;
-
-namespace PepperDash.Essentials.Devices.Common.Cameras
-{
- ///
- /// 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
- }
-
-
- ///
- /// Interface for devices that have cameras
- ///
- 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);
- }
-
- ///
- /// Defines the contract for IHasCodecCameras
- ///
- public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl
- {
-
- }
-
- ///
- /// To be implmented on codecs that can disable their camera(s) to blank the near end video
- ///
- 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();
- }
-
- ///
- /// Describes the ability to mute and unmute camera video
- ///
- 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;
- }
-
- ///
- /// Event arguments for the CameraSelected event
- ///
- public class CameraSelectedEventArgs : EventArgs
- {
- ///
- /// Gets or sets the SelectedCamera
- ///
- public CameraBase SelectedCamera { get; private set; }
-
- ///
- /// Constructor for CameraSelectedEventArgs
- ///
- ///
- public CameraSelectedEventArgs(CameraBase camera)
- {
- SelectedCamera = camera;
- }
- }
-
- ///
- /// 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; }
-
- }
-
- ///
- /// Defines the contract for IAmFarEndCamera
- ///
- public interface IAmFarEndCamera
- {
-
- }
-
- ///
- /// Interface for devices that have camera controls
- ///
- public interface IHasCameraControls
- {
- }
-
- ///
- /// Defines the contract for IHasCameraPtzControl
- ///
- public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl
- {
- ///
- /// Resets the camera position
- ///
- void PositionHome();
- }
-
- ///
- /// Interface for camera pan control
- ///
- public interface IHasCameraPanControl : IHasCameraControls
- {
- ///
- /// Pans the camera left
- ///
- void PanLeft();
-
- ///
- /// Pans the camera right
- ///
- void PanRight();
-
- ///
- /// Stops the camera pan movement
- ///
- void PanStop();
- }
-
- ///
- /// Defines the contract for IHasCameraTiltControl
- ///
- public interface IHasCameraTiltControl : IHasCameraControls
- {
- ///
- /// Tilts the camera down
- ///
- void TiltDown();
-
- ///
- /// Tilts the camera up
- ///
- void TiltUp();
-
- ///
- /// Stops the camera tilt movement
- ///
- void TiltStop();
- }
-
- ///
- /// Defines the contract for IHasCameraZoomControl
- ///
- public interface IHasCameraZoomControl : IHasCameraControls
- {
- ///
- /// Zooms the camera in
- ///
- void ZoomIn();
-
- ///
- /// Zooms the camera out
- ///
- void ZoomOut();
-
- ///
- /// Stops the camera zoom movement
- ///
- void ZoomStop();
- }
-
- ///
- /// Defines the contract for IHasCameraFocusControl
- ///
- 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();
- }
-
- ///
- /// 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; }
- }
-
-
-
-
-}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/CameraSelectedEventArgs.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/CameraSelectedEventArgs.cs
new file mode 100644
index 00000000..bb2a85a2
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/CameraSelectedEventArgs.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Event arguments for the CameraSelected event
+ ///
+ [Obsolete("Use CameraSelectedEventArgs instead. This class will be removed in a future version")]
+ public class CameraSelectedEventArgs : EventArgs
+ {
+ /// Gets or sets the SelectedCamera
+ ///
+ public CameraBase SelectedCamera { get; private set; }
+
+ ///
+ /// Constructor for CameraSelectedEventArgs
+ ///
+ ///
+ public CameraSelectedEventArgs(CameraBase camera)
+ {
+ SelectedCamera = camera;
+ }
+ }
+
+ ///
+ /// Event arguments for the CameraSelected event
+ ///
+ ///
+ public class CameraSelectedEventArgs : EventArgs
+ {
+ ///
+ /// Gets or sets the SelectedCamera
+ ///
+ public T SelectedCamera { get; private set; }
+
+ ///
+ /// Constructor for CameraSelectedEventArgs
+ ///
+ ///
+ public CameraSelectedEventArgs(T camera)
+ {
+ SelectedCamera = camera;
+ }
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IAmFarEndCamera.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IAmFarEndCamera.cs
new file mode 100644
index 00000000..a8e96664
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IAmFarEndCamera.cs
@@ -0,0 +1,12 @@
+using PepperDash.Core;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Defines the contract for IAmFarEndCamera
+ ///
+ public interface IAmFarEndCamera : IKeyName
+ {
+
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/ICameraCapabilities.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/ICameraCapabilities.cs
new file mode 100644
index 00000000..cf39a95c
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/ICameraCapabilities.cs
@@ -0,0 +1,86 @@
+using Newtonsoft.Json;
+using PepperDash.Core;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Interface for camera capabilities
+ ///
+ public interface ICameraCapabilities: IKeyName
+ {
+ ///
+ /// Indicates whether the camera can pan
+ ///
+ [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
+ bool CanPan { get; }
+
+ ///
+ /// Indicates whether the camera can tilt
+ ///
+ [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
+ bool CanTilt { get; }
+
+ ///
+ /// Indicates whether the camera can zoom
+ ///
+ [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
+ bool CanZoom { get; }
+
+
+ ///
+ /// Indicates whether the camera can focus
+ ///
+ [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
+ bool CanFocus { get; }
+ }
+
+ ///
+ /// Indicates the capabilities of a camera
+ ///
+ public class CameraCapabilities : ICameraCapabilities
+ {
+
+ ///
+ /// Unique Key
+ ///
+ [JsonProperty("key", NullValueHandling = NullValueHandling.Ignore)]
+ public string Key { get; set; }
+
+ ///
+ /// Isn't it obvious :)
+ ///
+ [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
+ public string Name { get; set; }
+
+
+ ///
+ /// Indicates whether the camera can pan
+ ///
+ [JsonProperty("canPan", NullValueHandling = NullValueHandling.Ignore)]
+ public bool CanPan { get; set; }
+
+ ///
+ /// Indicates whether the camera can tilt
+ ///
+ [JsonProperty("canTilt", NullValueHandling = NullValueHandling.Ignore)]
+ public bool CanTilt { get; set; }
+
+ ///
+ /// Indicates whether the camera can zoom
+ ///
+ [JsonProperty("canZoom", NullValueHandling = NullValueHandling.Ignore)]
+ public bool CanZoom { get; set; }
+
+
+ ///
+ /// Indicates whether the camera can focus
+ ///
+ [JsonProperty("canFocus", NullValueHandling = NullValueHandling.Ignore)]
+ public bool CanFocus { get; set; }
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasAutoFocusMode.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasAutoFocusMode.cs
new file mode 100644
index 00000000..0dbd5f52
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasAutoFocusMode.cs
@@ -0,0 +1,24 @@
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Interface for devices that have auto focus mode control
+ ///
+ public interface IHasAutoFocusMode : IHasCameraControls
+ {
+ ///
+ /// 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();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraAutoMode.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraAutoMode.cs
new file mode 100644
index 00000000..9eeb1f40
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraAutoMode.cs
@@ -0,0 +1,31 @@
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+
+ ///
+ /// 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.Devices.Common/Cameras/Interfaces/IHasCameraControls.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraControls.cs
new file mode 100644
index 00000000..a4ed5937
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraControls.cs
@@ -0,0 +1,13 @@
+using PepperDash.Core;
+
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+
+ ///
+ /// Interface for devices that have camera controls
+ ///
+ public interface IHasCameraControls : IKeyName
+ {
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraFocusControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraFocusControl.cs
new file mode 100644
index 00000000..bf266d56
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraFocusControl.cs
@@ -0,0 +1,29 @@
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Defines the contract for IHasCameraFocusControl
+ ///
+ 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();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMute.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMute.cs
new file mode 100644
index 00000000..cae6f5ef
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMute.cs
@@ -0,0 +1,31 @@
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Describes the ability to mute and unmute camera video
+ ///
+ public interface IHasCameraMute : IKeyName
+ {
+ ///
+ /// 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();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMuteWithUnmuteRequest.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMuteWithUnmuteRequest.cs
new file mode 100644
index 00000000..5426ea2b
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraMuteWithUnmuteRequest.cs
@@ -0,0 +1,16 @@
+using System;
+
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// 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;
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraOff.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraOff.cs
new file mode 100644
index 00000000..6dc451c1
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraOff.cs
@@ -0,0 +1,27 @@
+using PepperDash.Essentials.Core;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+
+
+ ///
+ /// To be implmented on codecs that can disable their camera(s) to blank the near end video
+ ///
+ public interface IHasCameraOff : IHasCameraControls
+ {
+ ///
+ /// Feedback that indicates whether the camera is off
+ ///
+ BoolFeedback CameraIsOffFeedback { get; }
+
+ ///
+ /// Turns the camera off, blanking the near end video
+ ///
+ void CameraOff();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPanControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPanControl.cs
new file mode 100644
index 00000000..507dc555
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPanControl.cs
@@ -0,0 +1,24 @@
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Interface for camera pan control
+ ///
+ public interface IHasCameraPanControl : IHasCameraControls
+ {
+ ///
+ /// Pans the camera left
+ ///
+ void PanLeft();
+
+ ///
+ /// Pans the camera right
+ ///
+ void PanRight();
+
+ ///
+ /// Stops the camera pan movement
+ ///
+ void PanStop();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPtzControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPtzControl.cs
new file mode 100644
index 00000000..de2b52dd
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraPtzControl.cs
@@ -0,0 +1,14 @@
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Defines the contract for IHasCameraPtzControl
+ ///
+ public interface IHasCameraPtzControl : IHasCameraPanControl, IHasCameraTiltControl, IHasCameraZoomControl
+ {
+ ///
+ /// Resets the camera position
+ ///
+ void PositionHome();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraTiltControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraTiltControl.cs
new file mode 100644
index 00000000..87dc1751
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraTiltControl.cs
@@ -0,0 +1,24 @@
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Defines the contract for IHasCameraTiltControl
+ ///
+ public interface IHasCameraTiltControl : IHasCameraControls
+ {
+ ///
+ /// Tilts the camera down
+ ///
+ void TiltDown();
+
+ ///
+ /// Tilts the camera up
+ ///
+ void TiltUp();
+
+ ///
+ /// Stops the camera tilt movement
+ ///
+ void TiltStop();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraZoomControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraZoomControl.cs
new file mode 100644
index 00000000..72bf16c4
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameraZoomControl.cs
@@ -0,0 +1,24 @@
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Defines the contract for IHasCameraZoomControl
+ ///
+ public interface IHasCameraZoomControl : IHasCameraControls
+ {
+ ///
+ /// Zooms the camera in
+ ///
+ void ZoomIn();
+
+ ///
+ /// Zooms the camera out
+ ///
+ void ZoomOut();
+
+ ///
+ /// Stops the camera zoom movement
+ ///
+ void ZoomStop();
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameras.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameras.cs
new file mode 100644
index 00000000..5a5962f8
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCameras.cs
@@ -0,0 +1,41 @@
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using System;
+using System.Collections.Generic;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Interface for devices that have cameras
+ ///
+ [Obsolete("Use IHasCamerasWithControls instead. This interface will be removed in a future version")]
+ 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);
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCamerasWithControls.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCamerasWithControls.cs
new file mode 100644
index 00000000..f7aff6d2
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCamerasWithControls.cs
@@ -0,0 +1,40 @@
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+using System;
+using System.Collections.Generic;
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Interface for devices that have cameras with controls
+ ///
+ public interface IHasCamerasWithControls : IKeyName, IKeyed
+ {
+ ///
+ /// List of cameras on the device. This should be a list of IHasCameraControls objects
+ ///
+
+ List Cameras { get; }
+
+ ///
+ /// The currently selected camera. This should be an IHasCameraControls object
+ ///
+ IHasCameraControls SelectedCamera { get; }
+
+ ///
+ /// Feedback that indicates the currently selected camera
+ ///
+ StringFeedback SelectedCameraFeedback { get; }
+
+ ///
+ /// Event that is raised when a camera is selected
+ ///
+ event EventHandler> CameraSelected;
+
+ ///
+ /// Selects a camera from the list of available cameras based on the provided key.
+ ///
+ ///
+ void SelectCamera(string key);
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCodecCameras.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCodecCameras.cs
new file mode 100644
index 00000000..01cdf24e
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasCodecCameras.cs
@@ -0,0 +1,13 @@
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+
+ ///
+ /// Defines the contract for IHasCodecCameras
+ ///
+ public interface IHasCodecCameras : IHasCameras, IHasFarEndCameraControl
+ {
+
+ }
+
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasFarEndCameraControl.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasFarEndCameraControl.cs
new file mode 100644
index 00000000..10a4ba69
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/IHasFarEndCameraControl.cs
@@ -0,0 +1,23 @@
+using PepperDash.Core;
+using PepperDash.Essentials.Core;
+
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// Interface for devices that have a far end camera control
+ ///
+ public interface IHasFarEndCameraControl : IKeyName
+ {
+ ///
+ /// 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; }
+
+ }
+}
diff --git a/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/eCameraControlMode.cs b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/eCameraControlMode.cs
new file mode 100644
index 00000000..c966ac41
--- /dev/null
+++ b/src/PepperDash.Essentials.Devices.Common/Cameras/Interfaces/eCameraControlMode.cs
@@ -0,0 +1,24 @@
+
+
+namespace PepperDash.Essentials.Devices.Common.Cameras
+{
+ ///
+ /// 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
+ }
+
+}
diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs
index 7650b430..8c9f0451 100644
--- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/CameraBaseMessenger.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.Cameras;
@@ -9,12 +11,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
///
/// Messenger for a CameraBase device
///
- public class CameraBaseMessenger : MessengerBase
+ public class CameraBaseMessenger : MessengerBase where T : IKeyed
{
///
/// Gets or sets the Camera
///
- public CameraBase Camera { get; set; }
+ public T Camera { get; set; }
///
/// Constructor
@@ -22,10 +24,13 @@ namespace PepperDash.Essentials.AppServer.Messengers
///
///
///
- public CameraBaseMessenger(string key, CameraBase camera, string messagePath)
- : base(key, messagePath, camera)
+ public CameraBaseMessenger(string key, T camera, string messagePath)
+ : base(key, messagePath, camera as IKeyName)
{
- Camera = camera ?? throw new ArgumentNullException("camera");
+ if (camera == null)
+ throw new ArgumentNullException(nameof(camera));
+
+ Camera = camera;
if (Camera is IHasCameraPresets presetsCamera)
@@ -178,19 +183,44 @@ namespace PepperDash.Essentials.AppServer.Messengers
private void SendCameraFullMessageObject(string id = null)
{
var presetList = new List();
+ CameraCapabilities capabilities = null;
if (Camera is IHasCameraPresets presetsCamera)
presetList = presetsCamera.Presets;
- PostStatusMessage(JToken.FromObject(new
+ if (Camera is ICameraCapabilities cameraCapabilities)
+ capabilities = new CameraCapabilities
+ {
+ CanPan = cameraCapabilities.CanPan,
+ CanTilt = cameraCapabilities.CanTilt,
+ CanZoom = cameraCapabilities.CanZoom,
+ CanFocus = cameraCapabilities.CanFocus
+
+ };
+
+ if (Camera is CameraBase cameraBase)
+ capabilities = new CameraCapabilities
+ {
+ CanPan = cameraBase.CanPan,
+ CanTilt = cameraBase.CanTilt,
+ CanZoom = cameraBase.CanZoom,
+ CanFocus = cameraBase.CanFocus
+
+ };
+
+ var message = new CameraStateMessage
{
- cameraManualSupported = Camera is IHasCameraControls,
- cameraAutoSupported = Camera is IHasCameraAutoMode,
- cameraOffSupported = Camera is IHasCameraOff,
- cameraMode = GetCameraMode(),
- hasPresets = Camera is IHasCameraPresets,
- presets = presetList
- }), id
+ CameraManualSupported = Camera is IHasCameraControls,
+ CameraAutoSupported = Camera is IHasCameraAutoMode,
+ CameraOffSupported = Camera is IHasCameraOff,
+ CameraMode = (eCameraControlMode)Enum.Parse(typeof(eCameraControlMode), GetCameraMode(), true),
+ HasPresets = Camera is IHasCameraPresets,
+ Presets = presetList,
+ Capabilities = capabilities,
+ IsFarEnd = Camera is IAmFarEndCamera
+ };
+
+ PostStatusMessage(message, id
);
}
@@ -210,4 +240,59 @@ namespace PepperDash.Essentials.AppServer.Messengers
return m;
}
}
+
+ ///
+ /// State message for a camera device
+ ///
+ public class CameraStateMessage : DeviceStateMessageBase
+ {
+ ///
+ /// Indicates whether the camera supports manual control
+ ///
+ [JsonProperty("cameraManualSupported", NullValueHandling = NullValueHandling.Ignore)]
+ public bool CameraManualSupported { get; set; }
+
+ ///
+ /// Indicates whether the camera supports auto control
+ ///
+ [JsonProperty("cameraAutoSupported", NullValueHandling = NullValueHandling.Ignore)]
+ public bool CameraAutoSupported { get; set; }
+
+ ///
+ /// Indicates whether the camera supports off control
+ ///
+ [JsonProperty("cameraOffSupported", NullValueHandling = NullValueHandling.Ignore)]
+ public bool CameraOffSupported { get; set; }
+
+ ///
+ /// Indicates the current camera control mode
+ ///
+ [JsonProperty("cameraMode", NullValueHandling = NullValueHandling.Ignore)]
+ [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
+ public eCameraControlMode CameraMode { get; set; }
+
+ ///
+ /// Indicates whether the camera has presets
+ ///
+ [JsonProperty("hasPresets", NullValueHandling = NullValueHandling.Ignore)]
+ public bool HasPresets { get; set; }
+
+ ///
+ /// List of presets if the camera supports them
+ ///
+ [JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)]
+ public List Presets { get; set; }
+
+ ///
+ /// Indicates the capabilities of the camera
+ ///
+ [JsonProperty("capabilities", NullValueHandling = NullValueHandling.Ignore)]
+ public CameraCapabilities Capabilities { get; set; }
+
+ ///
+ /// Indicates whether the camera is a far end camera
+ ///
+ [JsonProperty("isFarEnd", NullValueHandling = NullValueHandling.Ignore)]
+ public bool IsFarEnd { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs
index 7099e52c..00c2c2fe 100644
--- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasMessenger.cs
@@ -1,17 +1,14 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
using PepperDash.Essentials.Devices.Common.Cameras;
+using System;
+using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers
{
///
/// Messenger for devices that implement the IHasCameras interface.
///
+ [Obsolete("Use IHasCamerasWithControlsMessenger instead. This class will be removed in a future version")]
public class IHasCamerasMessenger : MessengerBase
{
///
diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasWithControlMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasWithControlMessenger.cs
new file mode 100644
index 00000000..cce07dcd
--- /dev/null
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCamerasWithControlMessenger.cs
@@ -0,0 +1,137 @@
+using Newtonsoft.Json;
+using PepperDash.Core;
+using PepperDash.Core.Logging;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Devices.Common.Cameras;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace PepperDash.Essentials.AppServer.Messengers
+{
+ ///
+ /// Messenger for devices that implement the IHasCameras interface.
+ ///
+ public class IHasCamerasWithControlMessenger : MessengerBase
+ {
+ ///
+ /// Device being bridged that implements IHasCameras interface.
+ ///
+ public IHasCamerasWithControls CameraController { get; private set; }
+
+ ///
+ /// Messenger for devices that implement IHasCameras interface.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IHasCamerasWithControlMessenger(string key, string messagePath, IHasCamerasWithControls cameraController)
+ : base(key, messagePath, cameraController)
+ {
+ CameraController = cameraController ?? throw new ArgumentNullException("cameraController");
+ CameraController.CameraSelected += CameraController_CameraSelected;
+ }
+
+ private void CameraController_CameraSelected(object sender, CameraSelectedEventArgs e)
+ {
+ var selectedCamera = new KeyName
+ {
+ Key = e.SelectedCamera.Key,
+ Name = e.SelectedCamera.Name
+ };
+
+ PostStatusMessage(new IHasCamerasWithControlsStateMessage
+ {
+ SelectedCamera = selectedCamera
+ });
+ }
+
+ ///
+ /// Registers the actions for this messenger.
+ ///
+ ///
+ protected override void RegisterActions()
+ {
+ base.RegisterActions();
+
+ AddAction("/fullStatus", (id, context) => SendFullStatus(id));
+
+ AddAction("/cameraListStatus", (id, content) => 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 cameraList = new List();
+ KeyName selectedCamera = null;
+
+ foreach (var cam in CameraController.Cameras)
+ {
+ cameraList.Add(new KeyName{
+ Key = cam.Key,
+ Name = cam.Name
+ });
+ }
+
+ if (CameraController.SelectedCamera != null)
+ {
+ selectedCamera = new KeyName
+ {
+ Key = CameraController.SelectedCamera.Key,
+ Name = CameraController.SelectedCamera.Name
+ };
+ }
+
+ var state = new IHasCamerasWithControlsStateMessage
+ {
+ CameraList = cameraList,
+ SelectedCamera = selectedCamera
+ };
+
+ PostStatusMessage(state, clientId);
+ }
+ }
+
+ ///
+ /// State message for devices that implement the IHasCameras interface.
+ ///
+ public class IHasCamerasWithControlsStateMessage : 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 IKeyName SelectedCamera { get; set; }
+ }
+
+ class KeyName : IKeyName
+ {
+ public string Key { get; set; }
+ public string Name { get; set; }
+ public KeyName()
+ {
+ Key = "";
+ Name = "";
+ }
+ }
+}
diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs
index 36d73a3e..8e2f8f3e 100644
--- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/ISelectableItemsMessenger.cs
@@ -16,6 +16,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
private readonly string _propName;
+ private List _itemKeys = new List();
+
///
/// Constructs a messenger for a device that implements ISelectableItems
///
@@ -39,9 +41,35 @@ namespace PepperDash.Essentials.AppServer.Messengers
AddAction("/itemsStatus", (id, content) => SendFullStatus(id));
+ AddAction("/selectItem", (id, content) =>
+ {
+ try
+ {
+ var key = content.ToObject();
+
+ if (key == null)
+ {
+ this.LogError("No key specified to select");
+ return;
+ }
+ if (itemDevice.Items.ContainsKey((TKey)Convert.ChangeType(key, typeof(TKey))))
+ {
+ itemDevice.Items[(TKey)Convert.ChangeType(key, typeof(TKey))].Select();
+ }
+ else
+ {
+ this.LogError("Key {0} not found in items", key);
+ }
+ }
+ catch (Exception e)
+ {
+ this.LogError("Error selecting item: {0}", e.Message);
+ }
+ });
+
itemDevice.ItemsUpdated += (sender, args) =>
{
- SendFullStatus();
+ SetItems();
};
itemDevice.CurrentItemChanged += (sender, args) =>
@@ -49,23 +77,47 @@ namespace PepperDash.Essentials.AppServer.Messengers
SendFullStatus();
};
- foreach (var input in itemDevice.Items)
+ SetItems();
+ }
+
+ ///
+ /// Sets the items and registers their update events
+ ///
+ private void SetItems()
+ {
+ if (_itemKeys != null && _itemKeys.Count > 0)
{
- var key = input.Key;
- var localItem = input.Value;
+ /// Clear out any existing item actions
+ foreach (var item in _itemKeys)
+ {
+ RemoveAction($"/{item}");
+ }
+
+ _itemKeys.Clear();
+ }
+
+ foreach (var item in itemDevice.Items)
+ {
+ var key = item.Key;
+ var localItem = item.Value;
AddAction($"/{key}", (id, content) =>
{
localItem.Select();
});
- localItem.ItemUpdated += (sender, args) =>
- {
- SendFullStatus();
- };
+ _itemKeys.Add(key.ToString());
+
+ localItem.ItemUpdated -= LocalItem_ItemUpdated;
+ localItem.ItemUpdated += LocalItem_ItemUpdated;
}
}
+ private void LocalItem_ItemUpdated(object sender, EventArgs e)
+ {
+ SendFullStatus();
+ }
+
private void SendFullStatus(string id = null)
{
try
diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs
index 0579c1f6..d6a40ede 100644
--- a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs
+++ b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs
@@ -405,14 +405,15 @@ namespace PepperDash.Essentials
messengerAdded = true;
}
- if (device is CameraBase cameraDevice)
+ // Default to IHasCameraControls if CameraBase and IHasCameraControls
+ if (device is CameraBase cameraDevice && !(device is IHasCameraControls))
{
this.LogVerbose(
"Adding CameraBaseMessenger for {deviceKey}",
device.Key
);
- var cameraMessenger = new CameraBaseMessenger(
+ var cameraMessenger = new CameraBaseMessenger(
$"{device.Key}-cameraBase-{Key}",
cameraDevice,
$"/device/{device.Key}"
@@ -423,6 +424,21 @@ namespace PepperDash.Essentials
messengerAdded = true;
}
+ if (device is IHasCameraControls cameraControlDev)
+ {
+ this.LogVerbose(
+ "Adding IHasCamerasWithControlMessenger for {deviceKey}",
+ device.Key
+ );
+ var cameraControlMessenger = new CameraBaseMessenger(
+ $"{device.Key}-hasCamerasWithControls-{Key}",
+ cameraControlDev,
+ $"/device/{device.Key}"
+ );
+ AddDefaultDeviceMessenger(cameraControlMessenger);
+ messengerAdded = true;
+ }
+
if (device is BlueJeansPc)
{
this.LogVerbose(
@@ -975,6 +991,19 @@ namespace PepperDash.Essentials
messengerAdded = true;
}
+ if (device is IHasCamerasWithControls cameras2)
+ {
+ this.LogVerbose("Adding IHasCamerasWithControlsMessenger for {deviceKey}", device.Key
+ );
+ var messenger = new IHasCamerasWithControlMessenger(
+ $"{device.Key}-cameras-{Key}",
+ $"/device/{device.Key}",
+ cameras2
+ );
+ AddDefaultDeviceMessenger(messenger);
+ messengerAdded = true;
+ }
+
this.LogVerbose("Trying to cast to generic device for device: {key}", device.Key);
if (device is EssentialsDevice)