From 47fb805766798b3f45a597c4c681b558b64ba0ca Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Tue, 28 May 2019 19:25:18 -0700 Subject: [PATCH 1/8] Added IBridge to make it easier to deal with calling the linkToApi method. Added as an else if in EiscApI to ensure backwards compatibility. --- PepperDashEssentials/Bridges/BridgeBase.cs | 5 +++++ PepperDashEssentials/Bridges/IBridge.cs | 14 ++++++++++++++ PepperDashEssentials/PepperDashEssentials.csproj | 1 + essentials-framework | 2 +- 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 PepperDashEssentials/Bridges/IBridge.cs diff --git a/PepperDashEssentials/Bridges/BridgeBase.cs b/PepperDashEssentials/Bridges/BridgeBase.cs index e6ecf1c0..9cfcc08a 100644 --- a/PepperDashEssentials/Bridges/BridgeBase.cs +++ b/PepperDashEssentials/Bridges/BridgeBase.cs @@ -123,6 +123,11 @@ namespace PepperDash.Essentials.Bridges { (device as IDigitalInput).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey); continue; + } + else if (device is IBridge) + { + (device as IBridge).LinkToApi(Eisc, d.JoinStart, d.JoinMapKey); + continue; } //else if (device is LightingBase) //{ diff --git a/PepperDashEssentials/Bridges/IBridge.cs b/PepperDashEssentials/Bridges/IBridge.cs new file mode 100644 index 00000000..d86a1d1d --- /dev/null +++ b/PepperDashEssentials/Bridges/IBridge.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.DeviceSupport; + +namespace PepperDash.Essentials.Bridges +{ + public interface IBridge + { + void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey); + } +} \ No newline at end of file diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index b454f4b4..4a5ad292 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -127,6 +127,7 @@ + diff --git a/essentials-framework b/essentials-framework index 75c2bf81..a801b08d 160000 --- a/essentials-framework +++ b/essentials-framework @@ -1 +1 @@ -Subproject commit 75c2bf819a3b7e6c37a3d6b0c7b11cc273043b12 +Subproject commit a801b08d38a9ba6e8a973c58d7b7715424b25839 From f82816729b9588c1b734a747c2f795ae680817a8 Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Thu, 13 Jun 2019 19:44:14 -0700 Subject: [PATCH 2/8] DID Not commit separately but also made bridge eisc uo actions use a threadpool thread. Fix the load plugin to load dlls before calling the load plugin method. Also added capability to place a cplz and unzip and load. The crestron dlls will throw exceptions so catching them and printing to console if debug is enabled to hide the messages from log and user as they can look like a problem when they are not. IMPORTANT we may need to add some logic to deal with multiple cplz's unzipping as the files will auto overwrite. See JIRA ticket ECS-1113 --- PepperDashEssentials/Bridges/BridgeFactory.cs | 14 +- PepperDashEssentials/ControlSystem.cs | 611 +++++++++--------- 2 files changed, 329 insertions(+), 296 deletions(-) diff --git a/PepperDashEssentials/Bridges/BridgeFactory.cs b/PepperDashEssentials/Bridges/BridgeFactory.cs index 8b9ba75c..923ee59f 100644 --- a/PepperDashEssentials/Bridges/BridgeFactory.cs +++ b/PepperDashEssentials/Bridges/BridgeFactory.cs @@ -128,13 +128,13 @@ public class BridgeApiEisc { if (Debug.Level >= 1) Debug.Console(1, "BridgeApiEisc change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); - var uo = args.Sig.UserObject; - if (uo is Action) - (uo as Action)(args.Sig.BoolValue); - else if (uo is Action) - (uo as Action)(args.Sig.UShortValue); - else if (uo is Action) - (uo as Action)(args.Sig.StringValue); + var uo = args.Sig.UserObject; + if (uo is Action) + CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.BoolValue), args); + else if (uo is Action) + CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.UShortValue), args); + else if (uo is Action) + CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.StringValue), args); } } } diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 8124beb7..44ebc31f 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -19,35 +19,35 @@ using PepperDash.Essentials.Room.Cotija; namespace PepperDash.Essentials { - public class ControlSystem : CrestronControlSystem - { + public class ControlSystem : CrestronControlSystem + { HttpLogoServer LogoServer; - List FactoryObjects = new List(); + List FactoryObjects = new List(); - public ControlSystem() - : base() - { - Thread.MaxNumberOfUserThreads = 400; - Global.ControlSystem = this; - DeviceManager.Initialize(this); - } + public ControlSystem() + : base() + { + Thread.MaxNumberOfUserThreads = 400; + Global.ControlSystem = this; + DeviceManager.Initialize(this); + } - /// - /// Git 'er goin' - /// - public override void InitializeSystem() - { + /// + /// Git 'er goin' + /// + public override void InitializeSystem() + { DeterminePlatform(); //CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file", // ConsoleAccessLevelEnum.AccessOperator); - // CrestronConsole.AddNewConsoleCommand(S => { ConfigWriter.WriteConfigFile(null); }, "writeconfig", "writes the current config to a file", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "CONSOLE MESSAGE: {0}", s); - }, "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); + // CrestronConsole.AddNewConsoleCommand(S => { ConfigWriter.WriteConfigFile(null); }, "writeconfig", "writes the current config to a file", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "CONSOLE MESSAGE: {0}", s); + }, "appdebugmessage", "Writes message to log", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => { @@ -56,23 +56,23 @@ namespace PepperDash.Essentials }, "listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - CrestronConsole.ConsoleCommandResponse - ("Current running configuration. This is the merged system and template configuration"); - CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject - (ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented)); - }, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + { + CrestronConsole.ConsoleCommandResponse + ("Current running configuration. This is the merged system and template configuration"); + CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject + (ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented)); + }, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator); - CrestronConsole.AddNewConsoleCommand(s => - { - CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r" + - "System URL: {0}\r" + - "Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl); - }, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + { + CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r" + + "System URL: {0}\r" + + "Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl); + }, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator); GoWithLoad(); - } + } /// /// Determines if the program is running on a processor (appliance) or server (VC-4). @@ -100,11 +100,11 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on 3-series Appliance", versionString); // Check if User/ProgramX exists - if(Directory.Exists(directoryPrefix + dirSeparator + "User" + if (Directory.Exists(directoryPrefix + dirSeparator + "User" + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber))) { Debug.Console(0, @"User/program{0} directory found", InitialParametersClass.ApplicationNumber); - filePathPrefix = directoryPrefix + dirSeparator + "User" + filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator; } // Check if Nvram/Programx exists @@ -134,165 +134,198 @@ namespace PepperDash.Essentials Global.SetFilePathPrefix(filePathPrefix); } - /// - /// Do it, yo - /// - public void GoWithLoad() - { - try - { + /// + /// Do it, yo + /// + public void GoWithLoad() + { + try + { Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials load from configuration"); - var filesReady = SetupFilesystem(); - if (filesReady) - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Checking for plugins"); - LoadPlugins(); + var filesReady = SetupFilesystem(); + if (filesReady) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Checking for plugins"); + LoadPlugins(); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Folder structure verified. Loading config..."); - if (!ConfigReader.LoadConfig2()) - return; + if (!ConfigReader.LoadConfig2()) + return; - Load(); + Load(); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Essentials load complete\r" + - "-------------------------------------------------------------"); - } - else - { - Debug.Console(0, - "------------------------------------------------\r" + - "------------------------------------------------\r" + - "------------------------------------------------\r" + - "Essentials file structure setup completed.\r" + - "Please load config, sgd and ir files and\r" + - "restart program.\r" + - "------------------------------------------------\r" + - "------------------------------------------------\r" + - "------------------------------------------------"); - } + "-------------------------------------------------------------"); + } + else + { + Debug.Console(0, + "------------------------------------------------\r" + + "------------------------------------------------\r" + + "------------------------------------------------\r" + + "Essentials file structure setup completed.\r" + + "Please load config, sgd and ir files and\r" + + "restart program.\r" + + "------------------------------------------------\r" + + "------------------------------------------------\r" + + "------------------------------------------------"); + } } - catch (Exception e) - { - Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e); + catch (Exception e) + { + Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e); - } + } // Notify the OS that the program intitialization has completed SystemMonitor.ProgramInitialization.ProgramInitializationComplete = true; - } + } - /// - /// Initial simple implementation. Reads user/programN/plugins folder and - /// use - /// - void LoadPlugins() - { - var dir = Global.FilePathPrefix + "plugins"; - if (Directory.Exists(dir)) - { - // TODO Clear out or create localPlugins folder (maybe in program slot folder) + /// + /// Initial simple implementation. Reads user/programN/plugins folder and + /// use + /// + void LoadPlugins() + { + var dir = Global.FilePathPrefix + "plugins"; + if (Directory.Exists(dir)) + { + // TODO Clear out or create localPlugins folder (maybe in program slot folder) - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Plugins directory found, checking for factory plugins"); - var di = new DirectoryInfo(dir); - var files = di.GetFiles("*.dll"); - foreach (FileInfo fi in files) - { - // TODO COPY plugin to loadedPlugins folder + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Plugins directory found, checking for factory plugins"); + var di = new DirectoryInfo(dir); + var zFiles = di.GetFiles("*.cplz"); + foreach (var fi in zFiles) + { + Debug.Console(0, "Found cplz: {0}. Unzipping into plugins directory", fi.Name); + var result = CrestronZIP.Unzip(fi.FullName, di.FullName); + Debug.Console(0, "UnZip Result: {0}", result.ToString()); + fi.Delete(); + } + var files = di.GetFiles("*.dll"); + Dictionary assyList = new Dictionary(); + foreach (FileInfo fi in files) + { + // TODO COPY plugin to loadedPlugins folder + // TODO LOAD that loadedPlugins dll file + try + { + var assy = Assembly.LoadFrom(fi.FullName); + var ver = assy.GetName().Version; + var verStr = string.Format("{0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision); + assyList.Add(fi.FullName, assy); + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loaded plugin file '{0}', version {1}", fi.FullName, verStr); + } + catch + { + Debug.Console(2, "Assembly {0} is not a custom assembly", fi.FullName); + continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here + } + } + foreach (var assy in assyList) + { + // iteratate this assembly's classes, looking for "LoadPlugin()" methods + try + { + var types = assy.Value.GetTypes(); + foreach (var type in types) + { + try + { + var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static); + var loadPlugin = methods.FirstOrDefault(m => m.Name.Equals("LoadPlugin")); + if (loadPlugin != null) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Adding type {0}", assy.Key, type.FullName); + loadPlugin.Invoke(null, null); + } + } + catch + { + Debug.Console(2, "Load Plugin not found. {0} is not a plugin assembly", assy.Value.FullName); + continue; + } - // TODO LOAD that loadedPlugins dll file + } + } + catch + { + Debug.Console(2, "Assembly {0} is not a custom assembly. Types cannot be loaded.", assy.Value.FullName); + continue; + } + } + // plugin dll will be loaded. Any classes in plugin should have a static constructor + // that registers that class with the Core.DeviceFactory + } + } - var assy = Assembly.LoadFrom(fi.FullName); - var ver = assy.GetName().Version; - var verStr = string.Format("{0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision); - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loaded plugin file '{0}', version {1}", fi.FullName, verStr); + /// + /// Verifies filesystem is set up. IR, SGD, and programX folders + /// + bool SetupFilesystem() + { + Debug.Console(0, "Verifying and/or creating folder structure"); + var configDir = Global.FilePathPrefix; + var configExists = Directory.Exists(configDir); + if (!configExists) + Directory.Create(configDir); - // iteratate this assembly's classes, looking for "LoadPlugin()" methods - var types = assy.GetTypes(); - foreach (var type in types) - { - var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static); - var loadPlugin = methods.FirstOrDefault(m => m.Name.Equals("LoadPlugin")); - if (loadPlugin != null) - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Adding type {0}", fi.FullName, type.FullName); - loadPlugin.Invoke(null, null); - } - - } - - // plugin dll will be loaded. Any classes in plugin should have a static constructor - // that registers that class with the Core.DeviceFactory - } - } - } - - /// - /// Verifies filesystem is set up. IR, SGD, and programX folders - /// - bool SetupFilesystem() - { - Debug.Console(0, "Verifying and/or creating folder structure"); - var configDir = Global.FilePathPrefix; - var configExists = Directory.Exists(configDir); - if (!configExists) - Directory.Create(configDir); - - var irDir = Global.FilePathPrefix + "ir"; - if (!Directory.Exists(irDir)) - Directory.Create(irDir); + var irDir = Global.FilePathPrefix + "ir"; + if (!Directory.Exists(irDir)) + Directory.Create(irDir); var sgdDir = Global.FilePathPrefix + "sgd"; - if (!Directory.Exists(sgdDir)) - Directory.Create(sgdDir); + if (!Directory.Exists(sgdDir)) + Directory.Create(sgdDir); - return configExists; - } + return configExists; + } - ///// - ///// - ///// - ///// - //public void EnablePortalSync(string s) - //{ - // if (s.ToLower() == "enable") - // { - // CrestronConsole.ConsoleCommandResponse("Portal Sync features enabled"); - // } - //} + ///// + ///// + ///// + ///// + //public void EnablePortalSync(string s) + //{ + // if (s.ToLower() == "enable") + // { + // CrestronConsole.ConsoleCommandResponse("Portal Sync features enabled"); + // } + //} - /// - /// - /// - public void TearDown() - { - Debug.Console(0, "Tearing down existing system"); - DeviceManager.DeactivateAll(); + /// + /// + /// + public void TearDown() + { + Debug.Console(0, "Tearing down existing system"); + DeviceManager.DeactivateAll(); - TieLineCollection.Default.Clear(); + TieLineCollection.Default.Clear(); - foreach (var key in DeviceManager.GetDevices()) - DeviceManager.RemoveDevice(key); + foreach (var key in DeviceManager.GetDevices()) + DeviceManager.RemoveDevice(key); - Debug.Console(0, "Tear down COMPLETE"); - } + Debug.Console(0, "Tear down COMPLETE"); + } - /// - /// - /// - void Load() - { - LoadDevices(); - LoadTieLines(); - LoadRooms(); - LoadLogoServer(); + /// + /// + /// + void Load() + { + LoadDevices(); + LoadTieLines(); + LoadRooms(); + LoadLogoServer(); - DeviceManager.ActivateAll(); + DeviceManager.ActivateAll(); LinkSystemMonitorToAppServer(); - } + } void LinkSystemMonitorToAppServer() { @@ -309,28 +342,28 @@ namespace PepperDash.Essentials messenger.RegisterWithAppServer(appServer); - DeviceManager.AddDevice(messenger); + DeviceManager.AddDevice(messenger); } } - /// - /// Reads all devices from config and adds them to DeviceManager - /// - public void LoadDevices() - { - // Build the processor wrapper class - DeviceManager.AddDevice(new PepperDash.Essentials.Core.Devices.CrestronProcessor("processor")); + /// + /// Reads all devices from config and adds them to DeviceManager + /// + public void LoadDevices() + { + // Build the processor wrapper class + DeviceManager.AddDevice(new PepperDash.Essentials.Core.Devices.CrestronProcessor("processor")); // Add global System Monitor device DeviceManager.AddDevice(new PepperDash.Essentials.Core.Monitoring.SystemMonitorController("systemMonitor")); - foreach (var devConf in ConfigReader.ConfigObject.Devices) - { + foreach (var devConf in ConfigReader.ConfigObject.Devices) + { - try - { + try + { Debug.Console(0, Debug.ErrorLogLevel.Notice, "Creating device '{0}', type '{1}'", devConf.Key, devConf.Type); - // Skip this to prevent unnecessary warnings + // Skip this to prevent unnecessary warnings if (devConf.Key == "processor") { if (devConf.Type.ToLower() != Global.ControlSystem.ControllerPrompt.ToLower()) @@ -341,94 +374,94 @@ namespace PepperDash.Essentials continue; } - // Try local factories first - var newDev = DeviceFactory.GetDevice(devConf); + // Try local factories first + var newDev = DeviceFactory.GetDevice(devConf); if (newDev == null) newDev = BridgeFactory.GetDevice(devConf); - // Then associated library factories + // Then associated library factories if (newDev == null) newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf); - if (newDev == null) - newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf); - if (newDev == null) - newDev = PepperDash.Essentials.DM.DeviceFactory.GetDevice(devConf); - if (newDev == null) - newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf); - if (newDev == null) - newDev = PepperDash.Essentials.BridgeFactory.GetDevice(devConf); + if (newDev == null) + newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf); + if (newDev == null) + newDev = PepperDash.Essentials.DM.DeviceFactory.GetDevice(devConf); + if (newDev == null) + newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf); + if (newDev == null) + newDev = PepperDash.Essentials.BridgeFactory.GetDevice(devConf); - //if (newDev == null) // might want to consider the ability to override an essentials "type" - //{ - // // iterate plugin factories - // foreach (var f in FactoryObjects) - // { - // var cresFactory = f as IGetCrestronDevice; - // if (cresFactory != null) - // { - // newDev = cresFactory.GetDevice(devConf, this); - // } - // } - //} + //if (newDev == null) // might want to consider the ability to override an essentials "type" + //{ + // // iterate plugin factories + // foreach (var f in FactoryObjects) + // { + // var cresFactory = f as IGetCrestronDevice; + // if (cresFactory != null) + // { + // newDev = cresFactory.GetDevice(devConf, this); + // } + // } + //} - if (newDev != null) - DeviceManager.AddDevice(newDev); - else + if (newDev != null) + DeviceManager.AddDevice(newDev); + else Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key); - } - catch (Exception e) - { + } + catch (Exception e) + { Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Creating device {0}. Skipping device. \r{1}", devConf.Key, e); - } - } + } + } Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Devices Loaded."); - } + } - /// - /// Helper method to load tie lines. This should run after devices have loaded - /// - public void LoadTieLines() - { - // In the future, we can't necessarily just clear here because devices - // might be making their own internal sources/tie lines + /// + /// Helper method to load tie lines. This should run after devices have loaded + /// + public void LoadTieLines() + { + // In the future, we can't necessarily just clear here because devices + // might be making their own internal sources/tie lines - var tlc = TieLineCollection.Default; - //tlc.Clear(); - if (ConfigReader.ConfigObject.TieLines == null) - { - return; - } + var tlc = TieLineCollection.Default; + //tlc.Clear(); + if (ConfigReader.ConfigObject.TieLines == null) + { + return; + } - foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines) - { - var newTL = tieLineConfig.GetTieLine(); - if (newTL != null) - tlc.Add(newTL); - } + foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines) + { + var newTL = tieLineConfig.GetTieLine(); + if (newTL != null) + tlc.Add(newTL); + } Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Tie Lines Loaded."); - } + } - /// - /// Reads all rooms from config and adds them to DeviceManager - /// - public void LoadRooms() - { - if (ConfigReader.ConfigObject.Rooms == null) - { - Debug.Console(0, Debug.ErrorLogLevel.Warning, "WARNING: Configuration contains no rooms"); - return; - } + /// + /// Reads all rooms from config and adds them to DeviceManager + /// + public void LoadRooms() + { + if (ConfigReader.ConfigObject.Rooms == null) + { + Debug.Console(0, Debug.ErrorLogLevel.Warning, "WARNING: Configuration contains no rooms"); + return; + } - foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) - { + foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) + { var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as EssentialsRoomBase; - if (room != null) - { + if (room != null) + { if (room is EssentialsHuddleSpaceRoom) { DeviceManager.AddDevice(room); @@ -438,10 +471,10 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge..."); - // Cotija bridge - var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom); - AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present - DeviceManager.AddDevice(bridge); + // Cotija bridge + var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom); + AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present + DeviceManager.AddDevice(bridge); Debug.Console(0, Debug.ErrorLogLevel.Notice, "Cotija Bridge Added..."); } @@ -452,60 +485,60 @@ namespace PepperDash.Essentials Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion"); DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1)); - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge..."); - // Cotija bridge - var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room); - AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present - DeviceManager.AddDevice(bridge); - } + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge..."); + // Cotija bridge + var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room); + AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present + DeviceManager.AddDevice(bridge); + } else { Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsRoom, attempting to add to DeviceManager w/o Fusion"); DeviceManager.AddDevice(room); } - } - else + } + else Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key); - } + } Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded."); - } + } - /// - /// Helps add the post activation steps that link bridges to main controller - /// - /// - void AddBridgePostActivationHelper(CotijaBridgeBase bridge) - { - bridge.AddPostActivationAction(() => - { - var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController; - if (parent == null) - { - Debug.Console(0, bridge, "ERROR: Cannot connect app server room bridge. System controller not present"); - return; - } - Debug.Console(0, bridge, "Linking to parent controller"); - bridge.AddParent(parent); - parent.AddBridge(bridge); - }); - } + /// + /// Helps add the post activation steps that link bridges to main controller + /// + /// + void AddBridgePostActivationHelper(CotijaBridgeBase bridge) + { + bridge.AddPostActivationAction(() => + { + var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController; + if (parent == null) + { + Debug.Console(0, bridge, "ERROR: Cannot connect app server room bridge. System controller not present"); + return; + } + Debug.Console(0, bridge, "Linking to parent controller"); + bridge.AddParent(parent); + parent.AddBridge(bridge); + }); + } - /// - /// Fires up a logo server if not already running - /// - void LoadLogoServer() - { - try - { + /// + /// Fires up a logo server if not already running + /// + void LoadLogoServer() + { + try + { LogoServer = new HttpLogoServer(8080, Global.DirectorySeparator + "html" + Global.DirectorySeparator + "logo"); } - catch (Exception) - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "NOTICE: Logo server cannot be started. Likely already running in another program"); - } - } - } + catch (Exception) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "NOTICE: Logo server cannot be started. Likely already running in another program"); + } + } + } } From 6efec400b8a1b53bb90e8befdab3635c346d12b9 Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Thu, 13 Jun 2019 20:05:38 -0700 Subject: [PATCH 3/8] add invoke to bridgeapieisc --- PepperDashEssentials/Bridges/BridgeFactory.cs | 240 +++++++++--------- 1 file changed, 119 insertions(+), 121 deletions(-) diff --git a/PepperDashEssentials/Bridges/BridgeFactory.cs b/PepperDashEssentials/Bridges/BridgeFactory.cs index 923ee59f..6adeeafc 100644 --- a/PepperDashEssentials/Bridges/BridgeFactory.cs +++ b/PepperDashEssentials/Bridges/BridgeFactory.cs @@ -13,129 +13,127 @@ using PepperDash.Essentials.Bridges; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.EthernetCommunication; -namespace PepperDash.Essentials - +namespace PepperDash.Essentials { -public class BridgeFactory -{ - public static IKeyed GetDevice(DeviceConfig dc) - { - // ? why is this static JTA 2018-06-13? - - var key = dc.Key; - var name = dc.Name; - var type = dc.Type; - var properties = dc.Properties; - var propAnon = new { }; - - var typeName = dc.Type.ToLower(); - var groupName = dc.Group.ToLower(); + public class BridgeFactory + { + public static IKeyed GetDevice(DeviceConfig dc) + { + // ? why is this static JTA 2018-06-13? - //Debug.Console(2, "Name {0}, Key {1}, Type {2}, Properties {3}", name, key, type, properties.ToString()); + var key = dc.Key; + var name = dc.Name; + var type = dc.Type; + var properties = dc.Properties; + var propAnon = new { }; - if (typeName == "eiscapi") - { - return new EiscApi(dc); - } + var typeName = dc.Type.ToLower(); + var groupName = dc.Group.ToLower(); - return null; - } + //Debug.Console(2, "Name {0}, Key {1}, Type {2}, Properties {3}", name, key, type, properties.ToString()); + + if (typeName == "eiscapi") + { + return new EiscApi(dc); + } + + return null; + } + } + + + public class CommBridge : Device + { + public CommBridgeProperties Properties { get; private set; } + + public List CommDevices { get; private set; } + + public CommBridge(string key, string name, JToken properties) + : base(key, name) + { + Properties = JsonConvert.DeserializeObject(properties.ToString()); + } + + public override bool CustomActivate() + { + // Create EiscApis + if (Properties.Eiscs != null) + { + foreach (var eisc in Properties.Eiscs) + { + var ApiEisc = new BridgeApiEisc(eisc.IpId, eisc.Hostname); + } + } + + foreach (var deviceKey in Properties.CommDevices) + { + var device = DeviceManager.GetDeviceForKey(deviceKey); + + if (device != null) + { + Debug.Console(0, "deviceKey {0} Found in Device Manager", device.Key); + CommDevices.Add(device as IBasicCommunication); + } + else + { + Debug.Console(0, "deviceKey {0} Not Found in Device Manager", deviceKey); + } + } + + // Iterate through all the CommDevices and link up their Actions and Feedbacks + + Debug.Console(0, "Bridge {0} Activated", this.Name); + + return true; + } + } + + + public class EiscBridgeProperties + { + public string ParentDeviceKey { get; set; } + public eApiType ApiType { get; set; } + public List Eiscs { get; set; } + public string ApiOverrideFilePath { get; set; } + + public class EiscProperties + { + public string IpId { get; set; } + public string Hostname { get; set; } + } + } + + public class CommBridgeProperties : EiscBridgeProperties + { + public List CommDevices { get; set; } + } + + public enum eApiType { Eisc = 0 } + + public class BridgeApiEisc + { + public uint Ipid { get; private set; } + public ThreeSeriesTcpIpEthernetIntersystemCommunications Eisc { get; private set; } + + public BridgeApiEisc(string ipid, string hostname) + { + Ipid = (UInt32)int.Parse(ipid, System.Globalization.NumberStyles.HexNumber); + Eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(Ipid, hostname, Global.ControlSystem); + Eisc.Register(); + Eisc.SigChange += Eisc_SigChange; + Debug.Console(0, "BridgeApiEisc Created at Ipid {0}", ipid); + } + void Eisc_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) + { + if (Debug.Level >= 1) + Debug.Console(1, "BridgeApiEisc change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); + var uo = args.Sig.UserObject; + if (uo is Action) + CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.BoolValue), args); + else if (uo is Action) + CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.UShortValue), args); + else if (uo is Action) + CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.StringValue), args); + } + } } - - -public class CommBridge : Device -{ - public CommBridgeProperties Properties { get; private set; } - - public List CommDevices { get; private set; } - - public CommBridge(string key, string name, JToken properties) - : base(key, name) - { - Properties = JsonConvert.DeserializeObject(properties.ToString()); - } - - public override bool CustomActivate() - { - // Create EiscApis - if (Properties.Eiscs != null) - { - foreach (var eisc in Properties.Eiscs) - { - var ApiEisc = new BridgeApiEisc(eisc.IpId, eisc.Hostname); - } - } - - foreach (var deviceKey in Properties.CommDevices) - { - var device = DeviceManager.GetDeviceForKey(deviceKey); - - if (device != null) - { - Debug.Console(0, "deviceKey {0} Found in Device Manager", device.Key); - CommDevices.Add(device as IBasicCommunication); - } - else - { - Debug.Console(0, "deviceKey {0} Not Found in Device Manager", deviceKey); - } - } - - // Iterate through all the CommDevices and link up their Actions and Feedbacks - - Debug.Console(0, "Bridge {0} Activated", this.Name); - - return true; - } -} - - -public class EiscBridgeProperties -{ - public string ParentDeviceKey { get; set; } - public eApiType ApiType { get; set; } - public List Eiscs { get; set; } - public string ApiOverrideFilePath { get; set; } - - public class EiscProperties - { - public string IpId { get; set; } - public string Hostname { get; set; } - } -} - -public class CommBridgeProperties : EiscBridgeProperties -{ - public List CommDevices { get; set; } -} - -public enum eApiType { Eisc = 0 } - -public class BridgeApiEisc -{ - public uint Ipid { get; private set; } - public ThreeSeriesTcpIpEthernetIntersystemCommunications Eisc { get; private set; } - - public BridgeApiEisc(string ipid, string hostname) - { - Ipid = (UInt32)int.Parse(ipid, System.Globalization.NumberStyles.HexNumber); - Eisc = new ThreeSeriesTcpIpEthernetIntersystemCommunications(Ipid, hostname, Global.ControlSystem); - Eisc.Register(); - Eisc.SigChange += Eisc_SigChange; - Debug.Console(0, "BridgeApiEisc Created at Ipid {0}", ipid); - } - void Eisc_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args) - { - if (Debug.Level >= 1) - Debug.Console(1, "BridgeApiEisc change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); - var uo = args.Sig.UserObject; - if (uo is Action) - CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.BoolValue), args); - else if (uo is Action) - CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.UShortValue), args); - else if (uo is Action) - CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.StringValue), args); - } -} -} - \ No newline at end of file From 22722fca21406efa58eabfac81550de96fb30e56 Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Thu, 13 Jun 2019 20:06:43 -0700 Subject: [PATCH 4/8] update core ref to add PDC-14 and 15 features for testing kpmg --- essentials-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework b/essentials-framework index 75c2bf81..464de091 160000 --- a/essentials-framework +++ b/essentials-framework @@ -1 +1 @@ -Subproject commit 75c2bf819a3b7e6c37a3d6b0c7b11cc273043b12 +Subproject commit 464de0916dbc28da46d4092161c9c9a45f13d256 From f2c2cd423da9f7d9ac71a32ca4360f213607ea4d Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Fri, 14 Jun 2019 15:23:05 -0700 Subject: [PATCH 5/8] Remove the crestron invoke from the eisc change event. Not good as it could spool a lot of threads --- PepperDashEssentials/Bridges/BridgeFactory.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PepperDashEssentials/Bridges/BridgeFactory.cs b/PepperDashEssentials/Bridges/BridgeFactory.cs index 6adeeafc..38cd117e 100644 --- a/PepperDashEssentials/Bridges/BridgeFactory.cs +++ b/PepperDashEssentials/Bridges/BridgeFactory.cs @@ -129,11 +129,11 @@ namespace PepperDash.Essentials Debug.Console(1, "BridgeApiEisc change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue); var uo = args.Sig.UserObject; if (uo is Action) - CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.BoolValue), args); + (uo as Action)(args.Sig.BoolValue); else if (uo is Action) - CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.UShortValue), args); + (uo as Action)(args.Sig.UShortValue); else if (uo is Action) - CrestronInvoke.BeginInvoke(o => (uo as Action)((o as SigEventArgs).Sig.StringValue), args); + (uo as Action)(args.Sig.StringValue); } } } From fe172098b9ab58cdf9154a31934ce4ddf27d1cd8 Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Fri, 14 Jun 2019 15:50:21 -0700 Subject: [PATCH 6/8] updated core --- essentials-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework b/essentials-framework index 464de091..f9feb174 160000 --- a/essentials-framework +++ b/essentials-framework @@ -1 +1 @@ -Subproject commit 464de0916dbc28da46d4092161c9c9a45f13d256 +Subproject commit f9feb174eb56f39c93cda4dfe217513f79d8a64d From aff4e5a61f83b8a64380ad2f334691a765bafed9 Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Fri, 14 Jun 2019 19:18:50 -0700 Subject: [PATCH 7/8] update core ref --- essentials-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework b/essentials-framework index f9feb174..9d62e174 160000 --- a/essentials-framework +++ b/essentials-framework @@ -1 +1 @@ -Subproject commit f9feb174eb56f39c93cda4dfe217513f79d8a64d +Subproject commit 9d62e174e2b993ae974a6d09f7f54a8f16bc2924 From 327a9a5f6bc71f87347ba7bbc23b1cbf12437287 Mon Sep 17 00:00:00 2001 From: Joshua Gutenplan Date: Tue, 18 Jun 2019 16:56:51 -0700 Subject: [PATCH 8/8] Update compile to include pdc feature/MultipleServerUpdates --- essentials-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework b/essentials-framework index 9d62e174..4886a542 160000 --- a/essentials-framework +++ b/essentials-framework @@ -1 +1 @@ -Subproject commit 9d62e174e2b993ae974a6d09f7f54a8f16bc2924 +Subproject commit 4886a5427647b1cb2d5d939dc97515703cf96ceb