diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCameraMuteMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCameraMuteMessenger.cs
new file mode 100644
index 00000000..c1a5340a
--- /dev/null
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCameraMuteMessenger.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using PepperDash.Core;
+using PepperDash.Core.Logging;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Devices.Common.Cameras;
+
+namespace PepperDash.Essentials.AppServer.Messengers
+{
+ ///
+ /// Provides a messaging bridge for devices implementing
+ ///
+ public class IHasCameraMuteMessenger : MessengerBase
+ {
+ private readonly IHasCameraMute _cameraMute;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key for the messenger.
+ /// The message path for the messenger.
+ /// The device implementing .
+ public IHasCameraMuteMessenger(string key, string messagePath, EssentialsDevice device)
+ : base(key, messagePath, device)
+ {
+ _cameraMute = device as IHasCameraMute ?? throw new ArgumentNullException(nameof(device));
+ _cameraMute.CameraIsMutedFeedback.OutputChange += CameraIsMutedFeedback_OutputChange;
+ }
+
+ ///
+ protected override void RegisterActions()
+ {
+ base.RegisterActions();
+
+ AddAction("/fullStatus", (id, content) => SendFullStatus(id));
+ AddAction("/cameraMuteStatus", (id, content) => SendFullStatus(id));
+
+ AddAction("/cameraMuteOn", (id, content) => _cameraMute.CameraMuteOn());
+ AddAction("/cameraMuteOff", (id, content) => _cameraMute.CameraMuteOff());
+ AddAction("/cameraMuteToggle", (id, content) => _cameraMute.CameraMuteToggle());
+ }
+
+ private void CameraIsMutedFeedback_OutputChange(object sender, FeedbackEventArgs e)
+ {
+ try
+ {
+ PostStatusMessage(new IHasCameraMuteStateMessage
+ {
+ CameraIsMuted = e.BoolValue
+ });
+ }
+ catch (Exception ex)
+ {
+ this.LogError(ex, "Error posting camera mute state");
+ }
+ }
+
+ private void SendFullStatus(string id = null)
+ {
+ try
+ {
+ var state = new IHasCameraMuteStateMessage
+ {
+ CameraIsMuted = _cameraMute.CameraIsMutedFeedback.BoolValue
+ };
+
+ Task.Run(() => PostStatusMessage(state, id));
+ }
+ catch (Exception ex)
+ {
+ this.LogError(ex, "Error sending camera mute full status");
+ }
+ }
+ }
+
+ ///
+ /// State message for
+ ///
+ public class IHasCameraMuteStateMessage : DeviceStateMessageBase
+ {
+ ///
+ /// Gets or sets a value indicating whether the camera is muted. Null if unknown or not applicable.
+ ///
+ [JsonProperty("cameraIsMuted", NullValueHandling = NullValueHandling.Ignore)]
+ public bool? CameraIsMuted { get; set; }
+ }
+}
diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCameraPresetsMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCameraPresetsMessenger.cs
new file mode 100644
index 00000000..b7cc61eb
--- /dev/null
+++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IHasCameraPresetsMessenger.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using PepperDash.Core;
+using PepperDash.Core.Logging;
+using PepperDash.Essentials.Core;
+using PepperDash.Essentials.Devices.Common.Cameras;
+
+namespace PepperDash.Essentials.AppServer.Messengers
+{
+ ///
+ /// Provides a messaging bridge for devices implementing
+ ///
+ public class IHasCameraPresetsMessenger : MessengerBase
+ {
+ private readonly IHasCameraPresets _cameraPresets;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key for the messenger.
+ /// The message path for the messenger.
+ /// The device implementing .
+ public IHasCameraPresetsMessenger(string key, string messagePath, EssentialsDevice device)
+ : base(key, messagePath, device)
+ {
+ _cameraPresets = device as IHasCameraPresets ?? throw new ArgumentNullException(nameof(device));
+ _cameraPresets.PresetsListHasChanged += PresetsListHasChanged;
+ }
+
+ ///
+ protected override void RegisterActions()
+ {
+ base.RegisterActions();
+
+ AddAction("/fullStatus", (id, content) => SendFullStatus(id));
+ AddAction("/presetsStatus", (id, content) => SendFullStatus(id));
+
+ AddAction("/recallPreset", (id, content) =>
+ {
+ var msg = content.ToObject>();
+ _cameraPresets.PresetSelect(msg.Value);
+ });
+
+ AddAction("/savePreset", (id, content) =>
+ {
+ var msg = content.ToObject>();
+ _cameraPresets.PresetStore(msg.Value, string.Empty);
+ });
+ }
+
+ private void PresetsListHasChanged(object sender, EventArgs e)
+ {
+ try
+ {
+ PostStatusMessage(new IHasCameraPresetsStateMessage
+ {
+ Presets = _cameraPresets.Presets
+ });
+ }
+ catch (Exception ex)
+ {
+ this.LogError(ex, "Error posting camera presets state");
+ }
+ }
+
+ private void SendFullStatus(string id = null)
+ {
+ try
+ {
+ var state = new IHasCameraPresetsStateMessage
+ {
+ Presets = _cameraPresets.Presets
+ };
+
+ Task.Run(() => PostStatusMessage(state, id));
+ }
+ catch (Exception ex)
+ {
+ this.LogError(ex, "Error sending camera presets full status");
+ }
+ }
+ }
+
+ ///
+ /// State message for
+ ///
+ public class IHasCameraPresetsStateMessage : DeviceStateMessageBase
+ {
+ ///
+ /// Gets or sets the list of camera presets.
+ ///
+ [JsonProperty("presets", NullValueHandling = NullValueHandling.Ignore)]
+ public List Presets { get; set; }
+ }
+}