diff --git a/src/PepperDash.Core/Logging/Debug.cs b/src/PepperDash.Core/Logging/Debug.cs index 97a6e93e..4160da21 100644 --- a/src/PepperDash.Core/Logging/Debug.cs +++ b/src/PepperDash.Core/Logging/Debug.cs @@ -272,6 +272,11 @@ public static class Debug { LogMessage(LogEventLevel.Information, "Console debug level set to {minimumLevel}", consoleLoggingLevelSwitch.MinimumLevel); }; + + errorLogLevelSwitch.MinimumLevelChanged += (sender, args) => + { + LogMessage(LogEventLevel.Information, "Error log debug level set to {minimumLevel}", errorLogLevelSwitch.MinimumLevel); + }; } catch (Exception ex) { @@ -424,61 +429,88 @@ public static class Debug if (levelString.Trim() == "?") { _console?.ConsoleCommandResponse( - - "Used to set the minimum level of debug messages to be printed to the console:\r\n" + - "[LogLevel] [TimeoutInMinutes]\r\n" + - "If TimeoutInMinutes is not provided, it will default to 120 minutes. If provided, the level will reset to Information after the timeout period elapses.\r\n" + - "LogLevel can be either a number from 0-5 or a log level name. If using a number, the mapping is as follows:\r\n" + - $"{_logLevels[0]} = 0\r\n" + - $"{_logLevels[1]} = 1\r\n" + - $"{_logLevels[2]} = 2\r\n" + - $"{_logLevels[3]} = 3\r\n" + - $"{_logLevels[4]} = 4\r\n" + - $"{_logLevels[5]} = 5"); + "Used to set the minimum level of debug messages:\r\n" + + "Usage: appdebug:P [sink] [level] [timeoutMinutes]\r\n" + + " sink (optional): console (default), errorlog, websocket, file, all\r\n" + + " timeoutMinutes (optional, console sink only): level resets to Information after this many minutes (default 120)\r\n" + + $" level: {string.Join(", ", _logLevels.Values)}"); return; } if (string.IsNullOrEmpty(levelString.Trim())) { - _console?.ConsoleCommandResponse($"AppDebug level = {consoleLoggingLevelSwitch.MinimumLevel}"); + _console?.ConsoleCommandResponse($"Console log level = {consoleLoggingLevelSwitch.MinimumLevel}\r\n"); + _console?.ConsoleCommandResponse($"File log level = {fileLoggingLevelSwitch.MinimumLevel}\r\n"); + _console?.ConsoleCommandResponse($"Error log level = {errorLogLevelSwitch.MinimumLevel}\r\n"); + _console?.ConsoleCommandResponse($"Websocket log level = {websocketLoggingLevelSwitch.MinimumLevel}\r\n"); return; } - // split on space to allow for potential future addition of timeout parameter without breaking existing command usage - var parts = Regex.Split(levelString.Trim(), @"\s+"); - levelString = parts[0]; + var tokens = Regex.Split(levelString.Trim(), @"\s+"); - if (parts.Length > 1 && long.TryParse(parts[1], out var timeout)) + // Determine whether the first token is a sink name or a level + var knownSinks = new[] { "console", "errorlog", "websocket", "file", "all" }; + string sinkName; + string levelToken; + long timeoutMinutes = defaultConsoleDebugTimeoutMin; + + if (tokens.Length >= 2 && Array.IndexOf(knownSinks, tokens[0].ToLowerInvariant()) >= 0) { - timeout = Math.Max(timeout, 1); // enforce minimum timeout of 1 minute - consoleDebugTimer.Interval = timeout * 60000; + // First token is a sink name + sinkName = tokens[0].ToLowerInvariant(); + levelToken = tokens[1]; + + if (tokens.Length >= 3 && long.TryParse(tokens[2], out var parsedTimeout)) + timeoutMinutes = Math.Max(parsedTimeout, 1); + } + else + { + // No sink prefix — treat as console with optional timeout as second token + sinkName = "console"; + levelToken = tokens[0]; + + if (tokens.Length >= 2 && long.TryParse(tokens[1], out var parsedTimeout)) + timeoutMinutes = Math.Max(parsedTimeout, 1); } - // first try to parse as int for backward compatibility with existing usage of numeric levels + // Parse the level + LogEventLevel level; - if (int.TryParse(levelString, out var levelInt)) + if (!Enum.TryParse(levelToken, true, out level)) { - if (levelInt < 0 || levelInt > 5) - { - _console?.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5"); - return; - } - SetDebugLevel((uint)levelInt); + _console?.ConsoleCommandResponse($"Error: Unable to parse '{levelToken}' to valid log level. Valid levels: {string.Join(", ", _logLevels.Values)}"); return; } - // make this parse attempt case-insensitive to allow for more flexible command usage - if (Enum.TryParse(levelString, true, out var levelEnum)) + // Apply to the specified sink(s) + switch (sinkName) { - SetDebugLevel(levelEnum); - return; + case "console": + SetDebugLevel(level, (int)timeoutMinutes); + break; + case "errorlog": + SetErrorLogMinimumDebugLevel(level); + break; + case "websocket": + SetWebSocketMinimumDebugLevel(level); + break; + case "file": + SetFileMinimumDebugLevel(level); + break; + case "all": + SetDebugLevel(level, (int)timeoutMinutes); + SetErrorLogMinimumDebugLevel(level); + SetWebSocketMinimumDebugLevel(level); + SetFileMinimumDebugLevel(level); + break; + default: + _console?.ConsoleCommandResponse($"Error: Unknown sink '{sinkName}'. Valid sinks: console, errorlog, websocket, file, all"); + break; } - - _console?.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level"); } catch { - _console?.ConsoleCommandResponse("Usage: appdebug:P [0-5]"); + _console?.ConsoleCommandResponse("Usage: appdebug:P [sink] [level] [timeoutMinutes]"); } } diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs index f920e5fe..074d51de 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/IMobileControl.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using Newtonsoft.Json.Linq; using PepperDash.Core; +using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Core.DeviceTypeInterfaces; @@ -68,4 +70,19 @@ public interface IMobileControl : IKeyed /// messenger key to find /// Messenger if found, null otherwise IMobileControlRoomMessenger GetRoomMessenger(string key); + + /// + /// Registers default mobile-control messengers for the given device based on the + /// interfaces it implements. When is null all + /// applicable messengers are added; when a list is supplied only messengers whose + /// registry entry type appears in that list are added. + /// + /// The device to add messengers for. + /// + /// Optional filter. Pass typeof(IBasicVolumeControls), + /// typeof(IHasInputs<string>), etc. to restrict which messengers are + /// created. Pass null (or omit the argument) to add all applicable messengers. + /// + void AddDefaultMessengersForDevice(EssentialsDevice device, IEnumerable interfaces = null); + } diff --git a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs index 305a14ec..7a62d1c3 100644 --- a/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs +++ b/src/PepperDash.Essentials.Core/Devices/EssentialsDevice.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using PepperDash.Core; using PepperDash.Essentials.Core.Config; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; using Serilog.Events; namespace PepperDash.Essentials.Core; @@ -84,7 +86,10 @@ public abstract class EssentialsDevice : Device } /// - /// Override this method to perform any initialization that requires all devices to be activated. This method is called automatically after the DeviceManager.AllDevicesActivated event is fired, and should not be called directly. + /// Override this method to perform any initialization that requires all devices to be activated. + /// This method is called automatically after the DeviceManager.AllDevicesActivated event is fired, + /// and should not be called directly. + /// If this is not called then no Mobile Control messengers will be created. /// /// protected override bool CustomActivate() @@ -99,7 +104,21 @@ public abstract class EssentialsDevice : Device /// protected virtual void CreateMobileControlMessengers() { + var controller = DeviceManager.AllDevices + .OfType() + .FirstOrDefault(); + if (controller == null) + { + Debug.LogMessage( + LogEventLevel.Warning, + this, + "No IMobileControl controller found; default messengers will not be registered for {key}", + Key); + return; + } + + controller.AddDefaultMessengersForDevice(this); } } diff --git a/src/PepperDash.Essentials.MobileControl/MessengerFactoryRegistry.cs b/src/PepperDash.Essentials.MobileControl/MessengerFactoryRegistry.cs new file mode 100644 index 00000000..e333cd0b --- /dev/null +++ b/src/PepperDash.Essentials.MobileControl/MessengerFactoryRegistry.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using PepperDash.Essentials.AppServer.Messengers; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.CrestronIO; +using PepperDash.Essentials.Core.DeviceInfo; +using PepperDash.Essentials.Core.DeviceTypeInterfaces; +using PepperDash.Essentials.Core.Lighting; +using PepperDash.Essentials.Core.Routing; +using PepperDash.Essentials.Core.Shades; +using PepperDash.Essentials.Devices.Common.AudioCodec; +using PepperDash.Essentials.Devices.Common.Cameras; +using PepperDash.Essentials.Devices.Common.Displays; +using PepperDash.Essentials.Devices.Common.SoftCodec; +using PepperDash.Essentials.Devices.Common.VideoCodec; +using PepperDash.Essentials.Room.MobileControl; + +namespace PepperDash.Essentials +{ + /// + /// Describes a single entry in . + /// + internal sealed class MessengerFactoryEntry + { + /// + /// The primary type used for both IsAssignableFrom matching and for + /// caller-supplied type filtering via . + /// + public Type InterfaceType { get; } + + /// + /// Optional additional condition. When null the entry matches any device + /// whose runtime type satisfies . + /// + public Func Predicate { get; } + + /// + /// Factory that creates the messenger. Parameters are + /// (device, messagePath, controllerKey). + /// + public Func Factory { get; } + + public MessengerFactoryEntry( + Type interfaceType, + Func factory, + Func predicate = null) + { + InterfaceType = interfaceType; + Factory = factory; + Predicate = predicate; + } + + /// + /// Returns true when this entry should produce a messenger for + /// . + /// + public bool Matches(EssentialsDevice device) + { + return Predicate != null + ? Predicate(device) + : InterfaceType.IsAssignableFrom(device.GetType()); + } + } + + /// + /// Maps device interface / class types to messenger factories, replacing the + /// previous cascade of if (device is X) checks in + /// SetupDefaultDeviceMessengers. + /// + internal static class MessengerFactoryRegistry + { + public static IReadOnlyList Entries { get; } = + new List + { + // ── Communication ──────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(ICommunicationMonitor), + (d, mp, ck) => new ICommunicationMonitorMessenger( + $"{d.Key}-commMonitor-{ck}", mp, (ICommunicationMonitor)d) + ), + + // ── Cameras ────────────────────────────────────────────────────────────── + // CameraBase only when the device does NOT also implement IHasCameraControls + new MessengerFactoryEntry( + typeof(CameraBase), + (d, mp, ck) => new CameraBaseMessenger( + $"{d.Key}-cameraBase-{ck}", (CameraBase)d, mp), + predicate: d => d is CameraBase && !(d is IHasCameraControls) + ), + + new MessengerFactoryEntry( + typeof(IHasCameraControls), + (d, mp, ck) => new CameraBaseMessenger( + $"{d.Key}-hasCamerasWithControls-{ck}", (IHasCameraControls)d, mp) + ), + new MessengerFactoryEntry( + typeof(IHasCamerasWithControls), + (d, mp, ck) => new IHasCamerasWithControlMessenger( + $"{d.Key}-cameras-{ck}", mp, (IHasCamerasWithControls)d) + ), + + // ── Routing ────────────────────────────────────────────────────────────── + // BlueJeansPc implements IRunRouteAction + new MessengerFactoryEntry( + typeof(BlueJeansPc), + (d, mp, ck) => new RunRouteActionMessenger( + $"{d.Key}-runRouteAction-{ck}", (IRunRouteAction)d, mp) + ), + + // ── Presets ────────────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(ITvPresetsProvider), + (d, mp, ck) => new DevicePresetsModelMessenger( + $"{d.Key}-presets-{ck}", mp, (ITvPresetsProvider)d) + ), + + // ── Displays ───────────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(DisplayBase), + (d, mp, ck) => new DisplayBaseMessenger( + $"{d.Key}-displayBase-{ck}", mp, (DisplayBase)d) + ), + new MessengerFactoryEntry( + typeof(TwoWayDisplayBase), + (d, mp, ck) => new TwoWayDisplayBaseMessenger( + $"{d.Key}-twoWayDisplay-{ck}", mp, (TwoWayDisplayBase)d) + ), + + // ── Audio / Video ───────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IBasicVolumeControls), + (d, mp, ck) => new DeviceVolumeMessenger( + $"{d.Key}-volume-{ck}", mp, (IBasicVolumeControls)d) + ), + new MessengerFactoryEntry( + typeof(IBasicVideoMuteWithFeedback), + (d, mp, ck) => new IBasicVideoMuteWithFeedbackMessenger( + $"{d.Key}-videoMute-{ck}", mp, (IBasicVideoMuteWithFeedback)d) + ), + + // ── Lighting ───────────────────────────────────────────────────────────── + // ILightingScenes covers LightingBase too (LightingBase : ILightingScenes) + new MessengerFactoryEntry( + typeof(ILightingScenes), + (d, mp, ck) => new ILightingScenesMessenger( + $"{d.Key}-lighting-{ck}", (ILightingScenes)d, mp) + ), + + // ── Shades ─────────────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IShadesOpenCloseStop), + (d, mp, ck) => new IShadesOpenCloseStopMessenger( + $"{d.Key}-shades-{ck}", (IShadesOpenCloseStop)d, mp) + ), + + // ── Codecs ─────────────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(VideoCodecBase), + (d, mp, ck) => new VideoCodecBaseMessenger( + $"{d.Key}-videoCodec-{ck}", (VideoCodecBase)d, mp) + ), + new MessengerFactoryEntry( + typeof(AudioCodecBase), + (d, mp, ck) => new AudioCodecBaseMessenger( + $"{d.Key}-audioCodec-{ck}", (AudioCodecBase)d, mp) + ), + + // ── Set-top box controls ────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(ISetTopBoxControls), + (d, mp, ck) => new ISetTopBoxControlsMessenger( + $"{d.Key}-stb-{ck}", mp, (ISetTopBoxControls)d) + ), + new MessengerFactoryEntry( + typeof(IChannel), + (d, mp, ck) => new IChannelMessenger( + $"{d.Key}-channel-{ck}", mp, (IChannel)d) + ), + new MessengerFactoryEntry( + typeof(IColor), + (d, mp, ck) => new IColorMessenger( + $"{d.Key}-color-{ck}", mp, (IColor)d) + ), + new MessengerFactoryEntry( + typeof(IDPad), + (d, mp, ck) => new IDPadMessenger( + $"{d.Key}-dPad-{ck}", mp, (IDPad)d) + ), + new MessengerFactoryEntry( + typeof(INumericKeypad), + (d, mp, ck) => new INumericKeypadMessenger( + $"{d.Key}-numericKeypad-{ck}", mp, (INumericKeypad)d) + ), + + // ── Power ───────────────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IHasPowerControl), + (d, mp, ck) => new IHasPowerMessenger( + $"{d.Key}-powerControl-{ck}", mp, (IHasPowerControl)d) + ), + new MessengerFactoryEntry( + typeof(IHasPowerControlWithFeedback), + (d, mp, ck) => new IHasPowerControlWithFeedbackMessenger( + $"{d.Key}-powerFeedback-{ck}", mp, (IHasPowerControlWithFeedback)d) + ), + + // ── Transport / sources ─────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(ITransport), + (d, mp, ck) => new ITransportMessenger( + $"{d.Key}-transport-{ck}", mp, (ITransport)d) + ), + new MessengerFactoryEntry( + typeof(ICurrentSources), + (d, mp, ck) => new ICurrentSourcesMessenger( + $"{d.Key}-currentSources-{ck}", mp, (ICurrentSources)d) + ), + new MessengerFactoryEntry( + typeof(ISwitchedOutput), + (d, mp, ck) => new ISwitchedOutputMessenger( + $"{d.Key}-switchedOutput-{ck}", (ISwitchedOutput)d, mp) + ), + + // ── Device info / levels / inputs ───────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IDeviceInfoProvider), + (d, mp, ck) => new IDeviceInfoProviderMessenger( + $"{d.Key}-deviceInfo-{ck}", mp, (IDeviceInfoProvider)d) + ), + new MessengerFactoryEntry( + typeof(ILevelControls), + (d, mp, ck) => new ILevelControlsMessenger( + $"{d.Key}-levelControls-{ck}", mp, (ILevelControls)d) + ), + new MessengerFactoryEntry( + typeof(IHasInputs), + (d, mp, ck) => new IHasInputsMessenger( + $"{d.Key}-inputs-{ck}", mp, (IHasInputs)d) + ), + new MessengerFactoryEntry( + typeof(IHasInputs), + (d, mp, ck) => new IHasInputsMessenger( + $"{d.Key}-inputs-{ck}", mp, (IHasInputs)d) + ), + new MessengerFactoryEntry( + typeof(IHasInputs), + (d, mp, ck) => new IHasInputsMessenger( + $"{d.Key}-inputs-{ck}", mp, (IHasInputs)d) + ), + + // ── Matrix routing ──────────────────────────────────────────────────────── + // Preserving original key format (no controller key suffix) + new MessengerFactoryEntry( + typeof(IMatrixRouting), + (d, mp, _) => new IMatrixRoutingMessenger( + $"{d.Key}-matrixRouting", mp, (IMatrixRouting)d) + ), + + // ── Environmental sensors ───────────────────────────────────────────────── + // Preserving original key format (no controller key suffix) + new MessengerFactoryEntry( + typeof(ITemperatureSensor), + (d, mp, _) => new ITemperatureSensorMessenger( + $"{d.Key}-tempSensor", (ITemperatureSensor)d, mp) + ), + new MessengerFactoryEntry( + typeof(IHumiditySensor), + (d, mp, _) => new IHumiditySensorMessenger( + $"{d.Key}-humiditySensor", (IHumiditySensor)d, mp) + ), + + // ── Room combining ──────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IEssentialsRoomCombiner), + (d, mp, ck) => new IEssentialsRoomCombinerMessenger( + $"{d.Key}-roomCombiner-{ck}", mp, (IEssentialsRoomCombiner)d) + ), + + // ── Projector screen ────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IProjectorScreenLiftControl), + (d, mp, ck) => new IProjectorScreenLiftControlMessenger( + $"{d.Key}-screenLiftControl-{ck}", mp, (IProjectorScreenLiftControl)d) + ), + + // ── DSP ─────────────────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IDspPresets), + (d, mp, ck) => new IDspPresetsMessenger( + $"{d.Key}-dspPresets-{ck}", mp, (IDspPresets)d) + ), + + // Room Entries + // ── Event schedule ──────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IRoomEventSchedule), + (d, mp, ck) => new RoomEventScheduleMessenger( + $"{d.Key}-schedule-{ck}", mp, (IRoomEventSchedule)d) + ), + + // ── Tech password ───────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(ITechPassword), + (d, mp, ck) => new ITechPasswordMessenger( + $"{d.Key}-techPassword-{ck}", mp, (ITechPassword)d) + ), + + // ── Shutdown prompt timer ───────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(IShutdownPromptTimer), + (d, mp, ck) => new IShutdownPromptTimerMessenger( + $"{d.Key}-shutdownPromptTimer-{ck}", mp, (IShutdownPromptTimer)d) + ), + + // ── Level controls ──────────────────────────────────────────────────────── + new MessengerFactoryEntry( + typeof(ILevelControls), + (d, mp, ck) => new ILevelControlsMessenger( + $"{d.Key}-levelControls-{ck}", mp, (ILevelControls)d) + ), + }; + } +} diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs index 1b0580f6..5e3314aa 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs @@ -17,22 +17,10 @@ using PepperDash.Essentials.AppServer; using PepperDash.Essentials.AppServer.Messengers; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; -using PepperDash.Essentials.Core.CrestronIO; -using PepperDash.Essentials.Core.DeviceInfo; using PepperDash.Essentials.Core.DeviceTypeInterfaces; -using PepperDash.Essentials.Core.Lighting; using PepperDash.Essentials.Core.Monitoring; using PepperDash.Essentials.Core.Queues; -using PepperDash.Essentials.Core.Routing; -using PepperDash.Essentials.Core.Shades; using PepperDash.Essentials.Core.Web; -using PepperDash.Essentials.Devices.Common.AudioCodec; -using PepperDash.Essentials.Devices.Common.Cameras; -using PepperDash.Essentials.Devices.Common.Displays; -using PepperDash.Essentials.Devices.Common.Lighting; -using PepperDash.Essentials.Devices.Common.SoftCodec; -using PepperDash.Essentials.Devices.Common.VideoCodec; -using PepperDash.Essentials.Room.MobileControl; using PepperDash.Essentials.RoomBridges; using PepperDash.Essentials.Services; using PepperDash.Essentials.WebApiHandlers; @@ -138,7 +126,7 @@ namespace PepperDash.Essentials "No system_url value defined in config. Checking for value from SIMPL Bridge." ); - if (!string.IsNullOrEmpty(SystemUrl)) + if (string.IsNullOrEmpty(SystemUrl)) { this.LogError( "No system_url value defined in config or SIMPL Bridge. Unable to connect to Mobile Control." @@ -254,10 +242,6 @@ namespace PepperDash.Essentials AddPreActivationAction(() => LinkSystemMonitorToAppServer()); - AddPreActivationAction(() => SetupDefaultDeviceMessengers()); - - AddPreActivationAction(() => SetupDefaultRoomMessengers()); - AddPreActivationAction(() => AddWebApiPaths()); AddPreActivationAction(() => @@ -282,765 +266,36 @@ namespace PepperDash.Essentials }); } - private void SetupDefaultRoomMessengers() + /// + public void AddDefaultMessengersForDevice(EssentialsDevice device, IEnumerable interfaces = null) { - this.LogVerbose("Setting up room messengers"); + var interfaceSet = interfaces != null ? new HashSet(interfaces) : [.. device.GetType().GetInterfaces()]; + var messengerAdded = false; - foreach (var room in DeviceManager.AllDevices.OfType()) + foreach (var entry in MessengerFactoryRegistry.Entries) { - this.LogVerbose( - "Setting up room messengers for room: {key}", - room.Key - ); + if (interfaceSet != null && !interfaceSet.Contains(entry.InterfaceType)) + continue; - var messenger = new MobileControlEssentialsRoomBridge(room); + if (!entry.Matches(device)) + continue; - messenger.AddParent(this); + var messenger = entry.Factory(device, $"/device/{device.Key}", Key); - _roomBridges.Add(messenger); + if (messenger == null) + continue; AddDefaultDeviceMessenger(messenger); - - this.LogVerbose( - "Attempting to set up default room messengers for room: {0}", - room.Key - ); - - if (room is IRoomEventSchedule) - { - this.LogInformation("Setting up event schedule messenger for room: {key}", room.Key); - - var scheduleMessenger = new RoomEventScheduleMessenger( - $"{room.Key}-schedule-{Key}", - string.Format("/room/{0}", room.Key), - room as IRoomEventSchedule - ); - - AddDefaultDeviceMessenger(scheduleMessenger); - } - - if (room is ITechPassword) - { - this.LogInformation("Setting up tech password messenger for room: {key}", room.Key); - - var techPasswordMessenger = new ITechPasswordMessenger( - $"{room.Key}-techPassword-{Key}", - string.Format("/room/{0}", room.Key), - room as ITechPassword - ); - - AddDefaultDeviceMessenger(techPasswordMessenger); - } - - if (room is IShutdownPromptTimer) - { - this.LogInformation("Setting up shutdown prompt timer messenger for room: {key}", this, room.Key); - - var shutdownPromptTimerMessenger = new IShutdownPromptTimerMessenger( - $"{room.Key}-shutdownPromptTimer-{Key}", - string.Format("/room/{0}", room.Key), - room as IShutdownPromptTimer - ); - - AddDefaultDeviceMessenger(shutdownPromptTimerMessenger); - } - - if (room is ILevelControls levelControls) - { - this.LogInformation("Setting up level controls messenger for room: {key}", this, room.Key); - - var levelControlsMessenger = new ILevelControlsMessenger( - $"{room.Key}-levelControls-{Key}", - $"/room/{room.Key}", - levelControls - ); - - AddDefaultDeviceMessenger(levelControlsMessenger); - } + messengerAdded = true; } - } - /// - /// Set up the messengers for each device type - /// - private void SetupDefaultDeviceMessengers() - { - bool messengerAdded = false; - - var allDevices = DeviceManager.AllDevices.Where((d) => !(d is IEssentialsRoom)); - - this.LogInformation( - "All Devices that aren't rooms count: {0}", - allDevices?.Count() - ); - - var count = allDevices.Count(); - - foreach (var device in allDevices) + if (!messengerAdded) { - try - { - this.LogVerbose( - "Attempting to set up device messengers for {deviceKey}", - device.Key - ); - - // StatusMonitorBase which is prop of ICommunicationMonitor is not a PepperDash.Core.Device, but is in the device array - if (device is ICommunicationMonitor) - { - this.LogVerbose( - "Checking if {deviceKey} implements ICommunicationMonitor", - device.Key - ); - - if (!(device is ICommunicationMonitor commMonitor)) - { - this.LogDebug( - "{deviceKey} does not implement ICommunicationMonitor. Skipping CommunicationMonitorMessenger", - device.Key - ); - - this.LogDebug("Created all messengers for {deviceKey}. Devices Left: {deviceCount}", device.Key, --count); - - continue; - } - - this.LogDebug( - "Adding CommunicationMonitorMessenger for {deviceKey}", - device.Key - ); - - var commMessenger = new ICommunicationMonitorMessenger( - $"{device.Key}-commMonitor-{Key}", - string.Format("/device/{0}", device.Key), - commMonitor - ); - - AddDefaultDeviceMessenger(commMessenger); - - messengerAdded = true; - } - - // 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( - $"{device.Key}-cameraBase-{Key}", - cameraDevice, - $"/device/{device.Key}" - ); - - AddDefaultDeviceMessenger(cameraMessenger); - - 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( - "Adding IRunRouteActionMessnger for {deviceKey}", - device.Key - ); - - var routeMessenger = new RunRouteActionMessenger( - $"{device.Key}-runRouteAction-{Key}", - device as BlueJeansPc, - $"/device/{device.Key}" - ); - - AddDefaultDeviceMessenger(routeMessenger); - - messengerAdded = true; - } - - if (device is ITvPresetsProvider) - { - this.LogVerbose( - "Trying to cast to ITvPresetsProvider for {deviceKey}", - device.Key - ); - - var presetsDevice = device as ITvPresetsProvider; - - - this.LogVerbose( - "Adding ITvPresetsProvider for {deviceKey}", - device.Key - ); - - var presetsMessenger = new DevicePresetsModelMessenger( - $"{device.Key}-presets-{Key}", - $"/device/{device.Key}", - presetsDevice - ); - - AddDefaultDeviceMessenger(presetsMessenger); - - messengerAdded = true; - } - - - if (device is DisplayBase) - { - this.LogVerbose("Adding actions for device: {0}", device.Key); - - var dbMessenger = new DisplayBaseMessenger( - $"{device.Key}-displayBase-{Key}", - $"/device/{device.Key}", - device as DisplayBase - ); - - AddDefaultDeviceMessenger(dbMessenger); - - messengerAdded = true; - } - - if (device is TwoWayDisplayBase twoWayDisplay) - { - this.LogVerbose( - "Adding TwoWayDisplayBase for {deviceKey}", - device.Key - ); - var twoWayDisplayMessenger = new TwoWayDisplayBaseMessenger( - $"{device.Key}-twoWayDisplay-{Key}", - string.Format("/device/{0}", device.Key), - twoWayDisplay - ); - AddDefaultDeviceMessenger(twoWayDisplayMessenger); - - messengerAdded = true; - } - - if (device is IBasicVolumeControls) - { - var deviceKey = device.Key; - this.LogVerbose( - "Adding IBasicVolumeControls for {deviceKey}", - deviceKey - ); - - var volControlDevice = device as IBasicVolumeControls; - var messenger = new DeviceVolumeMessenger( - $"{device.Key}-volume-{Key}", - string.Format("/device/{0}", deviceKey), - volControlDevice - ); - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IBasicVideoMuteWithFeedback) - { - var deviceKey = device.Key; - this.LogVerbose( - "Adding IBasicVideoMuteWithFeedback for {deviceKey}", - deviceKey - ); - - var videoMuteControlDevice = device as IBasicVideoMuteWithFeedback; - var messenger = new IBasicVideoMuteWithFeedbackMessenger( - $"{device.Key}-videoMute-{Key}", - string.Format("/device/{0}", deviceKey), - videoMuteControlDevice - ); - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is ILightingScenes || device is LightingBase) - { - var deviceKey = device.Key; - - this.LogVerbose( - "Adding LightingBaseMessenger for {deviceKey}", - deviceKey - ); - - var lightingDevice = device as ILightingScenes; - var messenger = new ILightingScenesMessenger( - $"{device.Key}-lighting-{Key}", - lightingDevice, - string.Format("/device/{0}", deviceKey) - ); - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IShadesOpenCloseStop) - { - var deviceKey = device.Key; - var shadeDevice = device as IShadesOpenCloseStop; - - this.LogVerbose( - "Adding ShadeBaseMessenger for {deviceKey}", - deviceKey - ); - - var messenger = new IShadesOpenCloseStopMessenger( - $"{device.Key}-shades-{Key}", - shadeDevice, - string.Format("/device/{0}", deviceKey) - ); - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is VideoCodecBase codec) - { - this.LogVerbose( - "Adding VideoCodecBaseMessenger for {deviceKey}", codec.Key); - - var messenger = new VideoCodecBaseMessenger( - $"{codec.Key}-videoCodec-{Key}", - codec, - $"/device/{codec.Key}" - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is AudioCodecBase audioCodec) - { - this.LogVerbose( - "Adding AudioCodecBaseMessenger for {deviceKey}", audioCodec.Key - ); - - var messenger = new AudioCodecBaseMessenger( - $"{audioCodec.Key}-audioCodec-{Key}", - audioCodec, - $"/device/{audioCodec.Key}" - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is ISetTopBoxControls stbDevice) - { - this.LogVerbose( - "Adding ISetTopBoxControlMessenger for {deviceKey}" - ); - - var messenger = new ISetTopBoxControlsMessenger( - $"{device.Key}-stb-{Key}", - $"/device/{device.Key}", - stbDevice - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IChannel channelDevice) - { - this.LogVerbose( - "Adding IChannelMessenger for {deviceKey}", device.Key - ); - - var messenger = new IChannelMessenger( - $"{device.Key}-channel-{Key}", - $"/device/{device.Key}", - channelDevice - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IColor colorDevice) - { - this.LogVerbose("Adding IColorMessenger for {deviceKey}", device.Key); - - var messenger = new IColorMessenger( - $"{device.Key}-color-{Key}", - $"/device/{device.Key}", - colorDevice - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IDPad dPadDevice) - { - this.LogVerbose("Adding IDPadMessenger for {deviceKey}", device.Key); - - var messenger = new IDPadMessenger( - $"{device.Key}-dPad-{Key}", - $"/device/{device.Key}", - dPadDevice - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is INumericKeypad nkDevice) - { - this.LogVerbose("Adding INumericKeyapdMessenger for {deviceKey}", device.Key); - - var messenger = new INumericKeypadMessenger( - $"{device.Key}-numericKeypad-{Key}", - $"/device/{device.Key}", - nkDevice - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IHasPowerControl pcDevice) - { - this.LogVerbose("Adding IHasPowerControlMessenger for {deviceKey}", device.Key); - - var messenger = new IHasPowerMessenger( - $"{device.Key}-powerControl-{Key}", - $"/device/{device.Key}", - pcDevice - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IHasPowerControlWithFeedback powerControl) - { - var deviceKey = device.Key; - this.LogVerbose( - "Adding IHasPowerControlWithFeedbackMessenger for {deviceKey}", - deviceKey - ); - - var messenger = new IHasPowerControlWithFeedbackMessenger( - $"{device.Key}-powerFeedback-{Key}", - string.Format("/device/{0}", deviceKey), - powerControl - ); - AddDefaultDeviceMessenger(messenger); - messengerAdded = true; - } - - if (device is ITransport transportDevice) - { - this.LogVerbose( - "Adding ITransportMessenger for {deviceKey}", device.Key - ); - - var messenger = new ITransportMessenger( - $"{device.Key}-transport-{Key}", - $"/device/{device.Key}", - transportDevice - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is ICurrentSources currentSources) - { - this.LogVerbose("Adding CurrentSourcesMessenger for {deviceKey}", device.Key); - - var messenger = new ICurrentSourcesMessenger($"{device.Key}-currentSources-{Key}", $"/device/{device.Key}", currentSources); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is ISwitchedOutput switchedDevice) - { - this.LogVerbose( - "Adding ISwitchedOutputMessenger for {deviceKey}", device.Key - ); - - var messenger = new ISwitchedOutputMessenger( - $"{device.Key}-switchedOutput-{Key}", - switchedDevice, - $"/device/{device.Key}" - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IDeviceInfoProvider provider) - { - this.LogVerbose("Adding IHasDeviceInfoMessenger for {deviceKey}", device.Key - ); - - var messenger = new IDeviceInfoProviderMessenger( - $"{device.Key}-deviceInfo-{Key}", - $"/device/{device.Key}", - provider - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is ILevelControls levelControls) - { - this.LogVerbose( - "Adding LevelControlsMessenger for {deviceKey}", device.Key - ); - - var messenger = new ILevelControlsMessenger( - $"{device.Key}-levelControls-{Key}", - $"/device/{device.Key}", - levelControls - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IHasInputs stringInputs) - { - this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); - - var messenger = new IHasInputsMessenger( - $"{device.Key}-inputs-{Key}", - $"/device/{device.Key}", - stringInputs - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IHasInputs byteInputs) - { - this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); - - var messenger = new IHasInputsMessenger( - $"{device.Key}-inputs-{Key}", - $"/device/{device.Key}", - byteInputs - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IHasInputs intInputs) - { - this.LogVerbose("Adding InputsMessenger for {deviceKey}", device.Key); - - var messenger = new IHasInputsMessenger( - $"{device.Key}-inputs-{Key}", - $"/device/{device.Key}", - intInputs - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IMatrixRouting matrix) - { - this.LogVerbose( - "Adding IMatrixRoutingMessenger for {deviceKey}", - device.Key - ); - - var messenger = new IMatrixRoutingMessenger( - $"{device.Key}-matrixRouting", - $"/device/{device.Key}", - matrix - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is ITemperatureSensor tempSensor) - { - this.LogVerbose( - "Adding ITemperatureSensor for {deviceKey}", - device.Key - ); - - var messenger = new ITemperatureSensorMessenger( - $"{device.Key}-tempSensor", - tempSensor, - $"/device/{device.Key}" - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IHumiditySensor humSensor) - { - this.LogVerbose( - "Adding IHumiditySensor for {deviceKey}", - device.Key - ); - - var messenger = new IHumiditySensorMessenger( - $"{device.Key}-humiditySensor", - humSensor, - $"/device/{device.Key}" - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IEssentialsRoomCombiner roomCombiner) - { - this.LogVerbose( - "Adding IEssentialsRoomCombinerMessenger for {deviceKey}", device.Key - ); - - var messenger = new IEssentialsRoomCombinerMessenger( - $"{device.Key}-roomCombiner-{Key}", - $"/device/{device.Key}", - roomCombiner - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IProjectorScreenLiftControl screenLiftControl) - { - this.LogVerbose("Adding IProjectorScreenLiftControlMessenger for {deviceKey}", device.Key - ); - - var messenger = new IProjectorScreenLiftControlMessenger( - $"{device.Key}-screenLiftControl-{Key}", - $"/device/{device.Key}", - screenLiftControl - ); - - AddDefaultDeviceMessenger(messenger); - - messengerAdded = true; - } - - if (device is IDspPresets dspPresets) - { - this.LogVerbose("Adding IDspPresetsMessenger for {deviceKey}", device.Key - ); - - var messenger = new IDspPresetsMessenger( - $"{device.Key}-dspPresets-{Key}", - $"/device/{device.Key}", - dspPresets - ); - - AddDefaultDeviceMessenger(messenger); - - 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) - { - if (!(device is EssentialsDevice genericDevice) || messengerAdded) - { - this.LogVerbose( - "Skipping GenericMessenger for {deviceKey}. Messenger(s) Added: {messengersAdded}.", - device.Key, - messengerAdded - ); - this.LogDebug( - "AllDevices Completed a device. Devices Left: {count}", - --count - ); - continue; - } - - this.LogDebug( - "Adding GenericMessenger for {deviceKey}", - this, - genericDevice?.Key - ); - - AddDefaultDeviceMessenger( - new GenericMessenger( - genericDevice.Key + "-" + Key + "-generic", - genericDevice, - string.Format("/device/{0}", genericDevice.Key) - ) - ); - } - else - { - this.LogVerbose( - "Not Essentials Device. Skipping GenericMessenger for {deviceKey}", - device.Key - ); - } - this.LogDebug( - "AllDevices Completed a device. Devices Left: {count}", - --count - ); - } - - catch (Exception ex) - { - this.LogException(ex, "Exception setting up default device messengers"); - } + this.LogDebug("Adding GenericMessenger for {deviceKey}", device.Key); + AddDefaultDeviceMessenger(new GenericMessenger( + $"{device.Key}-{Key}-generic", + device, + $"/device/{device.Key}")); } }