diff --git a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs index f4de34e4..b2565b3d 100644 --- a/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs +++ b/src/PepperDash.Essentials.Core/Devices/DeviceJsonApi.cs @@ -281,84 +281,92 @@ public class DeviceJsonApi /// public static object FindObjectOnPath(string deviceObjectPath) { - var path = deviceObjectPath.Split('.'); - - var dev = DeviceManager.GetDeviceForKey(path[0]); - if (dev == null) + try { - Debug.LogMessage(LogEventLevel.Information, "Device {0} not found", path[0]); - return null; - } + var path = deviceObjectPath.Split('.'); - // loop through any dotted properties - object obj = dev; - if (path.Length > 1) - { - for (int i = 1; i < path.Length; i++) + var dev = DeviceManager.GetDeviceForKey(path[0]); + if (dev == null) { - var objName = path[i]; - string indexStr = null; - var indexOpen = objName.IndexOf('['); - if (indexOpen != -1) - { - var indexClose = objName.IndexOf(']'); - if (indexClose == -1) - { - Debug.LogMessage(LogEventLevel.Information, dev, "ERROR Unmatched index brackets"); - return null; - } - // Get the index and strip quotes if any - indexStr = objName.Substring(indexOpen + 1, indexClose - indexOpen - 1).Replace("\"", ""); - objName = objName.Substring(0, indexOpen); - Debug.LogMessage(LogEventLevel.Information, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr); - } + Debug.LogMessage(LogEventLevel.Information, "Device {0} not found", path[0]); + return null; + } - Type oType = obj.GetType(); - var prop = oType.GetProperty(objName); - if (prop == null) + // loop through any dotted properties + object obj = dev; + if (path.Length > 1) + { + for (int i = 1; i < path.Length; i++) { - Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} not found on {1}", objName, path[i - 1]); - return null; - } - // if there's an index, try to get the property - if (indexStr != null) - { - if (!typeof(ICollection).IsAssignableFrom(prop.PropertyType)) + var objName = path[i]; + string indexStr = null; + var indexOpen = objName.IndexOf('['); + if (indexOpen != -1) { - Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} is not collection", objName); - return null; - } - var collection = prop.GetValue(obj, null) as ICollection; - // Get the indexed items "property" - var indexedPropInfo = prop.PropertyType.GetProperty("Item"); - // These are the parameters for the indexing. Only care about one - var indexParams = indexedPropInfo.GetIndexParameters(); - if (indexParams.Length > 0) - { - Debug.LogMessage(LogEventLevel.Information, " Indexed, param type: {0}", indexParams[0].ParameterType.Name); - var properParam = Convert.ChangeType(indexStr, indexParams[0].ParameterType, - System.Globalization.CultureInfo.InvariantCulture); - try + var indexClose = objName.IndexOf(']'); + if (indexClose == -1) { - obj = indexedPropInfo.GetValue(collection, new object[] { properParam }); - } - // if the index is bad, catch it here. - catch (TargetInvocationException e) - { - if (e.InnerException is ArgumentOutOfRangeException) - Debug.LogMessage(LogEventLevel.Information, " Index Out of range"); - else if (e.InnerException is KeyNotFoundException) - Debug.LogMessage(LogEventLevel.Information, " Key not found"); + Debug.LogMessage(LogEventLevel.Information, dev, "ERROR Unmatched index brackets"); return null; } + // Get the index and strip quotes if any + indexStr = objName.Substring(indexOpen + 1, indexClose - indexOpen - 1).Replace("\"", ""); + objName = objName.Substring(0, indexOpen); + Debug.LogMessage(LogEventLevel.Information, dev, " Checking for collection '{0}', index '{1}'", objName, indexStr); } + Type oType = obj.GetType(); + var prop = oType.GetProperty(objName); + if (prop == null) + { + Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} not found on {1}", objName, path[i - 1]); + return null; + } + // if there's an index, try to get the property + if (indexStr != null) + { + if (!typeof(ICollection).IsAssignableFrom(prop.PropertyType)) + { + Debug.LogMessage(LogEventLevel.Information, dev, "Property {0} is not collection", objName); + return null; + } + var collection = prop.GetValue(obj, null) as ICollection; + // Get the indexed items "property" + var indexedPropInfo = prop.PropertyType.GetProperty("Item"); + // These are the parameters for the indexing. Only care about one + var indexParams = indexedPropInfo.GetIndexParameters(); + if (indexParams.Length > 0) + { + Debug.LogMessage(LogEventLevel.Information, " Indexed, param type: {0}", indexParams[0].ParameterType.Name); + var properParam = Convert.ChangeType(indexStr, indexParams[0].ParameterType, + System.Globalization.CultureInfo.InvariantCulture); + try + { + obj = indexedPropInfo.GetValue(collection, new object[] { properParam }); + } + // if the index is bad, catch it here. + catch (TargetInvocationException e) + { + if (e.InnerException is ArgumentOutOfRangeException) + Debug.LogMessage(LogEventLevel.Information, " Index Out of range"); + else if (e.InnerException is KeyNotFoundException) + Debug.LogMessage(LogEventLevel.Information, " Key not found"); + return null; + } + } + + } + else + obj = prop.GetValue(obj, null); } - else - obj = prop.GetValue(obj, null); } + return obj; + } + catch (Exception e) + { + Debug.LogMessage(LogEventLevel.Error, e, "Error finding object on path {deviceObjectPath}", deviceObjectPath); + return null; } - return obj; } /// diff --git a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs index b32340af..b8913351 100644 --- a/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs +++ b/src/PepperDash.Essentials.Devices.Common/AudioCodec/MockAC/MockAC.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using PepperDash.Core; using PepperDash.Essentials.Core; @@ -8,16 +9,35 @@ using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.AudioCodec; -public class MockAC : AudioCodecBase +public class MockAC : AudioCodecBase, IAudioCodecPhonebook { + public event EventHandler ListChanged; + + public List PhonebookEntries { get; } + public MockAC(string key, string name, MockAcPropertiesConfig props) : base(key, name) { CodecInfo = new MockAudioCodecInfo(); CodecInfo.PhoneNumber = props.PhoneNumber; + + PhonebookEntries = new List + { + new() { Name = "Judge Chambers", Number = "5551001" }, + new() { Name = "Clerk Office", Number = "5551002" }, + new() { Name = "Court Reporter", Number = "5551003" }, + new() { Name = "Jury Room", Number = "5551004" }, + new() { Name = "Witness Room", Number = "5551005" }, + new() { Name = "Prosecution", Number = "5551006" }, + new() { Name = "Defense Counsel", Number = "5551007" }, + new() { Name = "Bailiff Station", Number = "5551008" }, + new() { Name = "Conference Room A", Number = "5551009" }, + new() { Name = "Conference Room B", Number = "5551010" }, + }; } + public override void Dial(string number) { if (!IsInCall) @@ -79,6 +99,29 @@ public class MockAC : AudioCodecBase Debug.LogMessage(LogEventLevel.Debug, this, "BEEP BOOP SendDTMF: {0}", s); } + public void SetPhonebookEntry(int index, string name, string number) + { + if (index < 0 || index >= PhonebookEntries.Count) + { + Debug.LogMessage(LogEventLevel.Debug, this, "SetPhonebookEntry: index {0} out of range", index); + return; + } + + PhonebookEntries[index] = new CodecPhonebookEntry { Name = name, Number = number }; + ListChanged?.Invoke(this, new PhonebookListChangedEventArgs(PhonebookEntries)); + } + + public void DialPhonebookEntry(int index) + { + if (index < 0 || index >= PhonebookEntries.Count) + { + Debug.LogMessage(LogEventLevel.Debug, this, "DialPhonebookEntry: index {0} out of range", index); + return; + } + + Dial(PhonebookEntries[index].Number); + } + /// /// /// diff --git a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IAudioCodecPhonebookMessenger.cs b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IAudioCodecPhonebookMessenger.cs index acf5fcff..7d336f75 100644 --- a/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IAudioCodecPhonebookMessenger.cs +++ b/src/PepperDash.Essentials.MobileControl.Messengers/Messengers/IAudioCodecPhonebookMessenger.cs @@ -28,6 +28,8 @@ namespace PepperDash.Essentials.AppServer.Messengers : base(key, messagePath, device) { _phonebook = device as IAudioCodecPhonebook ?? throw new ArgumentNullException(nameof(device)); + + _phonebook.ListChanged += (sender, args) => SendFullStatus(); } /// @@ -43,7 +45,12 @@ namespace PepperDash.Essentials.AppServer.Messengers { var entry = content.ToObject(); _phonebook.SetPhonebookEntry(entry.Index, entry.Name, entry.Number); - SendFullStatus(); + }); + + AddAction("/dialEntry", (id, content) => + { + var request = content.ToObject>(); + _phonebook.DialPhonebookEntry(request.Value); }); } diff --git a/src/PepperDash.Essentials.MobileControl/MessengerFactoryRegistry.cs b/src/PepperDash.Essentials.MobileControl/MessengerFactoryRegistry.cs index 1b81a5b0..7124de56 100644 --- a/src/PepperDash.Essentials.MobileControl/MessengerFactoryRegistry.cs +++ b/src/PepperDash.Essentials.MobileControl/MessengerFactoryRegistry.cs @@ -251,6 +251,16 @@ namespace PepperDash.Essentials (d, mp, ck) => new IDialerCallStatusMessenger( $"{d.Key}-audioCodec-{ck}", (IDialerCallStatus)d, mp) ), + new MessengerFactoryEntry( + typeof(IAudioCodecInfo), + (d, mp, ck) => new IAudioCodecInfoMessenger( + $"{d.Key}-audioCodecInfo-{ck}", mp, d) + ), + new MessengerFactoryEntry( + typeof(IAudioCodecPhonebook), + (d, mp, ck) => new IAudioCodecPhonebookMessenger( + $"{d.Key}-audioCodecPhonebook-{ck}", mp, d) + ), // ── Set-top box controls ────────────────────────────────────────────────── new MessengerFactoryEntry(