diff --git a/PepperDashEssentials/AppServer/CotijaSystemController.cs b/PepperDashEssentials/AppServer/CotijaSystemController.cs index 1f5fa0ff..1e74efe0 100644 --- a/PepperDashEssentials/AppServer/CotijaSystemController.cs +++ b/PepperDashEssentials/AppServer/CotijaSystemController.cs @@ -17,6 +17,7 @@ using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Room.Cotija; +using PepperDash.Essentials.AppServer.Messengers; namespace PepperDash.Essentials { @@ -39,6 +40,8 @@ namespace PepperDash.Essentials Dictionary PushedActions = new Dictionary(); + public ConfigMessenger ConfigMessenger { get; private set; } + CTimer ServerHeartbeatCheckTimer; long ServerHeartbeatInterval = 20000; @@ -49,7 +52,7 @@ namespace PepperDash.Essentials DateTime LastAckMessage; - string SystemUuid; + public string SystemUuid; List RoomBridges = new List(); @@ -97,11 +100,15 @@ namespace PepperDash.Essentials CrestronConsole.AddNewConsoleCommand(s => CleanUpWebsocketClient(), "mobiledisco", "Disconnects websocket", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => ParseStreamRx(s), "mobilesimulateaction", "Simulates a message from the server", ConsoleAccessLevelEnum.AccessOperator); + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); - - + // Config Messenger + var cmKey = Key + "-config"; + ConfigMessenger = new ConfigMessenger(cmKey, "/config"); + ConfigMessenger.RegisterWithAppServer(this); } /// @@ -319,10 +326,12 @@ namespace PepperDash.Essentials CrestronConsole.ConsoleCommandResponse(@"Mobile Control Information: Server address: {0} System Name: {1} - System UUID: {2} - System User code: {3} - Connected?: {4} - Seconds Since Last Ack: {5}", url, name, SystemUuid, + System URL: {2} + System UUID: {3} + System User code: {4} + Connected?: {5} + Seconds Since Last Ack: {6}" + , url, name, ConfigReader.ConfigObject.SystemUrl, SystemUuid, code, conn, secSinceLastAck.Seconds); } @@ -452,9 +461,9 @@ namespace PepperDash.Essentials Debug.Console(1, this, "Socket send result error: {0}", result); } } - else if (!WSClient.Connected) + else if (WSClient == null) { - Debug.Console(1, this, "Cannot send. Not connected {0}"); + Debug.Console(1, this, "Cannot send. Not connected."); } } diff --git a/PepperDashEssentials/AppServer/Messengers/ConfigMessenger.cs b/PepperDashEssentials/AppServer/Messengers/ConfigMessenger.cs new file mode 100644 index 00000000..1e3cfa12 --- /dev/null +++ b/PepperDashEssentials/AppServer/Messengers/ConfigMessenger.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Core; +using PepperDash.Essentials.Core.Config; + +namespace PepperDash.Essentials.AppServer.Messengers +{ + + /// + /// Handles interactions with the app server to update the config + /// + public class ConfigMessenger : MessengerBase + { + public ConfigMessenger(string key, string messagePath) + : base(key, messagePath) + { + ConfigUpdater.ConfigStatusChanged -= ConfigUpdater_ConfigStatusChanged; + ConfigUpdater.ConfigStatusChanged += new EventHandler(ConfigUpdater_ConfigStatusChanged); + } + + void ConfigUpdater_ConfigStatusChanged(object sender, ConfigStatusEventArgs e) + { + PostUpdateStatus(e.UpdateStatus.ToString()); + } + + protected override void CustomRegisterWithAppServer(CotijaSystemController appServerController) + { + appServerController.AddAction(MessagePath + "/updateConfig", new Action(s => GetConfigFile(s))); + } + + /// + /// Generates or passes the URL to make the request to GET the config from a server + /// + /// + void GetConfigFile(string url) + { + try + { + // Attempt to parse the URL + var parser = new Crestron.SimplSharp.Net.Http.UrlParser(url); + + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully parsed URL from AppServer message: {0}", parser.Url); + } + catch (Exception e) + { + // If unable to parse the URL, generate it from config data + Debug.Console(2, "Error parsing URL: {0}", e); + + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to parse URL from AppServer message. Generating URL from config data"); + url = string.Format("http://{0}/api/system/{1}/config", AppServerController.Config.ServerUrl, AppServerController.SystemUuid); + } + + ConfigUpdater.GetConfigFromServer(url); + } + + /// + /// Posts a message with the current status of the config update + /// + /// + void PostUpdateStatus(string status) + { + PostStatusMessage(new + { + updateStatus = status + }); + } + + } + + +} \ No newline at end of file diff --git a/PepperDashEssentials/AppServer/Messengers/SystemMonitorMessenger.cs b/PepperDashEssentials/AppServer/Messengers/SystemMonitorMessenger.cs index 7b56ab29..12107ff5 100644 --- a/PepperDashEssentials/AppServer/Messengers/SystemMonitorMessenger.cs +++ b/PepperDashEssentials/AppServer/Messengers/SystemMonitorMessenger.cs @@ -40,8 +40,11 @@ namespace PepperDash.Essentials.AppServer.Messengers /// void ProgramInfoChanged(object sender, ProgramInfoEventArgs e) { - Debug.Console(1, "Posting Status Message: {0}", e.ProgramInfo.ToString()); - PostStatusMessage(e.ProgramInfo); + if (e.ProgramInfo != null) + { + //Debug.Console(1, "Posting Status Message: {0}", e.ProgramInfo.ToString()); + PostStatusMessage(e.ProgramInfo); + } } /// diff --git a/PepperDashEssentials/AppServer/Messengers/VideoCodecBaseMessenger.cs b/PepperDashEssentials/AppServer/Messengers/VideoCodecBaseMessenger.cs index bd44e139..b8ca2dac 100644 --- a/PepperDashEssentials/AppServer/Messengers/VideoCodecBaseMessenger.cs +++ b/PepperDashEssentials/AppServer/Messengers/VideoCodecBaseMessenger.cs @@ -40,6 +40,7 @@ namespace PepperDash.Essentials.AppServer.Messengers if (dirCodec != null) { dirCodec.DirectoryResultReturned += new EventHandler(dirCodec_DirectoryResultReturned); + } var recCodec = codec as IHasCallHistory; @@ -74,12 +75,73 @@ namespace PepperDash.Essentials.AppServer.Messengers /// void dirCodec_DirectoryResultReturned(object sender, DirectoryEventArgs e) { - PostStatusMessage(new - { - currentDirectory = e.Directory - }); + SendDirectory((Codec as IHasDirectory).CurrentDirectoryResult, e.DirectoryIsOnRoot); } + /// + /// Posts the current directory + /// + void SendDirectory(CodecDirectory directory, bool isRoot) + { + var dirCodec = Codec as IHasDirectory; + + if (dirCodec != null) + { + var prefixedDirectoryResults = PrefixDirectoryFolderItems(directory); + + var directoryMessage = new + { + currentDirectory = new + { + directoryResults = prefixedDirectoryResults, + isRootDirectory = isRoot + } + }; + PostStatusMessage(directoryMessage); + } + } + + /// + /// Iterates a directory object and prefixes any folder items with "[+] " + /// + /// + /// + List PrefixDirectoryFolderItems (CodecDirectory directory) + { + var tempDirectoryList = new List(); + + if (directory.CurrentDirectoryResults.Count > 0) + { + foreach (var item in directory.CurrentDirectoryResults) + { + if (item is DirectoryFolder) + { + var newFolder = new DirectoryFolder(); + + newFolder = (DirectoryFolder)item.Clone(); + + string prefixName = "[+] " + newFolder.Name; + + newFolder.Name = prefixName; + + tempDirectoryList.Add(newFolder); + } + else + { + tempDirectoryList.Add(item); + } + } + } + //else + //{ + // DirectoryItem noResults = new DirectoryItem() { Name = "No Results Found" }; + + // tempDirectoryList.Add(noResults); + //} + + return tempDirectoryList; + } + /// /// /// @@ -122,10 +184,24 @@ namespace PepperDash.Essentials.AppServer.Messengers if (call != null) Codec.AcceptCall(call); })); - appServerController.AddAction(MessagePath + "/getDirectory", new Action(GetDirectoryRoot)); - appServerController.AddAction(MessagePath + "/directoryById", new Action(s => GetDirectory(s))); - appServerController.AddAction(MessagePath + "/directorySearch", new Action(s => DirectorySearch(s))); - appServerController.AddAction(MessagePath + "/getCallHistory", new Action(GetCallHistory)); + + // Directory actions + var dirCodec = Codec as IHasDirectory; + if (dirCodec != null) + { + appServerController.AddAction(MessagePath + "/getDirectory", new Action(GetDirectoryRoot)); + appServerController.AddAction(MessagePath + "/directoryById", new Action(s => GetDirectory(s))); + appServerController.AddAction(MessagePath + "/directorySearch", new Action(s => DirectorySearch(s))); + appServerController.AddAction(MessagePath + "/directoryBack", new Action(GetPreviousDirectory)); + } + + // History actions + var recCodec = Codec as IHasCallHistory; + if (recCodec != null) + { + appServerController.AddAction(MessagePath + "/getCallHistory", new Action(GetCallHistory)); + } + appServerController.AddAction(MessagePath + "/privacyModeOn", new Action(Codec.PrivacyModeOn)); appServerController.AddAction(MessagePath + "/privacyModeOff", new Action(Codec.PrivacyModeOff)); appServerController.AddAction(MessagePath + "/privacyModeToggle", new Action(Codec.PrivacyModeToggle)); @@ -215,12 +291,28 @@ namespace PepperDash.Essentials.AppServer.Messengers return; } - PostStatusMessage(new - { - currentDirectory = dirCodec.DirectoryRoot - }); + dirCodec.SetCurrentDirectoryToRoot(); + + //PostStatusMessage(new + //{ + // currentDirectory = dirCodec.DirectoryRoot + //}); } + /// + /// Requests the parent folder contents + /// + void GetPreviousDirectory() + { + var dirCodec = Codec as IHasDirectory; + if (dirCodec == null) + { + return; + } + + dirCodec.GetDirectoryParentFolderContents(); + } + /// /// Handler for codec changes /// @@ -271,6 +363,7 @@ namespace PepperDash.Essentials.AppServer.Messengers }, showSelfViewByDefault = Codec.ShowSelfViewByDefault, hasDirectory = Codec is IHasDirectory, + hasDirectorySearch = true, hasRecents = Codec is IHasCallHistory, hasCameras = Codec is IHasCameraControl }); diff --git a/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs b/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs index 525983fe..4fd75a36 100644 --- a/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs +++ b/PepperDashEssentials/AppServer/RoomBridges/CotijaEssentialsHuddleSpaceRoomBridge.cs @@ -25,6 +25,7 @@ namespace PepperDash.Essentials public AudioCodecBaseMessenger ACMessenger { get; private set; } + /// /// /// diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index ebfd5f4a..8124beb7 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -75,7 +75,7 @@ namespace PepperDash.Essentials } /// - /// Determines if the program is running on a processor (appliance) or server (XiO Edge). + /// Determines if the program is running on a processor (appliance) or server (VC-4). /// /// Sets Global.FilePathPrefix based on platform /// @@ -179,7 +179,7 @@ namespace PepperDash.Essentials } - // Notify the + // Notify the OS that the program intitialization has completed SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; } diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index 10fad395..a4072766 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -108,6 +108,7 @@ + diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index 4ceb481d..7b7718eb 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -71,7 +71,7 @@ namespace PepperDash.Essentials.Room.Config var microphonePrivacy = props.MicrophonePrivacy; if (microphonePrivacy == null) { - Debug.Console(0, "ERROR: Cannot create microphone privacy with null properties"); + Debug.Console(0, "Cannot create microphone privacy with null properties"); return null; } // Get the MicrophonePrivacy device from the device manager diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 62b11e49..d83c8e9a 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -266,6 +266,16 @@ namespace PepperDash.Essentials { IsCoolingDownFeedback.FireUpdate(); }; + + // Get Microphone Privacy object, if any + this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + + Debug.Console(2, this, "Microphone Privacy Config evaluated."); + + // Get emergency object, if any + this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + + Debug.Console(2, this, "Emergency Config evaluated."); } @@ -279,7 +289,7 @@ namespace PepperDash.Essentials inAudioCall = AudioCodec.IsInCall; if(VideoCodec != null) - inVideoCall = AudioCodec.IsInCall; + inVideoCall = VideoCodec.IsInCall; if (inAudioCall || inVideoCall) return true; @@ -327,12 +337,6 @@ namespace PepperDash.Essentials this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); - // Get Microphone Privacy object, if any - this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); - - // Get emergency object, if any - this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); - return base.CustomActivate(); } diff --git a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs index 4b1f2188..be51a4aa 100644 --- a/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs +++ b/PepperDashEssentials/UIDrivers/EssentialsHuddleVTC/EssentialsHuddleVtc1PanelAvFunctionsDriver.cs @@ -927,7 +927,10 @@ namespace PepperDash.Essentials _CurrentRoom.CurrentSingleSourceChange += CurrentRoom_SourceInfoChange; RefreshSourceInfo(); - (_CurrentRoom.VideoCodec as IHasScheduleAwareness).CodecSchedule.MeetingsListHasChanged += CodecSchedule_MeetingsListHasChanged; + if (_CurrentRoom.VideoCodec is IHasScheduleAwareness) + { + (_CurrentRoom.VideoCodec as IHasScheduleAwareness).CodecSchedule.MeetingsListHasChanged += CodecSchedule_MeetingsListHasChanged; + } CallSharingInfoVisibleFeedback = new BoolFeedback(() => _CurrentRoom.VideoCodec.SharingContentIsOnFeedback.BoolValue); _CurrentRoom.VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange; diff --git a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs index 13bf6a85..704a42d3 100644 --- a/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs +++ b/PepperDashEssentials/UIDrivers/VC/EssentialsVideoCodecUiDriver.cs @@ -58,16 +58,7 @@ namespace PepperDash.Essentials.UIDrivers.VC SmartObjectDynamicList RecentCallsList; SmartObjectDynamicList DirectoryList; - - CodecDirectory CurrentDirectoryResult; - - /// - /// Tracks the directory browse history when browsing beyond the root directory - /// - List DirectoryBrowseHistory; - bool NextDirectoryResultIsFolderContents; - BoolFeedback DirectoryBackButtonVisibleFeedback; // These are likely temp until we get a keyboard built @@ -111,7 +102,6 @@ namespace PepperDash.Essentials.UIDrivers.VC SetupCallStagingPopover(); SetupDialKeypad(); ActiveCallsSRL = new SubpageReferenceList(triList, UISmartObjectJoin.CodecActiveCallsHeaderList, 5,5,5); - SetupDirectoryList(); SetupRecentCallsList(); SetupFavorites(); SetupLayoutControls(); @@ -169,12 +159,14 @@ namespace PepperDash.Essentials.UIDrivers.VC }); SearchStringFeedback.LinkInputSig(triList.StringInput[UIStringJoin.CodecDirectorySearchEntryText]); + SetupDirectoryList(); + SearchStringBackspaceVisibleFeedback = new BoolFeedback(() => SearchStringBuilder.Length > 0); SearchStringBackspaceVisibleFeedback.LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackspaceVisible]); triList.SetSigFalseAction(UIBoolJoin.VCDirectoryBackPress, GetDirectoryParentFolderContents); - DirectoryBackButtonVisibleFeedback = new BoolFeedback(() => CurrentDirectoryResult != (codec as IHasDirectory).DirectoryRoot); + DirectoryBackButtonVisibleFeedback = (codec as IHasDirectory).CurrentDirectoryResultIsNotDirectoryRoot; DirectoryBackButtonVisibleFeedback .LinkInputSig(triList.BooleanInput[UIBoolJoin.VCDirectoryBackVisible]); @@ -532,8 +524,6 @@ namespace PepperDash.Essentials.UIDrivers.VC /// void SetupDirectoryList() { - DirectoryBrowseHistory = new List(); - var codec = Codec as IHasDirectory; if (codec != null) { @@ -548,28 +538,20 @@ namespace PepperDash.Essentials.UIDrivers.VC codec.PhonebookSyncState.InitialSyncCompleted += new EventHandler(PhonebookSyncState_InitialSyncCompleted); } - - // If there is something here now, show it otherwise wait for the event - if (CurrentDirectoryResult != null && codec.DirectoryRoot.DirectoryResults.Count > 0) - { - RefreshDirectory(); - } + RefreshDirectory(); + } } /// - /// Sets the current directory resutls to the DirectorRoot and updates Back Button visibiltiy + /// Sets the current directory results to the DirectoryRoot and updates Back Button visibiltiy /// void SetCurrentDirectoryToRoot() { - DirectoryBrowseHistory.Clear(); - - CurrentDirectoryResult = (Codec as IHasDirectory).DirectoryRoot; + (Codec as IHasDirectory).SetCurrentDirectoryToRoot(); SearchKeypadClear(); - DirectoryBackButtonVisibleFeedback.FireUpdate(); - RefreshDirectory(); } @@ -584,10 +566,8 @@ namespace PepperDash.Essentials.UIDrivers.VC SetCurrentDirectoryToRoot(); - if (CurrentDirectoryResult != null && codec.DirectoryRoot.DirectoryResults.Count > 0) - { - RefreshDirectory(); - } + RefreshDirectory(); + } /// @@ -597,13 +577,7 @@ namespace PepperDash.Essentials.UIDrivers.VC /// void dir_DirectoryResultReturned(object sender, DirectoryEventArgs e) { - if (NextDirectoryResultIsFolderContents) - { - NextDirectoryResultIsFolderContents = false; - DirectoryBrowseHistory.Add(e.Directory); - } - CurrentDirectoryResult = e.Directory; - DirectoryBackButtonVisibleFeedback.FireUpdate(); + RefreshDirectory(); } @@ -615,7 +589,6 @@ namespace PepperDash.Essentials.UIDrivers.VC { (Codec as IHasDirectory).GetDirectoryFolderContents(folder.FolderId); - NextDirectoryResultIsFolderContents = true; } /// @@ -625,18 +598,13 @@ namespace PepperDash.Essentials.UIDrivers.VC { var codec = Codec as IHasDirectory; - if (DirectoryBrowseHistory.Count > 0) + if (codec != null) { - var lastItemIndex = DirectoryBrowseHistory.Count - 1; - CurrentDirectoryResult = DirectoryBrowseHistory[lastItemIndex]; - DirectoryBrowseHistory.Remove(DirectoryBrowseHistory[lastItemIndex]); + codec.GetDirectoryParentFolderContents(); - RefreshDirectory(); - } - else - { - SetCurrentDirectoryToRoot(); + //RefreshDirectory(); } + } /// @@ -645,10 +613,10 @@ namespace PepperDash.Essentials.UIDrivers.VC /// void RefreshDirectory() { - if (CurrentDirectoryResult.DirectoryResults.Count > 0) + if ((Codec as IHasDirectory).CurrentDirectoryResult.CurrentDirectoryResults.Count > 0) { ushort i = 0; - foreach (var r in CurrentDirectoryResult.DirectoryResults) + foreach (var r in (Codec as IHasDirectory).CurrentDirectoryResult.CurrentDirectoryResults) { if (i == DirectoryList.MaxCount) { @@ -725,13 +693,13 @@ namespace PepperDash.Essentials.UIDrivers.VC Parent.MeetingOrContactMethodModalSrl.StringInputSig(i, 4).StringValue = ""; Parent.MeetingOrContactMethodModalSrl.StringInputSig(i, 5).StringValue = "Connect"; Parent.MeetingOrContactMethodModalSrl.BoolInputSig(i, 2).BoolValue = true; - var cc = c; // lambda scope + var cc = c; // to maintian lambda scope Parent.MeetingOrContactMethodModalSrl.GetBoolFeedbackSig(i, 1).SetSigFalseAction(() => { Parent.PopupInterlock.Hide(); var codec = Codec as VideoCodecBase; if (codec != null) - codec.Dial(c.Number); + codec.Dial(cc.Number); }); } Parent.MeetingOrContactMethodModalSrl.Count = i; @@ -1102,7 +1070,7 @@ namespace PepperDash.Essentials.UIDrivers.VC SearchStringFeedback.FireUpdate(); SearchStringKeypadCheckEnables(); - if(CurrentDirectoryResult != (Codec as IHasDirectory).DirectoryRoot) + if ((Codec as IHasDirectory).CurrentDirectoryResultIsNotDirectoryRoot.BoolValue) SetCurrentDirectoryToRoot(); }