diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index a88d932b..5b8579f5 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -428,11 +428,30 @@ namespace PepperDash.Essentials DeviceManager.AddDevice(dmpsRoutingController); } + else if (this.ControllerPrompt.IndexOf("mpc3", StringComparison.OrdinalIgnoreCase) > -1) + { + Debug.Console(2, "MPC3 processor type detected. Adding Mpc3TouchpanelController."); + + var butToken = devConf.Properties["buttons"]; + if (butToken != null) + { + var buttons = butToken.ToObject>(); + var tpController = new Essentials.Core.Touchpanels.Mpc3TouchpanelController(devConf.Key, devConf.Name, Global.ControlSystem, buttons); + DeviceManager.AddDevice(tpController); + } + else + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: Unable to deserialize buttons collection for device: {0}", devConf.Key); + } + + } else { Debug.Console(2, "************Processor is not DMPS type***************"); } + + continue; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceFeedbackExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceFeedbackExtensions.cs new file mode 100644 index 00000000..1ef59b0f --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceFeedbackExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + public static class DeviceFeedbackExtensions + { + /// + /// Attempts to get and return a feedback property from a device by name. + /// If unsuccessful, returns null. + /// + /// + /// + /// + public static Feedback GetFeedbackProperty(this Device device, string propertyName) + { + var feedback = DeviceJsonApi.GetPropertyByName(device.Key, propertyName) as Feedback; + + if (feedback != null) + { + return feedback; + } + + return null; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs index 32d53388..c7bc7c68 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/DeviceJsonApi.cs @@ -59,7 +59,7 @@ namespace PepperDash.Essentials.Core } /// - /// + /// Gets the properties on a device /// /// /// @@ -75,8 +75,34 @@ namespace PepperDash.Essentials.Core return JsonConvert.SerializeObject(props, Formatting.Indented); } + /// + /// Gets a property from a device path by name + /// + /// + /// + /// + public static object GetPropertyByName(string deviceObjectPath, string propertyName) + { + var obj = FindObjectOnPath(deviceObjectPath); + if(obj == null) + return "{ \"error\":\"No Device\"}"; + + CType t = obj.GetType(); + + var prop = t.GetProperty(propertyName); + if (prop != null) + { + return prop; + } + else + { + Debug.Console(1, "Unable to find Property: {0} on Device with path: {1}", propertyName, deviceObjectPath); + return null; + } + } + /// - /// + /// Gets the methods on a device /// /// /// diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs index 8bc89bd4..c07bc010 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Factory/DeviceFactory.cs @@ -9,6 +9,7 @@ using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Config; using PepperDash.Essentials.Core.CrestronIO; +using PepperDash.Essentials.Core.Touchpanels; namespace PepperDash.Essentials.Core { @@ -47,13 +48,21 @@ namespace PepperDash.Essentials.Core var typeName = dc.Type.ToLower(); - // Check "core" types first + + // Check for types that have been added by plugin dlls. + if (FactoryMethods.ContainsKey(typeName)) + { + Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from plugin", dc.Type); + return FactoryMethods[typeName](dc); + } + + // Check "core" types if (typeName == "genericcomm") { Debug.Console(1, "Factory Attempting to create new Generic Comm Device"); return new GenericComm(dc); } - else if (typeName == "ceniodigin104") + if (typeName == "ceniodigin104") { var control = CommFactory.GetControlPropertiesConfig(dc); var ipid = control.IpIdInt; @@ -75,13 +84,6 @@ namespace PepperDash.Essentials.Core return new C2nRthsController(key, name, new C2nRths(cresnetId, Global.ControlSystem)); } - // then check for types that have been added by plugin dlls. - if (FactoryMethods.ContainsKey(typeName)) - { - Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading '{0}' from plugin", dc.Type); - return FactoryMethods[typeName](dc); - } - return null; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolFeedback.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolFeedback.cs index 9fb4c1e1..60a09df8 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolFeedback.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Feedbacks/BoolFeedback.cs @@ -32,6 +32,8 @@ namespace PepperDash.Essentials.Core List LinkedInputSigs = new List(); List LinkedComplementInputSigs = new List(); + List LinkedCrestronFeedbacks = new List(); + public BoolFeedback(Func valueFunc) : this(null, valueFunc) { @@ -56,28 +58,63 @@ namespace PepperDash.Essentials.Core } } + /// + /// Links an input sig + /// + /// public void LinkInputSig(BoolInputSig sig) { LinkedInputSigs.Add(sig); UpdateSig(sig); } + /// + /// Unlinks an inputs sig + /// + /// public void UnlinkInputSig(BoolInputSig sig) { LinkedInputSigs.Remove(sig); } + /// + /// Links an input sig to the complement value + /// + /// public void LinkComplementInputSig(BoolInputSig sig) { LinkedComplementInputSigs.Add(sig); UpdateComplementSig(sig); } + /// + /// Unlinks an input sig to the complement value + /// + /// public void UnlinkComplementInputSig(BoolInputSig sig) { LinkedComplementInputSigs.Remove(sig); } + /// + /// Links a Crestron Feedback object + /// + /// + public void LinkCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) + { + LinkedCrestronFeedbacks.Add(feedback); + UpdateCrestronFeedback(feedback); + } + + /// + /// + /// + /// + public void UnlinkCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) + { + LinkedCrestronFeedbacks.Remove(feedback); + } + public override string ToString() { return (InTestMode ? "TEST -- " : "") + BoolValue.ToString(); @@ -103,6 +140,11 @@ namespace PepperDash.Essentials.Core { sig.BoolValue = !_BoolValue; } + + void UpdateCrestronFeedback(Crestron.SimplSharpPro.DeviceSupport.Feedback feedback) + { + feedback.State = _BoolValue; + } } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index cc3c6d74..61d1ffce 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -131,6 +131,7 @@ + @@ -236,6 +237,7 @@ + diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs new file mode 100644 index 00000000..01bae32d --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; + +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.Touchpanels +{ + /// + /// A wrapper class for the touchpanel portion of an MPC3 class process to allow for configurable + /// behavior of the keybad buttons + /// + public class Mpc3TouchpanelController : Device + { + MPC3Basic _Touchpanel; + + Dictionary _Buttons; + + public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) + : base(key, name) + { + _Touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; + _Buttons = buttons; + + _Touchpanel.ButtonStateChange += new Crestron.SimplSharpPro.DeviceSupport.ButtonEventHandler(_Touchpanel_ButtonStateChange); + + + AddPostActivationAction(() => + { + // Link up the button feedbacks to the specified BoolFeedbacks + foreach (var button in _Buttons) + { + var feedbackConfig = button.Value.Feedback; + var device = DeviceManager.GetDeviceForKey(feedbackConfig.DeviceKey) as Device; + if (device != null) + { + var feedback = device.GetFeedbackProperty(feedbackConfig.BoolFeedbackName) as BoolFeedback; + if (feedback != null) + { + // Link to the Crestron Feedback corresponding to the button number + feedback.LinkCrestronFeedback(_Touchpanel.Feedbacks[button.Key]); + } + else + { + Debug.Console(1, this, "Unable to get BoolFeedback with name: {0} from device: {1}", feedbackConfig.BoolFeedbackName, device.Key); + } + } + else + { + Debug.Console(1, this, "Unable to get device with key: {0}", feedbackConfig.DeviceKey); + } + } + }); + } + + void _Touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) + { + Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); + if (_Buttons.ContainsKey(args.Button.Number)) + { + var type = args.NewButtonState.ToString(); + Press(args.Button.Number, type); + } + } + + /// + /// Runs the function associated with this button/type. One of the following strings: + /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased + /// + /// + /// + public void Press(uint number, string type) + { + // TODO: In future, consider modifying this to generate actions at device activation time + // to prevent the need to dynamically call the method via reflection on each button press + if (!_Buttons.ContainsKey(number)) { return; } + var but = _Buttons[number]; + if (but.EventTypes.ContainsKey(type)) + { + foreach (var a in but.EventTypes[type]) { DeviceJsonApi.DoDeviceAction(a); } + } + } + + + } + + /// + /// Represents the configuration of a keybad buggon + /// + public class KeypadButton + { + public Dictionary EventTypes { get; set; } + public KeypadButtonFeedback Feedback { get; set; } + + public KeypadButton() + { + EventTypes = new Dictionary(); + Feedback = new KeypadButtonFeedback(); + } + } + + /// + /// + /// + public class KeypadButtonFeedback + { + public string DeviceKey { get; set; } + public string BoolFeedbackName { get; set; } + } +} \ No newline at end of file