diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index f24cb828..1bafbbac 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -401,20 +401,21 @@ namespace PepperDash.Essentials } else if (this.ControllerPrompt.IndexOf("mpc3", StringComparison.OrdinalIgnoreCase) > -1) { - Debug.Console(2, "MPC3 processor type detected. Adding Mpc3TouchpanelController."); + 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); - } - + var butToken = devConf.Properties["buttons"]; + if (butToken == null) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, + "Error: Unable to deserialize buttons collection for device: {0}", devConf.Key); + continue; + } + + var buttons = butToken.ToObject>(); + var tpController = new Core.Touchpanels.Mpc3TouchpanelController( + string.Format("{0}-keypadButtons", devConf.Key), devConf.Name, Global.ControlSystem, buttons); + + DeviceManager.AddDevice(tpController); } else { diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index c9a5f605..f4611a70 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -1,144 +1,295 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Collections.Generic; +using System.Globalization; using Crestron.SimplSharpPro; - +using Newtonsoft.Json; 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; + /// + /// 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 + { + readonly MPC3Basic _touchpanel; - Dictionary _Buttons; + readonly Dictionary _buttons; - public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) - : base(key, name) - { - _Touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; - _Buttons = buttons; + public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) + : base(key, name) + { + _touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; + if (_touchpanel == null) + { + Debug.Console(1, this, "Failed to construct MPC3 Touchpanel Controller with key {0}, check configuration", key); + return; + } - _Touchpanel.ButtonStateChange += new Crestron.SimplSharpPro.DeviceSupport.ButtonEventHandler(_Touchpanel_ButtonStateChange); + _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; + _buttons = buttons; + if (_buttons == null) + { + Debug.Console(1, this, + "Button properties are null, failed to setup MPC3 Touch Controller, check configuration"); + return; + } - 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 bKey = button.Key.ToLower(); + AddPostActivationAction(() => + { + foreach (var button in _buttons) + { + var buttonKey = button.Key.ToLower(); + var buttonConfig = button.Value; - var feedback = device.GetFeedbackProperty(feedbackConfig.FeedbackName); + InitializeButton(buttonKey, buttonConfig); + InitializeButtonFeedback(buttonKey, buttonConfig); + } + }); + } - var bFeedback = feedback as BoolFeedback; - var iFeedback = feedback as IntFeedback; - if (bFeedback != null) - { + /// + /// Enables/disables buttons based on event type configuration + /// + /// + /// + public void InitializeButton(string key, KeypadButton config) + { + if (config == null) + { + Debug.Console(1, this, "Button '{0}' config is null, unable to initialize", key); + return; + } - if (bKey == "power") - { - bFeedback.LinkCrestronFeedback(_Touchpanel.FeedbackPower); - continue; - } - else if (bKey == "mute") - { - bFeedback.LinkCrestronFeedback(_Touchpanel.FeedbackMute); - continue; - } + int buttonNumber; + TryParseInt(key, out buttonNumber); - // Link to the Crestron Feedback corresponding to the button number - bFeedback.LinkCrestronFeedback(_Touchpanel.Feedbacks[UInt16.Parse(button.Key)]); - } - else if (iFeedback != null) - { - if (bKey == "volumefeedback") - { - var volFeedback = feedback as IntFeedback; - // TODO: Figure out how to subsribe to a volume IntFeedback and link it to the voluem - volFeedback.LinkInputSig(_Touchpanel.VolumeBargraph); - } - } - else - { - Debug.Console(1, this, "Unable to get BoolFeedback with name: {0} from device: {1}", feedbackConfig.FeedbackName, device.Key); - } - } - else - { - Debug.Console(1, this, "Unable to get device with key: {0}", feedbackConfig.DeviceKey); - } - } - }); - } + var buttonEventTypes = config.EventTypes; - 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); - var type = args.NewButtonState.ToString(); + switch (key) + { + case ("power"): + { + if (buttonEventTypes == null) + _touchpanel.DisablePowerButton(); + else + _touchpanel.EnablePowerButton(); - if (_Buttons.ContainsKey(args.Button.Number.ToString())) - { - Press(args.Button.Number.ToString(), type); - } - else if(_Buttons.ContainsKey(args.Button.Name.ToString())) - { - Press(args.Button.Name.ToString(), type); - } - } + break; + } + case ("volumeup"): + { + if (buttonEventTypes == null) + _touchpanel.DisableVolumeUpButton(); - /// - /// Runs the function associated with this button/type. One of the following strings: - /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased - /// - /// - /// - public void Press(string 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); } - } - } + break; + } + case ("volumedown"): + { + if (buttonEventTypes == null) + _touchpanel.DisableVolumeDownButton(); + break; + } + case ("volumefeedback"): + { - } + break; + } + case ("mute"): + { + if (buttonEventTypes == null) + _touchpanel.DisableMuteButton(); + else + _touchpanel.EnableMuteButton(); - /// - /// Represents the configuration of a keybad buggon - /// - public class KeypadButton - { - public Dictionary EventTypes { get; set; } - public KeypadButtonFeedback Feedback { get; set; } + break; + } + default: + { + if (buttonNumber == 0) + break; - public KeypadButton() - { - EventTypes = new Dictionary(); - Feedback = new KeypadButtonFeedback(); - } - } + if (buttonEventTypes == null) + _touchpanel.DisableNumericalButton((uint)buttonNumber); + else + _touchpanel.EnableNumericalButton((uint)buttonNumber); - /// - /// - /// - public class KeypadButtonFeedback - { - public string DeviceKey { get; set; } - public string FeedbackName { get; set; } - } + break; + } + } + + Debug.Console(1, this, "Button '{0}' {1}", key, buttonEventTypes == null + ? "is disabled, verify eventTypes are configured." + : "is enabled"); + } + + /// + /// Links button feedback if configured + /// + /// + /// + public void InitializeButtonFeedback(string key, KeypadButton config) + { + if (config == null) + { + Debug.Console(1, this, "Button '{0}' config is null, unable to initialize feedback", key); + return; + } + + int buttonNumber; + TryParseInt(key, out buttonNumber); + + // Link up the button feedbacks to the specified device feedback + var buttonFeedback = config.Feedback; + if (buttonFeedback == null) + { + Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. Verify feedback is configured if required.", key); + return; + } + + var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + if (device == null) + { + Debug.Console(1, this, "Button '{0}' feedback device with key '{0}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", + buttonFeedback.DeviceKey); + return; + } + + // TODO [ ] verify if this can replace the current method + var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); + //switch (feedback.GetType().Name.ToLower()) + //{ + // case("boolfeedback"): + // { + // break; + // } + // case("intfeedback"): + // { + // break; + // } + // case("stringfeedback"): + // { + // break; + // } + //} + + var boolFeedback = deviceFeedback as BoolFeedback; + var intFeedback = deviceFeedback as IntFeedback; + + switch (key) + { + case ("power"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); + break; + } + case ("volumeup"): + case ("volumedown"): + case ("volumefeedback"): + { + if (intFeedback != null) + { + var volumeFeedback = intFeedback; + volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); + } + break; + } + case ("mute"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); + break; + } + default: + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); + break; + } + } + } + + /// + /// Try parse int helper method + /// + /// + /// + /// + public bool TryParseInt(string str, out int result) + { + try + { + result = int.Parse(str); + return true; + } + catch + { + result = 0; + return false; + } + } + + private 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); + var type = args.NewButtonState.ToString(); + + if (_buttons.ContainsKey(args.Button.Number.ToString(CultureInfo.InvariantCulture))) + { + Press(args.Button.Number.ToString(CultureInfo.InvariantCulture), type); + } + else if (_buttons.ContainsKey(args.Button.Name.ToString())) + { + Press(args.Button.Name.ToString(), type); + } + } + + /// + /// Runs the function associated with this button/type. One of the following strings: + /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased + /// + /// + /// + public void Press(string buttonKey, 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(buttonKey)) return; + + var button = _buttons[buttonKey]; + if (!button.EventTypes.ContainsKey(type)) return; + + foreach (var eventType in button.EventTypes[type]) DeviceJsonApi.DoDeviceAction(eventType); + } + } + + /// + /// Represents the configuration of a keypad button + /// + public class KeypadButton + { + [JsonProperty("eventTypes")] + public Dictionary EventTypes { get; set; } + + [JsonProperty("feedback")] + public KeypadButtonFeedback Feedback { get; set; } + + public KeypadButton() + { + EventTypes = new Dictionary(); + Feedback = new KeypadButtonFeedback(); + } + } + + /// + /// Represents the configuration of a keypad button feedback + /// + public class KeypadButtonFeedback + { + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + [JsonProperty("feedbackName")] + public string FeedbackName { get; set; } + } } \ No newline at end of file