using Crestron.SimplSharpPro; using PepperDash.Core; using PepperDash.Core.Logging; using Serilog.Events; using System; using System.Collections.Generic; using System.Globalization; namespace PepperDash.Essentials.Core.Touchpanels { /// /// A wrapper class for the touchpanel portion of an MPC4 class process to allow for configurable /// behavior of the keypad buttons /// public class Mpc4TouchpanelController : Device { private readonly CrestronControlSystem _processor; private MPC3Basic _touchpanel; readonly Dictionary _buttons; /// /// Constructor /// /// device key /// device name /// control system processor /// dictionary of keypad buttons public Mpc4TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) : base(key, name) { _processor = processor; _buttons = buttons ?? new Dictionary(); } public override void Initialize() { if (_processor.MPC4x102TouchscreenSlot != null) { Debug.LogMessage(LogEventLevel.Information, this, "Using MPC4x102TouchscreenSlot"); _touchpanel = _processor.MPC4x102TouchscreenSlot; } else if (_processor.MPC4x201TouchscreenSlot != null) { Debug.LogMessage(LogEventLevel.Information, this, "Using MPC4x201TouchscreenSlot"); _touchpanel = _processor.MPC4x201TouchscreenSlot; } else if (_processor.MPC4x301TouchscreenSlot != null) { Debug.LogMessage(LogEventLevel.Information, this, "Using MPC4x301TouchscreenSlot"); _touchpanel = _processor.MPC4x301TouchscreenSlot; } else if (_processor.MPC4x302TouchscreenSlot != null) { Debug.LogMessage(LogEventLevel.Information, this, "Using MPC4x302TouchscreenSlot"); _touchpanel = _processor.MPC4x302TouchscreenSlot; } else { Debug.LogMessage(LogEventLevel.Error, this, "Failed to find MPC4 Touchpanel Controller with key {0}, check configuration", Key); return; } if (_touchpanel.Registerable) { var registrationResponse = _touchpanel.Register(); Debug.LogMessage(LogEventLevel.Information, this, "touchpanel registration response: {0}", registrationResponse); } _touchpanel.BaseEvent += Touchpanel_BaseEvent; _touchpanel.ButtonStateChange += Touchpanel_ButtonStateChange; _touchpanel.PanelStateChange += Touchpanel_PanelStateChange; foreach (var button in _buttons) { var buttonKey = button.Key.ToLower(); var buttonConfig = button.Value; InitializeButton(buttonKey, buttonConfig); InitializeButtonFeedback(buttonKey, buttonConfig); } ListButtons(); } /// /// Enables/disables buttons based on event type configuration /// /// /// public void InitializeButton(string key, KeypadButton config) { if (config == null) { Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' config is null, unable to initialize", key); return; } TryParseInt(key, out int buttonNumber); var buttonEventTypes = config.EventTypes; BoolOutputSig enabledFb = null; BoolOutputSig disabledFb = null; switch (key) { case ("power"): { if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisablePowerButton(); else _touchpanel.EnablePowerButton(); enabledFb = _touchpanel.PowerButtonEnabledFeedBack; disabledFb = _touchpanel.PowerButtonDisabledFeedBack; break; } case ("mute"): { if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisableMuteButton(); else _touchpanel.EnableMuteButton(); enabledFb = _touchpanel.MuteButtonEnabledFeedBack; disabledFb = _touchpanel.MuteButtonDisabledFeedBack; break; } default: { if (buttonNumber == 0 || buttonNumber > 9) break; if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisableNumericalButton((uint)buttonNumber); else _touchpanel.EnableNumericalButton((uint)buttonNumber); if (_touchpanel.NumericalButtonEnabledFeedBack != null) enabledFb = _touchpanel.NumericalButtonEnabledFeedBack[(uint)buttonNumber]; if (_touchpanel.NumericalButtonDisabledFeedBack != null) disabledFb = _touchpanel.NumericalButtonDisabledFeedBack[(uint)buttonNumber]; break; } } Debug.LogMessage(LogEventLevel.Information, this, "InitializeButton: key-'{0}' enabledFb-'{1}', disabledFb-'{2}'", key, enabledFb ?? (object)"null", disabledFb ?? (object)"null"); } /// /// Links button feedback if configured /// /// /// public void InitializeButtonFeedback(string key, KeypadButton config) { if (config == null) { Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' config is null, skipping.", key); return; } TryParseInt(key, out int buttonNumber); // Link up the button feedbacks to the specified device feedback var buttonFeedback = config.Feedback; if (buttonFeedback == null || string.IsNullOrEmpty(buttonFeedback.DeviceKey)) { Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback not configured, skipping.", key); return; } Feedback deviceFeedback; try { if (!(DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) is Device device)) { Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedback deviceKey '{1}' not found.", key, buttonFeedback.DeviceKey); return; } deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); if (deviceFeedback == null) { Debug.LogMessage(LogEventLevel.Debug, this, "Button '{0}' feedbackName property '{1}' not found.", key, buttonFeedback.FeedbackName); return; } } catch (Exception ex) { Debug.LogMessage(LogEventLevel.Debug, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception Message: {0}", ex.Message, key, buttonFeedback.DeviceKey); Debug.LogMessage(LogEventLevel.Verbose, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception StackTrace: {0}", ex.StackTrace, key, buttonFeedback.DeviceKey); if (ex.InnerException != null) Debug.LogMessage(LogEventLevel.Verbose, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') InnerException: {0}", ex.InnerException, key, buttonFeedback.DeviceKey); return; } var boolFeedback = deviceFeedback as BoolFeedback; switch (key) { case ("power"): { boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackPower); break; } case ("volumeup"): case ("volumedown"): case ("volumefeedback"): { if (deviceFeedback is IntFeedback intFeedback) { var volumeFeedback = intFeedback; volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); } break; } case ("mute"): { boolFeedback?.LinkCrestronFeedback(_touchpanel.FeedbackMute); break; } default: { 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_BaseEvent(GenericBase device, BaseEventArgs args) { Debug.LogMessage(LogEventLevel.Debug, this, "BaseEvent: eventId-'{0}', index-'{1}'", args.EventId, args.Index); } private void Touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) { Debug.LogMessage(LogEventLevel.Debug, this, "ButtonStateChange: buttonNumber-'{0}' buttonName-'{1}', buttonState-'{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); } } private void Touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args) { Debug.LogMessage(LogEventLevel.Debug, this, "PanelStateChange: eventId-'{0}', index-'{1}'", args.EventId, args.Index); } /// /// 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) { this.LogVerbose("Press: buttonKey-'{buttonKey}', type-'{type}'", buttonKey, type); 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); } /// /// ListButtons method /// public void ListButtons() { this.LogVerbose("MPC4 Controller {0} - Available Buttons", Key); foreach (var button in _buttons) { this.LogVerbose("Key: {key}", button.Key); } } } }