Merge pull request #1296 from PepperDash/feature/add-IHasCamerasMessenger

This commit is contained in:
Andrew Welker
2025-07-24 18:53:05 -05:00
committed by GitHub
4 changed files with 287 additions and 4 deletions

View File

@@ -3,29 +3,60 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core; using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Devices.Common.Cameras namespace PepperDash.Essentials.Devices.Common.Cameras
{ {
/// <summary>
/// Enum for camera control modes
/// </summary>
public enum eCameraControlMode public enum eCameraControlMode
{ {
/// <summary>
/// Manual control mode, where the camera is controlled directly by the user or system
/// </summary>
Manual = 0, Manual = 0,
/// <summary>
/// Off control mode, where the camera is turned off or disabled
/// </summary>
Off, Off,
/// <summary>
/// Auto control mode, where the camera automatically adjusts settings based on the environment or conditions
/// </summary>
Auto Auto
} }
public interface IHasCameras /// <summary>
/// Interface for devices that have cameras
/// </summary>
public interface IHasCameras : IKeyName
{ {
/// <summary>
/// Event that is raised when a camera is selected
/// </summary>
event EventHandler<CameraSelectedEventArgs> CameraSelected; event EventHandler<CameraSelectedEventArgs> CameraSelected;
/// <summary>
/// List of cameras on the device. This should be a list of CameraBase objects
/// </summary>
List<CameraBase> Cameras { get; } List<CameraBase> Cameras { get; }
/// <summary>
/// The currently selected camera. This should be a CameraBase object
/// </summary>
CameraBase SelectedCamera { get; } CameraBase SelectedCamera { get; }
/// <summary>
/// Feedback that indicates the currently selected camera
/// </summary>
StringFeedback SelectedCameraFeedback { get; } StringFeedback SelectedCameraFeedback { get; }
/// <summary>
/// Selects a camera from the list of available cameras based on the provided key.
/// </summary>
/// <param name="key">The unique identifier or name of the camera to select.</param>
void SelectCamera(string key); void SelectCamera(string key);
} }
@@ -42,7 +73,14 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary> /// </summary>
public interface IHasCameraOff public interface IHasCameraOff
{ {
/// <summary>
/// Feedback that indicates whether the camera is off
/// </summary>
BoolFeedback CameraIsOffFeedback { get; } BoolFeedback CameraIsOffFeedback { get; }
/// <summary>
/// Turns the camera off, blanking the near end video
/// </summary>
void CameraOff(); void CameraOff();
} }
@@ -51,31 +89,71 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary> /// </summary>
public interface IHasCameraMute public interface IHasCameraMute
{ {
/// <summary>
/// Feedback that indicates whether the camera is muted
/// </summary>
BoolFeedback CameraIsMutedFeedback { get; } BoolFeedback CameraIsMutedFeedback { get; }
/// <summary>
/// Mutes the camera video, preventing it from being sent to the far end
/// </summary>
void CameraMuteOn(); void CameraMuteOn();
/// <summary>
/// Unmutes the camera video, allowing it to be sent to the far end
/// </summary>
void CameraMuteOff(); void CameraMuteOff();
/// <summary>
/// Toggles the camera mute state. If the camera is muted, it will be unmuted, and vice versa.
/// </summary>
void CameraMuteToggle(); void CameraMuteToggle();
} }
/// <summary>
/// Interface for devices that can mute and unmute their camera video, with an event for unmute requests
/// </summary>
public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute public interface IHasCameraMuteWithUnmuteReqeust : IHasCameraMute
{ {
/// <summary>
/// Event that is raised when a video unmute is requested, typically by the far end
/// </summary>
event EventHandler VideoUnmuteRequested; event EventHandler VideoUnmuteRequested;
} }
/// <summary>
/// Event arguments for the CameraSelected event
/// </summary>
public class CameraSelectedEventArgs : EventArgs public class CameraSelectedEventArgs : EventArgs
{ {
/// <summary>
/// The selected camera
/// </summary>
public CameraBase SelectedCamera { get; private set; } public CameraBase SelectedCamera { get; private set; }
/// <summary>
/// Constructor for CameraSelectedEventArgs
/// </summary>
/// <param name="camera"></param>
public CameraSelectedEventArgs(CameraBase camera) public CameraSelectedEventArgs(CameraBase camera)
{ {
SelectedCamera = camera; SelectedCamera = camera;
} }
} }
/// <summary>
/// Interface for devices that have a far end camera control
/// </summary>
public interface IHasFarEndCameraControl public interface IHasFarEndCameraControl
{ {
/// <summary>
/// Gets the far end camera, which is typically a CameraBase object that represents the camera at the far end of a call
/// </summary>
CameraBase FarEndCamera { get; } CameraBase FarEndCamera { get; }
/// <summary>
/// Feedback that indicates whether the far end camera is being controlled
/// </summary>
BoolFeedback ControllingFarEndCameraFeedback { get; } BoolFeedback ControllingFarEndCameraFeedback { get; }
} }
@@ -88,6 +166,9 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
} }
/// <summary>
/// Interface for devices that have camera controls
/// </summary>
public interface IHasCameraControls public interface IHasCameraControls
{ {
} }
@@ -108,8 +189,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary> /// </summary>
public interface IHasCameraPanControl : IHasCameraControls public interface IHasCameraPanControl : IHasCameraControls
{ {
/// <summary>
/// Pans the camera left
/// </summary>
void PanLeft(); void PanLeft();
/// <summary>
/// Pans the camera right
/// </summary>
void PanRight(); void PanRight();
/// <summary>
/// Stops the camera pan movement
/// </summary>
void PanStop(); void PanStop();
} }
@@ -118,8 +210,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary> /// </summary>
public interface IHasCameraTiltControl : IHasCameraControls public interface IHasCameraTiltControl : IHasCameraControls
{ {
/// <summary>
/// Tilts the camera down
/// </summary>
void TiltDown(); void TiltDown();
/// <summary>
/// Tilts the camera up
/// </summary>
void TiltUp(); void TiltUp();
/// <summary>
/// Stops the camera tilt movement
/// </summary>
void TiltStop(); void TiltStop();
} }
@@ -128,8 +231,19 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary> /// </summary>
public interface IHasCameraZoomControl : IHasCameraControls public interface IHasCameraZoomControl : IHasCameraControls
{ {
/// <summary>
/// Zooms the camera in
/// </summary>
void ZoomIn(); void ZoomIn();
/// <summary>
/// Zooms the camera out
/// </summary>
void ZoomOut(); void ZoomOut();
/// <summary>
/// Stops the camera zoom movement
/// </summary>
void ZoomStop(); void ZoomStop();
} }
@@ -138,25 +252,71 @@ namespace PepperDash.Essentials.Devices.Common.Cameras
/// </summary> /// </summary>
public interface IHasCameraFocusControl : IHasCameraControls public interface IHasCameraFocusControl : IHasCameraControls
{ {
/// <summary>
/// Focuses the camera near
/// </summary>
void FocusNear(); void FocusNear();
/// <summary>
/// Focuses the camera far
/// </summary>
void FocusFar(); void FocusFar();
/// <summary>
/// Stops the camera focus movement
/// </summary>
void FocusStop(); void FocusStop();
/// <summary>
/// Triggers the camera's auto focus functionality, if available.
/// </summary>
void TriggerAutoFocus(); void TriggerAutoFocus();
} }
/// <summary>
/// Interface for devices that have auto focus mode control
/// </summary>
public interface IHasAutoFocusMode public interface IHasAutoFocusMode
{ {
/// <summary>
/// Sets the focus mode to auto or manual, or toggles between them.
/// </summary>
void SetFocusModeAuto(); void SetFocusModeAuto();
/// <summary>
/// Sets the focus mode to manual, allowing for manual focus adjustments.
/// </summary>
void SetFocusModeManual(); void SetFocusModeManual();
/// <summary>
/// Toggles the focus mode between auto and manual.
/// </summary>
void ToggleFocusMode(); void ToggleFocusMode();
} }
/// <summary>
/// Interface for devices that have camera auto mode control
/// </summary>
public interface IHasCameraAutoMode : IHasCameraControls public interface IHasCameraAutoMode : IHasCameraControls
{ {
/// <summary>
/// Enables or disables the camera's auto mode, which may include automatic adjustments for focus, exposure, and other settings.
/// </summary>
void CameraAutoModeOn(); void CameraAutoModeOn();
/// <summary>
/// Disables the camera's auto mode, allowing for manual control of camera settings.
/// </summary>
void CameraAutoModeOff(); void CameraAutoModeOff();
/// <summary>
/// Toggles the camera's auto mode state. If the camera is in auto mode, it will switch to manual mode, and vice versa.
/// </summary>
void CameraAutoModeToggle(); void CameraAutoModeToggle();
/// <summary>
/// Feedback that indicates whether the camera's auto mode is currently enabled.
/// </summary>
BoolFeedback CameraAutoModeIsOnFeedback { get; } BoolFeedback CameraAutoModeIsOnFeedback { get; }
} }

