From 7dd3ccc67024e36bde89ef27d8aaad116990d8b7 Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Tue, 31 Oct 2023 20:49:38 +0000 Subject: [PATCH] Configurable Menu Uses a JSON file served by a URL. --- manifest.xml | 15 ++- resources/drawables/drawables.xml | 14 ++ resources/layouts/layout.xml | 6 - resources/menus/menu.xml | 4 - resources/settings/properties.xml | 25 +++- resources/settings/settings.xml | 34 +++++ resources/strings/strings.xml | 19 ++- source/Alert.mc | 142 +++++++++++++++++++ source/Globals.mc | 30 +++-- source/HomeAssistantApp.mc | 98 +++++++++++++- source/HomeAssistantMenuItem.mc | 30 ++++- source/HomeAssistantToggleMenuItem.mc | 40 ++++-- source/HomeAssistantView.mc | 187 ++++++++++++++------------ source/HomeAssistantViewMenuItem.mc | 43 ++++++ 14 files changed, 550 insertions(+), 137 deletions(-) delete mode 100644 resources/layouts/layout.xml delete mode 100644 resources/menus/menu.xml create mode 100644 source/Alert.mc create mode 100644 source/HomeAssistantViewMenuItem.mc diff --git a/manifest.xml b/manifest.xml index 9028ea1..eb86c81 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,5 +1,18 @@ - + + + diff --git a/resources/layouts/layout.xml b/resources/layouts/layout.xml deleted file mode 100644 index e0bb1b2..0000000 --- a/resources/layouts/layout.xml +++ /dev/null @@ -1,6 +0,0 @@ - - diff --git a/resources/menus/menu.xml b/resources/menus/menu.xml deleted file mode 100644 index 6537eba..0000000 --- a/resources/menus/menu.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/resources/settings/properties.xml b/resources/settings/properties.xml index 5d2bccb..f1537be 100644 --- a/resources/settings/properties.xml +++ b/resources/settings/properties.xml @@ -1,3 +1,26 @@ + + - + eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI1OTEzODI3NzhiNDI0MzU5OGVmYzY4ZmM2YzZiZTU3ZCIsImlhdCI6MTY5ODU3MDg0MywiZXhwIjoyMDEzOTMwODQzfQ.vskr0ERbnEXjB51vVHwlXosy3JK3v1znHzv8Hiej8zA + + + https://home.abbey1.org.uk/api + + + https://home.abbey1.org.uk/local/garmin/philip.json diff --git a/resources/settings/settings.xml b/resources/settings/settings.xml index 664d902..1ea3ca6 100644 --- a/resources/settings/settings.xml +++ b/resources/settings/settings.xml @@ -1,3 +1,17 @@ + + + + + + + + + + diff --git a/resources/strings/strings.xml b/resources/strings/strings.xml index f425222..ba10b15 100644 --- a/resources/strings/strings.xml +++ b/resources/strings/strings.xml @@ -1,8 +1,17 @@ + + HomeAssistant - - Click the menu button - - Item 1 - Item 2 diff --git a/source/Alert.mc b/source/Alert.mc new file mode 100644 index 0000000..c77e338 --- /dev/null +++ b/source/Alert.mc @@ -0,0 +1,142 @@ +//----------------------------------------------------------------------------------- +// +// Distributed under MIT Licence +// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. +// +//----------------------------------------------------------------------------------- +// +// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely +// tested on a Venu 2 device. The source code is provided at: +// https://github.com/house-of-abbey/GarminHomeAssistant. +// +// J D Abbey & P A Abbey, 28 December 2022 +// +// +// Description: +// +// Alert provides a means to present application notifications to the user +// briefly. Credit to travis.vitek on forums.garmin.com. +// +// Reference: +// * https://forums.garmin.com/developer/connect-iq/f/discussion/106/how-to-show-alert-messages +// +//----------------------------------------------------------------------------------- + +using Toybox.Lang; +using Toybox.Graphics; +using Toybox.WatchUi; +using Toybox.Timer; + +const bRadius = 10; + +class Alert extends WatchUi.View { + hidden var timer; + hidden var timeout; + hidden var text; + hidden var font; + hidden var fgcolor; + hidden var bgcolor; + + function initialize(params as Lang.Dictionary) { + View.initialize(); + + text = params.get(:text); + if (text == null) { + text = "Alert"; + } + + font = params.get(:font); + if (font == null) { + font = Graphics.FONT_MEDIUM; + } + + fgcolor = params.get(:fgcolor); + if (fgcolor == null) { + fgcolor = Graphics.COLOR_BLACK; + } + + bgcolor = params.get(:bgcolor); + if (bgcolor == null) { + bgcolor = Graphics.COLOR_WHITE; + } + + timeout = params.get(:timeout); + if (timeout == null) { + timeout = 2000; + } + + timer = new Timer.Timer(); + } + + function onShow() { + timer.start(method(:dismiss), timeout, false); + } + + function onHide() { + timer.stop(); + } + + function onUpdate(dc) { + var tWidth = dc.getTextWidthInPixels(text, font); + var tHeight = dc.getFontHeight(font); + var bWidth = tWidth + 20; + var bHeight = tHeight + 15; + var bX = (dc.getWidth() - bWidth) / 2; + var bY = (dc.getHeight() - bHeight) / 2; + + if(dc has :setAntiAlias) { + dc.setAntiAlias(true); + } + + dc.setColor( + Graphics.COLOR_WHITE, + Graphics.COLOR_TRANSPARENT + ); + dc.clear(); + dc.setColor(bgcolor, bgcolor); + dc.fillRoundedRectangle(bX, bY, bWidth, bHeight, bRadius); + + dc.setColor(fgcolor, bgcolor); + for (var i = 0; i < 3; ++i) { + bX += i; + bY += i; + bWidth -= (2 * i); + bHeight -= (2 * i); + dc.drawRoundedRectangle(bX, bY, bWidth, bHeight, bRadius); + } + + var tX = dc.getWidth() / 2; + var tY = bY + bHeight / 2; + dc.setColor(fgcolor, bgcolor); + dc.drawText(tX, tY, font, text, Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER); + } + + // Remove the alert from view, usually on user input, but that is defined by the calling function. + // + function dismiss() { + WatchUi.popView(SLIDE_IMMEDIATE); + } + + function pushView(transition) { + WatchUi.pushView(self, new AlertDelegate(self), transition); + } +} + +class AlertDelegate extends WatchUi.InputDelegate { + hidden var mView; + + function initialize(view) { + InputDelegate.initialize(); + mView = view; + } + + function onKey(evt) { + mView.dismiss(); + return true; + } + + function onTap(evt) { + mView.dismiss(); + return true; + } +} diff --git a/source/Globals.mc b/source/Globals.mc index 75adb8f..5e8e393 100644 --- a/source/Globals.mc +++ b/source/Globals.mc @@ -1,15 +1,29 @@ +//----------------------------------------------------------------------------------- +// +// Distributed under MIT Licence +// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. +// +//----------------------------------------------------------------------------------- +// +// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely +// tested on a Venu 2 device. The source code is provided at: +// https://github.com/house-of-abbey/GarminHomeAssistant. +// +// P A Abbey & J D Abbey, 31 October 2023 +// +// +// Description: +// +// Home Assistant centralised constants. +// +//----------------------------------------------------------------------------------- + using Toybox.Lang; class Globals { // Enable printing of messages to the debug console (don't make this a Property // as the messages can't be read from a watch!) static const debug = false; - static const updateInterval = 5; // seconds -// static hidden const apiUrl = "https://homeassistant.local/api"; - static hidden const apiUrl = "https://home.abbey1.org.uk/api"; - - static function getApiUrl() { - return apiUrl; - } - + static const updateInterval = 5; // seconds + static const alertTimeout = 1000; // ms } diff --git a/source/HomeAssistantApp.mc b/source/HomeAssistantApp.mc index 3aad550..812f118 100644 --- a/source/HomeAssistantApp.mc +++ b/source/HomeAssistantApp.mc @@ -1,24 +1,108 @@ -import Toybox.Application; -import Toybox.Lang; -import Toybox.WatchUi; +//----------------------------------------------------------------------------------- +// +// Distributed under MIT Licence +// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. +// +//----------------------------------------------------------------------------------- +// +// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely +// tested on a Venu 2 device. The source code is provided at: +// https://github.com/house-of-abbey/GarminHomeAssistant. +// +// P A Abbey & J D Abbey, 31 October 2023 +// +// +// Description: +// +// Application root for GarminHomeAssistant. +// +//----------------------------------------------------------------------------------- + +using Toybox.Application; +using Toybox.Lang; +using Toybox.WatchUi; +using Toybox.Application.Properties; +using Toybox.Timer; class HomeAssistantApp extends Application.AppBase { + hidden var haMenu; + hidden var timer as Timer.Timer; function initialize() { AppBase.initialize(); + timer = new Timer.Timer(); } // onStart() is called on application start up - function onStart(state as Dictionary?) as Void { + function onStart(state as Lang.Dictionary?) as Void { + fetchMenuConfig(); } // onStop() is called when your application is exiting - function onStop(state as Dictionary?) as Void { + function onStop(state as Lang.Dictionary?) as Void { + if (timer != null) { + timer.stop(); + } } // Return the initial view of your application here - function getInitialView() as Array? { - return [ new HomeAssistantView(), new HomeAssistantViewDelegate() ] as Array; + function getInitialView() as Lang.Array? { + return [new WatchUi.View(), new WatchUi.BehaviorDelegate()] as Lang.Array; + } + + // Callback function after completing the GET request to fetch the configuration menu. + // + function onReturnFetchMenuConfig(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void { + if (Globals.debug) { + System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Code: " + responseCode); + System.println("HomeAssistantApp onReturnFetchMenuConfig() Response Data: " + data); + } + if (responseCode == 200) { + haMenu = new HomeAssistantView(data, null); + timer.start( + haMenu.method(:stateUpdate), + Globals.updateInterval * 1000, + true + ); + WatchUi.switchToView(haMenu, new HomeAssistantViewDelegate(), WatchUi.SLIDE_IMMEDIATE); + } else { + if (Globals.debug) { + System.println("HomeAssistantApp Note - onReturnFetchMenuConfig(): Configuration not found or potential validation issue."); + } + new Alert({ + :timeout => Globals.alertTimeout, + :font => Graphics.FONT_SYSTEM_MEDIUM, + :text => "Error " + responseCode, + :fgcolor => Graphics.COLOR_RED, + :bgcolor => Graphics.COLOR_BLACK + }).pushView(WatchUi.SLIDE_IMMEDIATE); + } + } + + function fetchMenuConfig() as Void { + var options = { + :method => Communications.HTTP_REQUEST_METHOD_GET, + :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON + }; + if (System.getDeviceSettings().phoneConnected && System.getDeviceSettings().connectionAvailable) { + Communications.makeWebRequest( + Properties.getValue("config_url"), + null, + options, + method(:onReturnFetchMenuConfig) + ); + } else { + if (Globals.debug) { + System.println("HomeAssistantApp Note - fetchMenuConfig(): No Internet connection, skipping API call."); + } + new Alert({ + :timeout => Globals.alertTimeout, + :font => Graphics.FONT_SYSTEM_MEDIUM, + :text => "No Internet connection", + :fgcolor => Graphics.COLOR_RED, + :bgcolor => Graphics.COLOR_BLACK + }).pushView(WatchUi.SLIDE_IMMEDIATE); + } } } diff --git a/source/HomeAssistantMenuItem.mc b/source/HomeAssistantMenuItem.mc index 2f3b484..57d5d37 100644 --- a/source/HomeAssistantMenuItem.mc +++ b/source/HomeAssistantMenuItem.mc @@ -1,6 +1,26 @@ -import Toybox.Lang; -import Toybox.WatchUi; -import Toybox.Graphics; +//----------------------------------------------------------------------------------- +// +// Distributed under MIT Licence +// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. +// +//----------------------------------------------------------------------------------- +// +// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely +// tested on a Venu 2 device. The source code is provided at: +// https://github.com/house-of-abbey/GarminHomeAssistant. +// +// P A Abbey & J D Abbey, 31 October 2023 +// +// +// Description: +// +// Menu button that triggers a script. +// +//----------------------------------------------------------------------------------- + +using Toybox.Lang; +using Toybox.WatchUi; +using Toybox.Graphics; using Toybox.Application.Properties; class HomeAssistantMenuItem extends WatchUi.MenuItem { @@ -11,7 +31,7 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem { subLabel as Lang.String or Lang.Symbol or Null, identifier as Lang.Object or Null, options as { - :alignment as MenuItem.Alignment, + :alignment as WatchUi.MenuItem.Alignment, :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol } or Null ) { @@ -51,7 +71,7 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem { :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON }; if (System.getDeviceSettings().phoneConnected && System.getDeviceSettings().connectionAvailable) { - var url = Globals.getApiUrl() + "/services/" + mIdentifier.substring(0, mIdentifier.find(".")) + "/" + mIdentifier.substring(mIdentifier.find(".")+1, null); + var url = Properties.getValue("api_url") + "/services/" + mIdentifier.substring(0, mIdentifier.find(".")) + "/" + mIdentifier.substring(mIdentifier.find(".")+1, null); if (Globals.debug) { System.println("URL=" + url); System.println("mIdentifier=" + mIdentifier); diff --git a/source/HomeAssistantToggleMenuItem.mc b/source/HomeAssistantToggleMenuItem.mc index 342a9e1..9e2452a 100644 --- a/source/HomeAssistantToggleMenuItem.mc +++ b/source/HomeAssistantToggleMenuItem.mc @@ -1,14 +1,32 @@ -import Toybox.Lang; -import Toybox.WatchUi; -import Toybox.Graphics; +//----------------------------------------------------------------------------------- +// +// Distributed under MIT Licence +// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. +// +//----------------------------------------------------------------------------------- +// +// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely +// tested on a Venu 2 device. The source code is provided at: +// https://github.com/house-of-abbey/GarminHomeAssistant. +// +// P A Abbey & J D Abbey, 31 October 2023 +// +// +// Description: +// +// Light or switch toggle button that calls the API to maintain the up to date state. +// +//----------------------------------------------------------------------------------- + +using Toybox.Lang; +using Toybox.WatchUi; +using Toybox.Graphics; using Toybox.Application.Properties; class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { hidden var api_key = Properties.getValue("api_key"); - hidden var menu; function initialize( - menu as HomeAssistantView, label as Lang.String or Lang.Symbol, subLabel as Lang.String or Lang.Symbol or { :enabled as Lang.String or Lang.Symbol or Null, @@ -17,23 +35,23 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { identifier, enabled as Lang.Boolean, options as { - :alignment as MenuItem.Alignment, + :alignment as WatchUi.MenuItem.Alignment, :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol } or Null ) { WatchUi.ToggleMenuItem.initialize(label, subLabel, identifier, enabled, options); api_key = Properties.getValue("api_key"); - self.menu = menu; } private function setUiToggle(state as Null or Lang.String) as Void { if (state != null) { if (state.equals("on") && !isEnabled()) { setEnabled(true); + WatchUi.requestUpdate(); } else if (state.equals("off") && isEnabled()) { setEnabled(false); + WatchUi.requestUpdate(); } - WatchUi.requestUpdate(); } } @@ -65,7 +83,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON }; if (System.getDeviceSettings().phoneConnected && System.getDeviceSettings().connectionAvailable) { - var url = Globals.getApiUrl() + "/states/" + mIdentifier; + var url = Properties.getValue("api_url") + "/states/" + mIdentifier; if (Globals.debug) { System.println("URL=" + url); } @@ -116,9 +134,9 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { if (System.getDeviceSettings().phoneConnected && System.getDeviceSettings().connectionAvailable) { var url; if (s) { - url = Globals.getApiUrl() + "/services/" + mIdentifier.substring(0, mIdentifier.find(".")) + "/turn_on"; + url = Properties.getValue("api_url") + "/services/" + mIdentifier.substring(0, mIdentifier.find(".")) + "/turn_on"; } else { - url = Globals.getApiUrl() + "/services/" + mIdentifier.substring(0, mIdentifier.find(".")) + "/turn_off"; + url = Properties.getValue("api_url") + "/services/" + mIdentifier.substring(0, mIdentifier.find(".")) + "/turn_off"; } if (Globals.debug) { System.println("URL=" + url); diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc index 6de07a4..a84a04f 100644 --- a/source/HomeAssistantView.mc +++ b/source/HomeAssistantView.mc @@ -1,93 +1,89 @@ -import Toybox.Lang; -import Toybox.Graphics; -import Toybox.WatchUi; +//----------------------------------------------------------------------------------- +// +// Distributed under MIT Licence +// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. +// +//----------------------------------------------------------------------------------- +// +// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely +// tested on a Venu 2 device. The source code is provided at: +// https://github.com/house-of-abbey/GarminHomeAssistant. +// +// P A Abbey & J D Abbey, 31 October 2023 +// +// +// Description: +// +// Home Assistant menu construction. +// +//----------------------------------------------------------------------------------- + +using Toybox.Lang; +using Toybox.Graphics; +using Toybox.WatchUi; class HomeAssistantView extends WatchUi.Menu2 { - hidden var timer; - - function initialize() { - timer = new Timer.Timer(); + function initialize( + definition as Lang.Dictionary, + options as { + :focus as Lang.Number, + :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol, + :theme as WatchUi.MenuTheme or Null + } or Null + ) { var toggle_obj = { :enabled => "On", :disabled => "Off" }; - WatchUi.Menu2.initialize({ - :title => "Entities" - }); - addItem( - new HomeAssistantToggleMenuItem( - self, - "Bedroom Light", - toggle_obj, - "light.philip_s_bedside_light_switch", - false, - null - ) - ); - addItem( - new HomeAssistantToggleMenuItem( - self, - "Lounge Lights", - toggle_obj, - "light.living_room_ambient_lights_all", - false, - null - ) - ); - addItem( - new HomeAssistantMenuItem( - "Food is Ready!", - null, - "script.food_is_ready", - null - ) - ); - // addItem( - // new HomeAssistantMenuItem( - // "Test Script", - // null, - // "script.test", - // null - // ) - // ); - addItem( - new HomeAssistantToggleMenuItem( - self, - "Bookcase USBs", - toggle_obj, - "switch.bookcase_usbs", - false, - null - ) - ); - addItem( - new HomeAssistantToggleMenuItem( - self, - "Corner Table USBs", - toggle_obj, - "switch.corner_table_usbs", - false, - null - ) - ); - } + if (options == null) { + options = { + :title => definition.get("title") as Lang.String + }; + } else { + options.put(:title, definition.get("title") as Lang.String); + } + WatchUi.Menu2.initialize(options); - // Load your resources here - function onLayout(dc as Dc) as Void { - setLayout(Rez.Layouts.MainLayout(dc)); + var items = definition.get("items") as Lang.Dictionary; + for(var i = 0; i < items.size(); i++) { + var type = items[i].get("type") as Lang.String or Null; + var name = items[i].get("name") as Lang.String or Null; + var entity = items[i].get("entity") as Lang.String or Null; + if (type != null && name != null && entity != null) { + if (type.equals("toggle")) { + addItem( + new HomeAssistantToggleMenuItem( + name, + toggle_obj, + entity, + false, + null + ) + ); + } else if (type.equals("tap")) { + addItem( + new HomeAssistantMenuItem( + name, + "Tap", + entity, + null + ) + ); + } else if (type.equals("group")) { + addItem( + new HomeAssistantViewMenuItem(items[i]) + ); + } + } + } } // Called when this View is brought to the foreground. Restore // the state of this View and prepare it to be shown. This includes // loading resources into memory. function onShow() as Void { - timer.start( - method(:timerUpdate), - Globals.updateInterval * 1000, - true - ); for(var i = 0; i < mItems.size(); i++) { if (mItems[i] instanceof HomeAssistantToggleMenuItem) { var toggleItem = mItems[i] as HomeAssistantToggleMenuItem; @@ -99,26 +95,20 @@ class HomeAssistantView extends WatchUi.Menu2 { } } - // Update the view - function onUpdate(dc as Dc) as Void { - View.onUpdate(dc); - } - - // Called when this View is removed from the screen. Save the - // state of this View here. This includes freeing resources from - // memory. - function onHide() as Void { - timer.stop(); - } - - function timerUpdate() as Void { + function stateUpdate() as Void { for(var i = 0; i < mItems.size(); i++) { if (mItems[i] instanceof HomeAssistantToggleMenuItem) { var toggleItem = mItems[i] as HomeAssistantToggleMenuItem; toggleItem.getState(); if (Globals.debug) { - System.println("HomeAssistantView Note: " + toggleItem.getLabel() + " ID=" + toggleItem.getId() + " Enabled=" + toggleItem.isEnabled()); + System.println("HomeAssistantView Toggle stateUpdate: " + toggleItem.getLabel() + " ID=" + toggleItem.getId() + " Enabled=" + toggleItem.isEnabled()); } + } else if (mItems[i] instanceof HomeAssistantViewMenuItem) { + var menu = mItems[i] as HomeAssistantViewMenuItem; + if (Globals.debug) { + System.println("HomeAssistantView Menu stateUpdate: " + menu.getLabel() + " ID=" + menu.getId()); + } + menu.getMenuView().stateUpdate(); } } } @@ -144,6 +134,13 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate { System.println(haItem.getLabel() + " " + haItem.getId()); } haItem.execScript(); + } else if (item instanceof HomeAssistantViewMenuItem) { + var haMenuItem = item as HomeAssistantViewMenuItem; + if (Globals.debug) { + System.println("Menu: " + haMenuItem.getLabel() + " " + haMenuItem.getId()); + } + // No delegate state to be amended, so re-use 'self'. + WatchUi.pushView(haMenuItem.getMenuView(), self, WatchUi.SLIDE_LEFT); } else { if (Globals.debug) { System.println(item.getLabel() + " " + item.getId()); @@ -151,4 +148,16 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate { } } + function onSwipe(swipeEvent) as Lang.Boolean { + switch (swipeEvent.getDirection()) { + case WatchUi.SWIPE_RIGHT: + WatchUi.popView(WatchUi.SLIDE_RIGHT); + break; + + default: + // Do nothing + break; + } + return true; + } } \ No newline at end of file diff --git a/source/HomeAssistantViewMenuItem.mc b/source/HomeAssistantViewMenuItem.mc new file mode 100644 index 0000000..39b72c3 --- /dev/null +++ b/source/HomeAssistantViewMenuItem.mc @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------------- +// +// Distributed under MIT Licence +// See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. +// +//----------------------------------------------------------------------------------- +// +// GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely +// tested on a Venu 2 device. The source code is provided at: +// https://github.com/house-of-abbey/GarminHomeAssistant. +// +// P A Abbey & J D Abbey, 31 October 2023 +// +// +// Description: +// +// Menu button that opens a sub-menu. +// +//----------------------------------------------------------------------------------- + +using Toybox.Lang; +using Toybox.WatchUi; + +class HomeAssistantViewMenuItem extends WatchUi.MenuItem { + hidden var menu as HomeAssistantView; + + function initialize(definition as Lang.Dictionary) { + // definitions.get(...) are Strings here as they have been checked by HomeAssistantView first + WatchUi.MenuItem.initialize( + definition.get("name") as Lang.String, + "Menu", + definition.get("entity") as Lang.String, + null + ); + + menu = new HomeAssistantView(definition, null); + } + + function getMenuView() as HomeAssistantView { + return menu; + } + +}