feat: Adds device interface support info to joinroom response in MC websocket server.

Enhance MessengerBase and WebSocketServer functionality

Updated MessengerBase with new methods for action management and message posting, along with improved documentation. Introduced DeviceMessageBase for better message representation.

Enhanced MobileControlWebsocketServer to support device interfaces, adding DeviceInterfaceSupport to JoinResponse and a new DeviceInterfaceInfo class for detailed device information.
This commit is contained in:
Neil Dorin
2025-09-24 14:49:41 -06:00
parent b0a090062f
commit 06341b14f3
2 changed files with 102 additions and 4 deletions

View File

@@ -15,12 +15,18 @@ namespace PepperDash.Essentials.AppServer.Messengers
/// </summary> /// </summary>
public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger public abstract class MessengerBase : EssentialsDevice, IMobileControlMessenger
{ {
/// <summary>
/// The device this messenger is associated with
/// </summary>
protected IKeyName _device; protected IKeyName _device;
private readonly List<string> _deviceInterfaces; private readonly List<string> _deviceInterfaces;
private readonly Dictionary<string, Action<string, JToken>> _actions = new Dictionary<string, Action<string, JToken>>(); private readonly Dictionary<string, Action<string, JToken>> _actions = new Dictionary<string, Action<string, JToken>>();
/// <summary>
/// Gets the DeviceKey
/// </summary>
public string DeviceKey => _device?.Key ?? ""; public string DeviceKey => _device?.Key ?? "";
@@ -50,6 +56,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
MessagePath = messagePath; MessagePath = messagePath;
} }
/// <summary>
/// Constructor for a messenger associated with a device
/// </summary>
/// <param name="key"></param>
/// <param name="messagePath"></param>
/// <param name="device"></param>
protected MessengerBase(string key, string messagePath, IKeyName device) protected MessengerBase(string key, string messagePath, IKeyName device)
: this(key, messagePath) : this(key, messagePath)
{ {
@@ -96,6 +108,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
action(id, content); action(id, content);
} }
/// <summary>
/// Adds an action for a given path
/// </summary>
/// <param name="path"></param>
/// <param name="action"></param>
protected void AddAction(string path, Action<string, JToken> action) protected void AddAction(string path, Action<string, JToken> action)
{ {
if (_actions.ContainsKey(path)) if (_actions.ContainsKey(path))
@@ -115,6 +132,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
return _actions.Keys.ToList(); return _actions.Keys.ToList();
} }
/// <summary>
/// Removes an action for a given path
/// </summary>
/// <param name="path"></param>
protected void RemoveAction(string path) protected void RemoveAction(string path)
{ {
if (!_actions.ContainsKey(path)) if (!_actions.ContainsKey(path))
@@ -128,7 +149,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
/// <summary> /// <summary>
/// Implemented in extending classes. Wire up API calls and feedback here /// Implemented in extending classes. Wire up API calls and feedback here
/// </summary> /// </summary>
/// <param name="appServerController"></param>
protected virtual void RegisterActions() protected virtual void RegisterActions()
{ {
@@ -137,8 +157,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
/// <summary> /// <summary>
/// Helper for posting status message /// Helper for posting status message
/// </summary> /// </summary>
/// <param name="type"></param>
/// <param name="message"></param> /// <param name="message"></param>
/// <param name="clientId">Optional client id that will direct the message back to only that client</param>
protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null) protected void PostStatusMessage(DeviceStateMessageBase message, string clientId = null)
{ {
try try
@@ -169,6 +189,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
} }
} }
/// <summary>
/// Helper for posting status message
/// </summary>
/// <param name="type"></param>
/// <param name="deviceState"></param>
/// <param name="clientId">Optional client id that will direct the message back to only that client</param>
protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null) protected void PostStatusMessage(string type, DeviceStateMessageBase deviceState, string clientId = null)
{ {
try try
@@ -192,6 +218,12 @@ namespace PepperDash.Essentials.AppServer.Messengers
} }
} }
/// <summary>
/// Helper for posting status message
/// </summary>
/// <param name="content"></param>
/// <param name="type"></param>
/// <param name="clientId">Optional client id that will direct the message back to only that client</param>
protected void PostStatusMessage(JToken content, string type = "", string clientId = null) protected void PostStatusMessage(JToken content, string type = "", string clientId = null)
{ {
try try
@@ -204,6 +236,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
} }
} }
/// <summary>
/// Helper for posting event message
/// </summary>
/// <param name="message"></param>
protected void PostEventMessage(DeviceEventMessageBase message) protected void PostEventMessage(DeviceEventMessageBase message)
{ {
message.Key = _device.Key; message.Key = _device.Key;
@@ -217,6 +253,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
}); });
} }
/// <summary>
/// Helper for posting event message
/// </summary>
/// <param name="message"></param>
/// <param name="eventType"></param>
protected void PostEventMessage(DeviceEventMessageBase message, string eventType) protected void PostEventMessage(DeviceEventMessageBase message, string eventType)
{ {
message.Key = _device.Key; message.Key = _device.Key;
@@ -232,6 +273,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
}); });
} }
/// <summary>
/// Helper for posting event message with no content
/// </summary>
/// <param name="eventType"></param>
protected void PostEventMessage(string eventType) protected void PostEventMessage(string eventType)
{ {
AppServerController?.SendMessageObject(new MobileControlMessage AppServerController?.SendMessageObject(new MobileControlMessage
@@ -243,6 +288,9 @@ namespace PepperDash.Essentials.AppServer.Messengers
} }
/// <summary>
/// Base class for device messages that include the type of message
/// </summary>
public abstract class DeviceMessageBase public abstract class DeviceMessageBase
{ {
/// <summary> /// <summary>
@@ -266,10 +314,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
[JsonProperty("messageType")] [JsonProperty("messageType")]
public string MessageType => GetType().Name; public string MessageType => GetType().Name;
[JsonProperty("messageBasePath")]
/// <summary> /// <summary>
/// Gets or sets the MessageBasePath /// Gets or sets the MessageBasePath
/// </summary> /// </summary>
[JsonProperty("messageBasePath")]
public string MessageBasePath { get; set; } public string MessageBasePath { get; set; }
} }
@@ -284,6 +333,10 @@ namespace PepperDash.Essentials.AppServer.Messengers
[JsonProperty("interfaces")] [JsonProperty("interfaces")]
public List<string> Interfaces { get; private set; } public List<string> Interfaces { get; private set; }
/// <summary>
/// Sets the interfaces implemented by the device sending the message
/// </summary>
/// <param name="interfaces"></param>
public void SetInterfaces(List<string> interfaces) public void SetInterfaces(List<string> interfaces)
{ {
Interfaces = interfaces; Interfaces = interfaces;

View File

@@ -972,6 +972,20 @@ namespace PepperDash.Essentials.WebSocketServer
res.StatusCode = 200; res.StatusCode = 200;
res.ContentType = "application/json"; res.ContentType = "application/json";
var devices = DeviceManager.GetDevices();
Dictionary<string, DeviceInterfaceInfo> deviceInterfaces = new Dictionary<string, DeviceInterfaceInfo>();
foreach (var device in devices)
{
var interfaces = device?.GetType().GetInterfaces().Select((i) => i.Name).ToList() ?? new List<string>();
deviceInterfaces.Add(device.Key, new DeviceInterfaceInfo
{
Key = device.Key,
Name = device is IKeyName ? (device as IKeyName).Name : "",
Interfaces = interfaces
});
}
// Construct the response object // Construct the response object
JoinResponse jRes = new JoinResponse JoinResponse jRes = new JoinResponse
{ {
@@ -985,7 +999,8 @@ namespace PepperDash.Essentials.WebSocketServer
UserAppUrl = string.Format("http://{0}:{1}/mc/app", UserAppUrl = string.Format("http://{0}:{1}/mc/app",
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0), CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0),
Port), Port),
EnableDebug = false EnableDebug = false,
DeviceInterfaceSupport = deviceInterfaces
}; };
// Serialize to JSON and convert to Byte[] // Serialize to JSON and convert to Byte[]
@@ -1361,6 +1376,12 @@ namespace PepperDash.Essentials.WebSocketServer
[JsonProperty("config")] [JsonProperty("config")]
public object Config { get; set; } public object Config { get; set; }
/// <summary>
/// Gets or sets the DeviceInterfaceSupport
/// </summary>
[JsonProperty("deviceInterfaceSupport")]
public Dictionary<string, DeviceInterfaceInfo> DeviceInterfaceSupport { get; set; }
/// <summary> /// <summary>
/// Gets or sets the CodeExpires /// Gets or sets the CodeExpires
@@ -1389,4 +1410,28 @@ namespace PepperDash.Essentials.WebSocketServer
[JsonProperty("enableDebug")] [JsonProperty("enableDebug")]
public bool EnableDebug { get; set; } public bool EnableDebug { get; set; }
} }
/// <summary>
/// Represents info about a device including supproted interfaces
/// </summary>
public class DeviceInterfaceInfo : IKeyName
{
/// <summary>
/// Gets or sets the Key
/// </summary>
[JsonProperty("key")]
public string Key { get; set; }
/// <summary>
/// Gets or sets the Name
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the Interfaces
/// </summary>
[JsonProperty("interfaces")]
public List<string> Interfaces { get; set; }
}
} }