View File

@@ -6,6 +6,9 @@ using System.Collections.Generic;
namespace PepperDash.Essentials.AppServer.Messengers namespace PepperDash.Essentials.AppServer.Messengers
{ {
/// <summary>
/// Messenger for a CameraBase device
/// </summary>
public class CameraBaseMessenger : MessengerBase public class CameraBaseMessenger : MessengerBase
{ {
/// <summary> /// <summary>
@@ -45,6 +48,9 @@ namespace PepperDash.Essentials.AppServer.Messengers
); );
} }
/// <summary>
/// Registers the actions for this messenger. This is called by the base class
/// </summary>
protected override void RegisterActions() protected override void RegisterActions()
{ {
base.RegisterActions(); base.RegisterActions();

View File

@@ -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
{
/// <summary>
/// Messenger for devices that implement the IHasCameras interface.
/// </summary>
public class IHasCamerasMessenger : MessengerBase
{
/// <summary>
/// Device being bridged that implements IHasCameras interface.
/// </summary>
public IHasCameras CameraController { get; private set; }
/// <summary>
/// Messenger for devices that implement IHasCameras interface.
/// </summary>
/// <param name="key"></param>
/// <param name="cameraController"></param>
/// <param name="messagePath"></param>
/// <exception cref="ArgumentNullException"></exception>
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
});
}
/// <summary>
/// Registers the actions for this messenger.
/// </summary>
/// <exception cref="ArgumentException"></exception>
protected override void RegisterActions()
{
base.RegisterActions();
AddAction("/fullStatus", (id, context) =>
{
SendFullStatus(id);
});
AddAction("/selectCamera", (id, content) =>
{
var cameraKey = content?.ToObject<string>();
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);
}
}
/// <summary>
/// State message for devices that implement the IHasCameras interface.
/// </summary>
public class IHasCamerasStateMessage : DeviceStateMessageBase
{
/// <summary>
/// List of cameras available in the device.
/// </summary>
[JsonProperty("cameraList", NullValueHandling = NullValueHandling.Ignore)]
public List<CameraBase> CameraList { get; set; }
/// <summary>
/// The currently selected camera on the device.
/// </summary>
[JsonProperty("selectedCamera", NullValueHandling = NullValueHandling.Ignore)]
public CameraBase SelectedCamera { get; set; }
}
}

View File

@@ -907,6 +907,19 @@ namespace PepperDash.Essentials
messengerAdded = true; 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); this.LogVerbose("Trying to cast to generic device for device: {key}", device.Key);
if (device is EssentialsDevice) if (device is EssentialsDevice)