mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-07-02 10:38:16 +00:00
feat: enhance IHasDirectoryMessenger with new actions and state messaging for directory management
feat: update MobileControlConfig to enable messenger subscriptions by default fix: improve HandleBatchDeviceFullStatus to support granular device status requests and enhance error handling
This commit is contained in:
parent
77c78af74b
commit
8748157362
4 changed files with 93 additions and 28 deletions
|
|
@ -50,7 +50,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
};
|
||||
}
|
||||
|
||||
private void SendCurrentSourceStatus(string id = null)
|
||||
private void SendCurrentSourceStatus(string id)
|
||||
{
|
||||
var message = new CurrentSourcesStateMessage
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,12 +36,16 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
|
||||
AddAction("/getDirectory", (id, content) => GetDirectoryRoot());
|
||||
|
||||
AddAction("/setCurrentDirectoryToRoot", (id, content) => _directory.SetCurrentDirectoryToRoot());
|
||||
|
||||
AddAction("/directoryById", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
GetDirectory(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/getDirectoryPareentFolderContents", (id, content) => _directory.GetDirectoryParentFolderContents());
|
||||
|
||||
AddAction("/directorySearch", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<string>>();
|
||||
|
|
@ -52,6 +56,14 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
|
||||
_directory.DirectoryResultReturned += DirectoryResultReturned;
|
||||
_directory.PhonebookSyncState.InitialSyncCompleted += PhonebookSyncState_InitialSyncCompleted;
|
||||
|
||||
_directory.CurrentDirectoryResultIsNotDirectoryRoot.OutputChange += (s, e) =>
|
||||
{
|
||||
PostStatusMessage(new IHasDirectoryStateMessage
|
||||
{
|
||||
DirectorySelectedFolderIsNotRoot = _directory.CurrentDirectoryResultIsNotDirectoryRoot?.BoolValue
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private void DirectoryResultReturned(object sender, DirectoryEventArgs e)
|
||||
|
|
@ -125,16 +137,22 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
{
|
||||
PostStatusMessage(new IHasDirectoryStateMessage
|
||||
{
|
||||
DirectoryRoot = _directory.DirectoryRoot,
|
||||
CurrentDirectory = _directory.CurrentDirectoryResult,
|
||||
InitialPhonebookSyncComplete = _directory.PhonebookSyncState.InitialSyncComplete,
|
||||
HasDirectory = true,
|
||||
HasDirectorySearch = true,
|
||||
DirectorySelectedFolderName = _directory.CurrentDirectoryResult?.CurrentDirectoryResults?.Count > 0 ? _directory.CurrentDirectoryResult.CurrentDirectoryResults[0].Name : null,
|
||||
DirectorySelectedFolderIsNotRoot = _directory.CurrentDirectorResultIsNotDirectoryRoot?.BoolValue
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class IHasDirectoryStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("directoryRoot", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public CodecDirectory DirectoryRoot { get; set; }
|
||||
|
||||
[JsonProperty("currentDirectory", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public CodecDirectory CurrentDirectory { get; set; }
|
||||
|
||||
|
|
@ -153,5 +171,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
|||
[JsonProperty("directorySelectedFolderName", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string DirectorySelectedFolderName { get; set; }
|
||||
|
||||
[JsonProperty("directorySelectedFolderIsNotRoot", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? DirectorySelectedFolderIsNotRoot { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,11 @@ namespace PepperDash.Essentials
|
|||
public bool EnableApiServer { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Enable subscriptions for Messengers
|
||||
/// Enable subscriptions for Messengers.
|
||||
/// Defaults to true for v3.x+
|
||||
/// </summary>
|
||||
[JsonProperty("enableMessengerSubscriptions")]
|
||||
public bool EnableMessengerSubscriptions { get; set; }
|
||||
public bool EnableMessengerSubscriptions { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1501,8 +1501,14 @@ namespace PepperDash.Essentials
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a batch request for full status of multiple devices.
|
||||
/// Triggers all registered messengers for each device key in parallel,
|
||||
/// Handles a batch request for device status. Supports two content formats:
|
||||
/// <para>
|
||||
/// Granular format: <c>{ "devices": { "deviceKey": ["/fullStatus", "/layoutStatus"], ... } }</c>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Legacy format: <c>{ "deviceKeys": ["deviceKey1", "deviceKey2"] }</c> (equivalent to /fullStatus for each)
|
||||
/// </para>
|
||||
/// Triggers the specified action paths for each device in parallel,
|
||||
/// then sends an /system/initialSyncComplete message after all have been processed.
|
||||
/// </summary>
|
||||
private void HandleBatchDeviceFullStatus(string clientId, JToken content)
|
||||
|
|
@ -1513,11 +1519,23 @@ namespace PepperDash.Essentials
|
|||
return;
|
||||
}
|
||||
|
||||
// Build a dictionary of deviceKey -> list of action paths
|
||||
Dictionary<string, List<string>> deviceActionPaths;
|
||||
|
||||
var devicesToken = content.SelectToken("devices");
|
||||
if (devicesToken != null)
|
||||
{
|
||||
// Granular format: { "devices": { "key": ["/path1", "/path2"], ... } }
|
||||
deviceActionPaths = devicesToken.ToObject<Dictionary<string, List<string>>>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Legacy format: { "deviceKeys": ["key1", "key2"] } -> each gets /fullStatus
|
||||
var deviceKeys = content.SelectToken("deviceKeys")?.ToObject<List<string>>();
|
||||
|
||||
if (deviceKeys == null || deviceKeys.Count == 0)
|
||||
{
|
||||
this.LogWarning("BatchDeviceFullStatus: No device keys provided");
|
||||
this.LogWarning("BatchDeviceFullStatus: No device keys or devices provided");
|
||||
SendMessageObject(new MobileControlMessage
|
||||
{
|
||||
Type = "/system/initialSyncComplete",
|
||||
|
|
@ -1526,22 +1544,46 @@ namespace PepperDash.Essentials
|
|||
return;
|
||||
}
|
||||
|
||||
this.LogInformation("BatchDeviceFullStatus: Processing {count} device keys", deviceKeys.Count);
|
||||
deviceActionPaths = deviceKeys.ToDictionary(k => k, _ => new List<string> { "/fullStatus" });
|
||||
}
|
||||
|
||||
if (deviceActionPaths == null || deviceActionPaths.Count == 0)
|
||||
{
|
||||
this.LogWarning("BatchDeviceFullStatus: Empty devices dictionary");
|
||||
SendMessageObject(new MobileControlMessage
|
||||
{
|
||||
Type = "/system/initialSyncComplete",
|
||||
ClientId = clientId
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.LogInformation("BatchDeviceFullStatus: Processing {count} devices", deviceActionPaths.Count);
|
||||
|
||||
var tasks = new List<Task>();
|
||||
|
||||
foreach (var deviceKey in deviceKeys)
|
||||
foreach (var kvp in deviceActionPaths)
|
||||
{
|
||||
var fullStatusPath = $"/device/{deviceKey}/fullStatus";
|
||||
var deviceKey = kvp.Key;
|
||||
var actionPaths = kvp.Value;
|
||||
|
||||
if (actionPaths == null || actionPaths.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var actionPath in actionPaths)
|
||||
{
|
||||
var fullPath = $"/device/{deviceKey}{actionPath}";
|
||||
|
||||
var handlers = _actionDictionary
|
||||
.Where(kv => fullStatusPath.StartsWith(kv.Key + "/"))
|
||||
.Where(kv => fullPath.StartsWith(kv.Key + "/"))
|
||||
.SelectMany(kv => kv.Value)
|
||||
.ToList();
|
||||
|
||||
if (handlers.Count == 0)
|
||||
{
|
||||
this.LogDebug("BatchDeviceFullStatus: No handlers for {deviceKey}", deviceKey);
|
||||
this.LogDebug("BatchDeviceFullStatus: No handlers for {deviceKey} at path {actionPath}", deviceKey, actionPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1551,15 +1593,16 @@ namespace PepperDash.Essentials
|
|||
{
|
||||
try
|
||||
{
|
||||
handler.Action(fullStatusPath, clientId, JToken.FromObject(new { deviceKey }));
|
||||
handler.Action(fullPath, clientId, JToken.FromObject(new { deviceKey }));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.LogError("BatchDeviceFullStatus: Exception in handler for {deviceKey}: {message}", deviceKey, ex.Message);
|
||||
this.LogError("BatchDeviceFullStatus: Exception in handler for {deviceKey} at {actionPath}: {message}", deviceKey, actionPath, ex.Message);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// After all handlers have completed and enqueued their responses, send sync complete
|
||||
Task.Run(async () =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue