diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs
index 2049ef34..143929c9 100644
--- a/PepperDashEssentials/ControlSystem.cs
+++ b/PepperDashEssentials/ControlSystem.cs
@@ -61,6 +61,8 @@ namespace PepperDash.Essentials
CrestronConsole.AddNewConsoleCommand(PepperDash.Essentials.Core.DeviceFactory.GetDeviceFactoryTypes, "gettypes", "Gets the device types that can be built. Accepts a filter string.", ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(PepperDash.Essentials.Core.Room.Components.ComponentFactory.GetComponentFactoryTypes, "getcomponenttypes", "Gets the components types that can be built. Accepts a filter string.", ConsoleAccessLevelEnum.AccessOperator);
+
CrestronConsole.AddNewConsoleCommand(BridgeHelper.PrintJoinMap, "getjoinmap", "map(s) for bridge or device on bridge [brKey [devKey]]", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s =>
@@ -437,7 +439,7 @@ namespace PepperDash.Essentials
}
else
{
-
+ room = new ComponentRoom(roomConfig)
}
if (room != null && room is EssentialsRoomBase)
@@ -472,9 +474,9 @@ namespace PepperDash.Essentials
}
}
- else if (room is ComponentRoom)
+ else if (room != null && room is ComponentRoom)
{
-
+
}
else
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs
index 8d7f2c8d..781101d4 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/EssentialsDevice.cs
@@ -1,113 +1,113 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Crestron.SimplSharp;
-using Crestron.SimplSharp.Reflection;
-
-using PepperDash.Core;
-using PepperDash.Essentials.Core.Config;
-
-namespace PepperDash.Essentials.Core
-{
- ///
- /// Defines the basic needs for an EssentialsDevice to enable it to be build by an IDeviceFactory class
- ///
- [Description("The base Essentials Device Class")]
- public abstract class EssentialsDevice : Device
- {
- protected EssentialsDevice(string key)
- : base(key)
- {
-
- }
-
- protected EssentialsDevice(string key, string name)
- : base(key, name)
- {
-
- }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
- public class DescriptionAttribute : Attribute
- {
- private string _Description;
-
- public DescriptionAttribute(string description)
- {
- Debug.Console(2, "Setting Description: {0}", description);
- _Description = description;
- }
-
- public string Description
- {
- get { return _Description; }
- }
- }
-
- [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
- public class ConfigSnippetAttribute : Attribute
- {
- private string _ConfigSnippet;
-
- public ConfigSnippetAttribute(string configSnippet)
- {
- Debug.Console(2, "Setting Config Snippet {0}", configSnippet);
- _ConfigSnippet = configSnippet;
- }
-
- public string ConfigSnippet
- {
- get { return _ConfigSnippet; }
- }
- }
-
- ///
- /// Devices the basic needs for a Device Factory
- ///
- public abstract class EssentialsDeviceFactory : IDeviceFactory where T:EssentialsDevice
- {
- #region IDeviceFactory Members
-
- ///
- /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device
- ///
- public List TypeNames { get; protected set; }
-
- ///
- /// Loads an item to the DeviceFactory.FactoryMethods dictionary for each entry in the TypeNames list
- ///
- public void LoadTypeFactories()
- {
- foreach (var typeName in TypeNames)
- {
- Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName);
- var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.Reflection;
+
+using PepperDash.Core;
+using PepperDash.Essentials.Core.Config;
+
+namespace PepperDash.Essentials.Core
+{
+ ///
+ /// Defines the basic needs for an EssentialsDevice to enable it to be build by an IDeviceFactory class
+ ///
+ [Description("The base Essentials Device Class")]
+ public abstract class EssentialsDevice : Device
+ {
+ protected EssentialsDevice(string key)
+ : base(key)
+ {
+
+ }
+
+ protected EssentialsDevice(string key, string name)
+ : base(key, name)
+ {
+
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
+ public class DescriptionAttribute : Attribute
+ {
+ private string _Description;
+
+ public DescriptionAttribute(string description)
+ {
+ Debug.Console(2, "Setting Description: {0}", description);
+ _Description = description;
+ }
+
+ public string Description
+ {
+ get { return _Description; }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
+ public class ConfigSnippetAttribute : Attribute
+ {
+ private string _ConfigSnippet;
+
+ public ConfigSnippetAttribute(string configSnippet)
+ {
+ Debug.Console(2, "Setting Config Snippet {0}", configSnippet);
+ _ConfigSnippet = configSnippet;
+ }
+
+ public string ConfigSnippet
+ {
+ get { return _ConfigSnippet; }
+ }
+ }
+
+ ///
+ /// Devices the basic needs for a Device Factory
+ ///
+ public abstract class EssentialsDeviceFactory : IDeviceFactory where T:EssentialsDevice
+ {
+ #region IDeviceFactory Members
+
+ ///
+ /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device
+ ///
+ public List TypeNames { get; protected set; }
+
+ ///
+ /// Loads an item to the DeviceFactory.FactoryMethods dictionary for each entry in the TypeNames list
+ ///
+ public void LoadTypeFactories()
+ {
+ foreach (var typeName in TypeNames)
+ {
+ Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName);
+ var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];
string description = descriptionAttribute[0].Description;
- var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];
- DeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice);
- }
- }
-
- ///
- /// The method that will build the device
- ///
- /// The device config
- /// An instance of the device
- public abstract EssentialsDevice BuildDevice(DeviceConfig dc);
-
- #endregion
- }
-
- ///
- /// Devices the basic needs for a Device Factory
- ///
- public abstract class EssentialsPluginDeviceFactory : EssentialsDeviceFactory, IPluginDeviceFactory where T : EssentialsDevice
- {
- ///
- /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33")
- ///
- public string MinimumEssentialsFrameworkVersion { get; protected set; }
- }
+ var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];
+ DeviceFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildDevice);
+ }
+ }
+
+ ///
+ /// The method that will build the device
+ ///
+ /// The device config
+ /// An instance of the device
+ public abstract EssentialsDevice BuildDevice(DeviceConfig dc);
+
+ #endregion
+ }
+
+ ///
+ /// Devices the basic needs for a Device Factory
+ ///
+ public abstract class EssentialsPluginDeviceFactory : EssentialsDeviceFactory, IPluginDeviceFactory where T : EssentialsDevice
+ {
+ ///
+ /// Specifies the minimum version of Essentials required for a plugin to run. Must use the format Major.Minor.Build (ex. "1.4.33")
+ ///
+ public string MinimumEssentialsFrameworkVersion { get; protected set; }
+ }
}
\ No newline at end of file
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentFactory.cs
index e48c0a86..fab33c27 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentFactory.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentFactory.cs
@@ -3,13 +3,193 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
+using Crestron.SimplSharp.Reflection;
+
+using PepperDash.Core;
+
using PepperDash.Essentials.Interfaces.Components;
namespace PepperDash.Essentials.Core.Room.Components
{
- public class ComponentFactory
+ public class ComponentFactoryWrapper
+ {
+ public CType CType { get; set; }
+ public string Description { get; set; }
+ public Func FactoryMethod { get; set; }
+
+ public ComponentFactoryWrapper()
+ {
+ CType = null;
+ Description = "Not Available";
+ }
+ }
+
+ ///
+ /// Defines a class that is capable of loading component types
+ ///
+ public interface IComponentFactory : IDeviceFactory
{
}
-}
\ No newline at end of file
+
+ public static class ComponentFactory
+ {
+ public static ComponentFactory()
+ {
+ var assy = Assembly.GetExecutingAssembly();
+ PluginLoader.SetEssentialsAssembly(assy.GetName().Name, assy);
+
+ var types = assy.GetTypes().Where(ct => typeof(IComponentFactory).IsAssignableFrom(ct) && !ct.IsInterface && !ct.IsAbstract);
+
+ if (types != null)
+ {
+ foreach (var type in types)
+ {
+ try
+ {
+ var factory = (IComponentFactory)Crestron.SimplSharp.Reflection.Activator.CreateInstance(type);
+ factory.LoadTypeFactories();
+ }
+ catch (Exception e)
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to load type: '{1}' ComponentFactory: {0}", e, type.Name);
+ }
+ }
+ }
+ }
+
+ ///
+ /// A dictionary of factory methods, keyed by config types, added by plugins.
+ /// These methods are looked up and called by GetDevice in this class.
+ ///
+ static Dictionary FactoryMethods =
+ new Dictionary(StringComparer.OrdinalIgnoreCase);
+
+ ///
+ /// Adds a plugin factory method
+ ///
+ ///
+ ///
+ public static void AddFactoryForType(string typeName, Func method)
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
+ ComponentFactory.FactoryMethods.Add(typeName, new ComponentFactoryWrapper() { FactoryMethod = method });
+ }
+
+ public static void AddFactoryForType(string typeName, string description, CType cType, Func method)
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Notice, "Adding factory method for type '{0}'", typeName);
+
+ if (FactoryMethods.ContainsKey(typeName))
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Error, "Unable to add type: '{0}'. Already exists in ComponentFactory", typeName);
+ return;
+ }
+
+ var wrapper = new ComponentFactoryWrapper() { CType = cType, Description = description, FactoryMethod = method };
+ ComponentFactory.FactoryMethods.Add(typeName, wrapper);
+ }
+
+ ///
+ /// The factory method for Core components. Also iterates the Factory methods that have
+ /// been loaded from plugins
+ ///
+ ///
+ ///
+ public static IKeyed GetComponent(RoomComponentConfig dc)
+ {
+ var key = dc.Key;
+ var name = dc.Name;
+ var type = dc.Type;
+ var properties = dc.Properties;
+
+ var typeName = dc.Type.ToLower();
+
+ // Check for types that have been added by plugin dlls.
+ if (FactoryMethods.ContainsKey(typeName))
+ {
+ Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from Essentials Core", dc.Type);
+ return FactoryMethods[typeName].FactoryMethod(dc);
+ }
+
+ return null;
+ }
+
+ ///
+ /// Prints the type names and associated metadata from the FactoryMethods collection.
+ ///
+ ///
+ public static void GetComponentFactoryTypes(string filter)
+ {
+ Dictionary types = new Dictionary();
+
+ if (!string.IsNullOrEmpty(filter))
+ {
+ types = FactoryMethods.Where(k => k.Key.Contains(filter)).ToDictionary(k => k.Key, k => k.Value);
+ }
+ else
+ {
+ types = FactoryMethods;
+ }
+
+ Debug.Console(0, "Component Types:");
+
+ foreach (var type in types.OrderBy(t => t.Key))
+ {
+ var description = type.Value.Description;
+ var cType = "Not Specified by Plugin";
+
+ if (type.Value.CType != null)
+ {
+ cType = type.Value.CType.FullName;
+ }
+
+ Debug.Console(0,
+ @"Type: '{0}'
+ CType: '{1}'
+ Description: {2}", type.Key, cType, description);
+ }
+ }
+
+ }
+
+
+ ///
+ /// Devices the basic needs for a Device Factory
+ ///
+ public abstract class EssentialsComponentFactory : IComponentFactory where T : IComponent
+ {
+ #region IComponentFactory Members
+
+ ///
+ /// A list of strings that can be used in the type property of a DeviceConfig object to build an instance of this device
+ ///
+ public List TypeNames { get; protected set; }
+
+ ///
+ /// Loads an item to the ComponentFactory.FactoryMethods dictionary for each entry in the TypeNames list
+ ///
+ public void LoadTypeFactories()
+ {
+ foreach (var typeName in TypeNames)
+ {
+ Debug.Console(2, "Getting Description Attribute from class: '{0}'", typeof(T).FullName);
+ var descriptionAttribute = typeof(T).GetCustomAttributes(typeof(DescriptionAttribute), true) as DescriptionAttribute[];
+ string description = descriptionAttribute[0].Description;
+ var snippetAttribute = typeof(T).GetCustomAttributes(typeof(ConfigSnippetAttribute), true) as ConfigSnippetAttribute[];
+ ComponentFactory.AddFactoryForType(typeName.ToLower(), description, typeof(T), BuildComponent);
+ }
+ }
+
+ ///
+ /// The method that will build the device
+ ///
+ /// The device config
+ /// An instance of the device
+ public abstract IComponent BuildComponent(RoomComponentConfig dc);
+
+ #endregion
+ }
+}
+
diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentRoom.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentRoom.cs
index fd12901c..14daf522 100644
--- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentRoom.cs
+++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Components/ComponentRoom.cs
@@ -7,6 +7,7 @@ using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Interfaces.Components;
using PepperDash.Essentials.Core.Config;
+using PepperDash.Essentials.Core.Devices;
using Newtonsoft.Json;
@@ -51,6 +52,9 @@ namespace PepperDash.Essentials.Core.Room
}
+ ///
+ /// The config class for a ComponentRoom
+ ///
public class ComponentRoomPropertiesConfig
{
[JsonProperty("activities")]
@@ -60,14 +64,29 @@ namespace PepperDash.Essentials.Core.Room
}
- public class ComponentRoom : Device, IComponentRoom
+
+ ///
+ /// A room comprised of component parts built at runtime.
+ ///
+ public class ComponentRoom : ReconfigurableDevice, IComponentRoom
{
+ public ComponentRoomPropertiesConfig PropertiesConfig { get; private set; }
+
public List Components { get; private set; }
public List Activities { get; private set; }
- public ComponentRoom(string key, string name)
- : base(key, name)
+ public ComponentRoom(DeviceConfig config)
+ : base(config)
{
+ try
+ {
+ PropertiesConfig = JsonConvert.DeserializeObject
+ (config.Properties.ToString());
+ }
+ catch (Exception e)
+ {
+ Debug.Console(1, this, "Error building ComponentRoom: \n{0}", e);
+ }
}