mirror of
				https://github.com/house-of-abbey/GarminHomeAssistant.git
				synced 2025-10-31 15:48:13 +00:00 
			
		
		
		
	Added numeric Menu Item
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -7,3 +7,5 @@ Thumbs.db | |||||||
| source/ClientId.mc | source/ClientId.mc | ||||||
| # Gemini API key for automated translations | # Gemini API key for automated translations | ||||||
| gemini_api_key.txt | gemini_api_key.txt | ||||||
|  | # URLs ans settings modified for testing, so don't sync | ||||||
|  | sourc/Settings.mc | ||||||
							
								
								
									
										8
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							| @@ -4,14 +4,6 @@ | |||||||
|   // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |   // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||||
|   "version": "0.2.0", |   "version": "0.2.0", | ||||||
|   "configurations": [ |   "configurations": [ | ||||||
|     { |  | ||||||
|       "name": "Python: Current File", |  | ||||||
|       "type": "python", |  | ||||||
|       "request": "launch", |  | ||||||
|       "program": "${file}", |  | ||||||
|       "console": "integratedTerminal", |  | ||||||
|       "justMyCode": true |  | ||||||
|     }, |  | ||||||
|     { |     { | ||||||
|       "type": "monkeyc", |       "type": "monkeyc", | ||||||
|       "request": "launch", |       "request": "launch", | ||||||
|   | |||||||
							
								
								
									
										244
									
								
								manifest.xml
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								manifest.xml
									
									
									
									
									
								
							| @@ -20,211 +20,77 @@ | |||||||
|  |  | ||||||
| --> | --> | ||||||
| <iq:manifest version="3" xmlns:iq="http://www.garmin.com/xml/connectiq"> | <iq:manifest version="3" xmlns:iq="http://www.garmin.com/xml/connectiq"> | ||||||
|   <!-- |     <!-- | ||||||
|     Use "Monkey C: Edit Application" from the Visual Studio Code command palette |     Use "Monkey C: Edit Application" from the Visual Studio Code command palette | ||||||
|     to update the application attributes. |     to update the application attributes. | ||||||
|   --> |   --> | ||||||
|   <iq:application id="98c36259-498a-4458-9cef-74a273ad2bc3" type="watch-app" name="@Strings.AppName" entry="HomeAssistantApp" launcherIcon="@Drawables.LauncherIcon" minApiLevel="3.1.0"> |     <iq:application id="a9077d22-5b9c-4a2e-b4ff-7846f77b13cb" type="watch-app" name="@Strings.AppName" entry="HomeAssistantApp" launcherIcon="@Drawables.LauncherIcon" minApiLevel="3.1.0"> | ||||||
|     <!-- |         <!-- | ||||||
|       Use the following from the Visual Studio Code command palette to edit |       Use the following from the Visual Studio Code command palette to edit | ||||||
|       the build targets: |       the build targets: | ||||||
|       "Monkey C: Set Products by Product Category" - Lets you add all products |       "Monkey C: Set Products by Product Category" - Lets you add all products | ||||||
|                                   that belong to the same product category |                                   that belong to the same product category | ||||||
|       "Monkey C: Edit Products" - Lets you add or remove any product |       "Monkey C: Edit Products" - Lets you add or remove any product | ||||||
|     --> |     --> | ||||||
|     <iq:products> |         <iq:products> | ||||||
|       <iq:product id="approachs50"/> |             <iq:product id="epix2pro51mm"/> | ||||||
|       <iq:product id="approachs7042mm"/> |         </iq:products> | ||||||
|       <iq:product id="approachs7047mm"/> |         <!-- | ||||||
|       <iq:product id="d2air"/> |  | ||||||
|       <iq:product id="d2airx10"/> |  | ||||||
|       <iq:product id="d2delta"/> |  | ||||||
|       <iq:product id="d2deltapx"/> |  | ||||||
|       <iq:product id="d2deltas"/> |  | ||||||
|       <iq:product id="d2mach1"/> |  | ||||||
|       <iq:product id="descentg1"/> |  | ||||||
|       <iq:product id="descentg2"/> |  | ||||||
|       <iq:product id="descentmk1"/> |  | ||||||
|       <iq:product id="descentmk2"/> |  | ||||||
|       <iq:product id="descentmk2s"/> |  | ||||||
|       <iq:product id="descentmk343mm"/> |  | ||||||
|       <iq:product id="descentmk351mm"/> |  | ||||||
|       <iq:product id="edge1030"/> |  | ||||||
|       <iq:product id="edge1030bontrager"/> |  | ||||||
|       <iq:product id="edge1030plus"/> |  | ||||||
|       <iq:product id="edge1040"/> |  | ||||||
|       <iq:product id="edge1050"/> |  | ||||||
|       <iq:product id="edge520plus"/> |  | ||||||
|       <iq:product id="edge530"/> |  | ||||||
|       <iq:product id="edge540"/> |  | ||||||
|       <iq:product id="edge550"/> |  | ||||||
|       <iq:product id="edge820"/> |  | ||||||
|       <iq:product id="edge830"/> |  | ||||||
|       <iq:product id="edge840"/> |  | ||||||
|       <iq:product id="edge850"/> |  | ||||||
|       <iq:product id="edgeexplore"/> |  | ||||||
|       <iq:product id="edgeexplore2"/> |  | ||||||
|       <iq:product id="edgemtb"/> |  | ||||||
|       <iq:product id="enduro"/> |  | ||||||
|       <iq:product id="enduro3"/> |  | ||||||
|       <iq:product id="epix2"/> |  | ||||||
|       <iq:product id="epix2pro42mm"/> |  | ||||||
|       <iq:product id="epix2pro47mm"/> |  | ||||||
|       <iq:product id="epix2pro51mm"/> |  | ||||||
|       <iq:product id="fenix5"/> |  | ||||||
|       <iq:product id="fenix5plus"/> |  | ||||||
|       <iq:product id="fenix5s"/> |  | ||||||
|       <iq:product id="fenix5splus"/> |  | ||||||
|       <iq:product id="fenix5x"/> |  | ||||||
|       <iq:product id="fenix5xplus"/> |  | ||||||
|       <iq:product id="fenix6"/> |  | ||||||
|       <iq:product id="fenix6pro"/> |  | ||||||
|       <iq:product id="fenix6s"/> |  | ||||||
|       <iq:product id="fenix6spro"/> |  | ||||||
|       <iq:product id="fenix6xpro"/> |  | ||||||
|       <iq:product id="fenix7"/> |  | ||||||
|       <iq:product id="fenix7pro"/> |  | ||||||
|       <iq:product id="fenix7pronowifi"/> |  | ||||||
|       <iq:product id="fenix7s"/> |  | ||||||
|       <iq:product id="fenix7spro"/> |  | ||||||
|       <iq:product id="fenix7x"/> |  | ||||||
|       <iq:product id="fenix7xpro"/> |  | ||||||
|       <iq:product id="fenix7xpronowifi"/> |  | ||||||
|       <iq:product id="fenix843mm"/> |  | ||||||
|       <iq:product id="fenix847mm"/> |  | ||||||
|       <iq:product id="fenix8pro47mm"/> |  | ||||||
|       <iq:product id="fenix8solar47mm"/> |  | ||||||
|       <iq:product id="fenix8solar51mm"/> |  | ||||||
|       <iq:product id="fenixchronos"/> |  | ||||||
|       <iq:product id="fenixe"/> |  | ||||||
|       <iq:product id="fr165"/> |  | ||||||
|       <iq:product id="fr165m"/> |  | ||||||
|       <iq:product id="fr245"/> |  | ||||||
|       <iq:product id="fr245m"/> |  | ||||||
|       <iq:product id="fr255"/> |  | ||||||
|       <iq:product id="fr255m"/> |  | ||||||
|       <iq:product id="fr255s"/> |  | ||||||
|       <iq:product id="fr255sm"/> |  | ||||||
|       <iq:product id="fr265"/> |  | ||||||
|       <iq:product id="fr265s"/> |  | ||||||
|       <iq:product id="fr55"/> |  | ||||||
|       <iq:product id="fr57042mm"/> |  | ||||||
|       <iq:product id="fr57047mm"/> |  | ||||||
|       <iq:product id="fr645"/> |  | ||||||
|       <iq:product id="fr645m"/> |  | ||||||
|       <iq:product id="fr745"/> |  | ||||||
|       <iq:product id="fr935"/> |  | ||||||
|       <iq:product id="fr945"/> |  | ||||||
|       <iq:product id="fr945lte"/> |  | ||||||
|       <iq:product id="fr955"/> |  | ||||||
|       <iq:product id="fr965"/> |  | ||||||
|       <iq:product id="fr970"/> |  | ||||||
|       <iq:product id="gpsmap66"/> |  | ||||||
|       <iq:product id="gpsmap67"/> |  | ||||||
|       <iq:product id="gpsmaph1"/> |  | ||||||
|       <iq:product id="instinct2"/> |  | ||||||
|       <iq:product id="instinct2s"/> |  | ||||||
|       <iq:product id="instinct2x"/> |  | ||||||
|       <iq:product id="instinct3amoled45mm"/> |  | ||||||
|       <iq:product id="instinct3amoled50mm"/> |  | ||||||
|       <iq:product id="instinct3solar45mm"/> |  | ||||||
|       <iq:product id="instinctcrossover"/> |  | ||||||
|       <iq:product id="instinctcrossoveramoled"/> |  | ||||||
|       <iq:product id="instincte40mm"/> |  | ||||||
|       <iq:product id="instincte45mm"/> |  | ||||||
|       <iq:product id="legacyherocaptainmarvel"/> |  | ||||||
|       <iq:product id="legacyherofirstavenger"/> |  | ||||||
|       <iq:product id="legacysagadarthvader"/> |  | ||||||
|       <iq:product id="legacysagarey"/> |  | ||||||
|       <iq:product id="marq2"/> |  | ||||||
|       <iq:product id="marq2aviator"/> |  | ||||||
|       <iq:product id="marqadventurer"/> |  | ||||||
|       <iq:product id="marqathlete"/> |  | ||||||
|       <iq:product id="marqaviator"/> |  | ||||||
|       <iq:product id="marqcaptain"/> |  | ||||||
|       <iq:product id="marqcommander"/> |  | ||||||
|       <iq:product id="marqdriver"/> |  | ||||||
|       <iq:product id="marqexpedition"/> |  | ||||||
|       <iq:product id="marqgolfer"/> |  | ||||||
|       <iq:product id="montana7xx"/> |  | ||||||
|       <iq:product id="venu"/> |  | ||||||
|       <iq:product id="venu2"/> |  | ||||||
|       <iq:product id="venu2plus"/> |  | ||||||
|       <iq:product id="venu2s"/> |  | ||||||
|       <iq:product id="venu3"/> |  | ||||||
|       <iq:product id="venu3s"/> |  | ||||||
|       <iq:product id="venu441mm"/> |  | ||||||
|       <iq:product id="venu445mm"/> |  | ||||||
|       <iq:product id="venud"/> |  | ||||||
|       <iq:product id="venusq"/> |  | ||||||
|       <iq:product id="venusq2"/> |  | ||||||
|       <iq:product id="venusq2m"/> |  | ||||||
|       <iq:product id="venusqm"/> |  | ||||||
|       <iq:product id="venux1"/> |  | ||||||
|       <iq:product id="vivoactive3"/> |  | ||||||
|       <iq:product id="vivoactive3m"/> |  | ||||||
|       <iq:product id="vivoactive3mlte"/> |  | ||||||
|       <iq:product id="vivoactive4"/> |  | ||||||
|       <iq:product id="vivoactive4s"/> |  | ||||||
|       <iq:product id="vivoactive5"/> |  | ||||||
|       <iq:product id="vivoactive6"/> |  | ||||||
|     </iq:products> |  | ||||||
|     <!-- |  | ||||||
|       Use "Monkey C: Edit Permissions" from the Visual Studio Code command |       Use "Monkey C: Edit Permissions" from the Visual Studio Code command | ||||||
|       palette to update permissions. |       palette to update permissions. | ||||||
|     --> |     --> | ||||||
|     <iq:permissions> |         <iq:permissions> | ||||||
|       <iq:uses-permission id="Background"/> |             <iq:uses-permission id="Background"/> | ||||||
|       <iq:uses-permission id="BluetoothLowEnergy"/> |             <iq:uses-permission id="BluetoothLowEnergy"/> | ||||||
|       <iq:uses-permission id="Communications"/> |             <iq:uses-permission id="Communications"/> | ||||||
|       <iq:uses-permission id="Positioning"/> |             <iq:uses-permission id="Positioning"/> | ||||||
|     </iq:permissions> |         </iq:permissions> | ||||||
|     <!-- |         <!-- | ||||||
|       Use "Monkey C: Edit Languages" from the Visual Studio Code command |       Use "Monkey C: Edit Languages" from the Visual Studio Code command | ||||||
|       palette to edit your compatible language list. |       palette to edit your compatible language list. | ||||||
|     --> |     --> | ||||||
|     <iq:languages> |         <iq:languages> | ||||||
|       <iq:language>ara</iq:language> |             <iq:language>ara</iq:language> | ||||||
|       <iq:language>bul</iq:language> |             <iq:language>bul</iq:language> | ||||||
|       <iq:language>ces</iq:language> |             <iq:language>ces</iq:language> | ||||||
|       <iq:language>dan</iq:language> |             <iq:language>dan</iq:language> | ||||||
|       <iq:language>deu</iq:language> |             <iq:language>deu</iq:language> | ||||||
|       <iq:language>dut</iq:language> |             <iq:language>dut</iq:language> | ||||||
|       <iq:language>eng</iq:language> |             <iq:language>eng</iq:language> | ||||||
|       <iq:language>est</iq:language> |             <iq:language>est</iq:language> | ||||||
|       <iq:language>fin</iq:language> |             <iq:language>fin</iq:language> | ||||||
|       <iq:language>fre</iq:language> |             <iq:language>fre</iq:language> | ||||||
|       <iq:language>gre</iq:language> |             <iq:language>gre</iq:language> | ||||||
|       <iq:language>heb</iq:language> |             <iq:language>heb</iq:language> | ||||||
|       <iq:language>hrv</iq:language> |             <iq:language>hrv</iq:language> | ||||||
|       <iq:language>hun</iq:language> |             <iq:language>hun</iq:language> | ||||||
|       <iq:language>ind</iq:language> |             <iq:language>ind</iq:language> | ||||||
|       <iq:language>ita</iq:language> |             <iq:language>ita</iq:language> | ||||||
|       <iq:language>jpn</iq:language> |             <iq:language>jpn</iq:language> | ||||||
|       <iq:language>kor</iq:language> |             <iq:language>kor</iq:language> | ||||||
|       <iq:language>lav</iq:language> |             <iq:language>lav</iq:language> | ||||||
|       <iq:language>lit</iq:language> |             <iq:language>lit</iq:language> | ||||||
|       <iq:language>nob</iq:language> |             <iq:language>nob</iq:language> | ||||||
|       <iq:language>pol</iq:language> |             <iq:language>pol</iq:language> | ||||||
|       <iq:language>por</iq:language> |             <iq:language>por</iq:language> | ||||||
|       <iq:language>ron</iq:language> |             <iq:language>ron</iq:language> | ||||||
|       <!-- <iq:language>rus</iq:language> --> |             <!-- <iq:language>rus</iq:language> --> | ||||||
|       <iq:language>slo</iq:language> |             <iq:language>slo</iq:language> | ||||||
|       <iq:language>slv</iq:language> |             <iq:language>slv</iq:language> | ||||||
|       <iq:language>spa</iq:language> |             <iq:language>spa</iq:language> | ||||||
|       <iq:language>swe</iq:language> |             <iq:language>swe</iq:language> | ||||||
|       <iq:language>tha</iq:language> |             <iq:language>tha</iq:language> | ||||||
|       <iq:language>tur</iq:language> |             <iq:language>tur</iq:language> | ||||||
|       <iq:language>ukr</iq:language> |             <iq:language>ukr</iq:language> | ||||||
|       <iq:language>vie</iq:language> |             <iq:language>vie</iq:language> | ||||||
|       <iq:language>zhs</iq:language> |             <iq:language>zhs</iq:language> | ||||||
|       <iq:language>zht</iq:language> |             <iq:language>zht</iq:language> | ||||||
|       <iq:language>zsm</iq:language> |             <iq:language>zsm</iq:language> | ||||||
|     </iq:languages> |         </iq:languages> | ||||||
|     <!-- |         <!-- | ||||||
|       Use "Monkey C: Configure Monkey Barrel" from the Visual Studio Code |       Use "Monkey C: Configure Monkey Barrel" from the Visual Studio Code | ||||||
|       command palette to edit the included barrels. |       command palette to edit the included barrels. | ||||||
|     --> |     --> | ||||||
|     <iq:barrels/> |         <iq:barrels/> | ||||||
|   </iq:application> |     </iq:application> | ||||||
| </iq:manifest> | </iq:manifest> | ||||||
| @@ -37,7 +37,7 @@ class HomeAssistantApp extends Application.AppBase { | |||||||
|     private var mGlanceTimer    as Timer.Timer?; |     private var mGlanceTimer    as Timer.Timer?; | ||||||
|     private var mUpdateTimer    as Timer.Timer?; |     private var mUpdateTimer    as Timer.Timer?; | ||||||
|     // Array initialised by onReturnFetchMenuConfig() |     // Array initialised by onReturnFetchMenuConfig() | ||||||
|     private var mItemsToUpdate  as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem>?; |     private var mItemsToUpdate  as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem or HomeAssistantNumericMenuItem>?; | ||||||
|     private var mIsApp          as Lang.Boolean     = false; // Or Widget |     private var mIsApp          as Lang.Boolean     = false; // Or Widget | ||||||
|     private var mUpdating       as Lang.Boolean     = false; // Don't start a second chain of updates |     private var mUpdating       as Lang.Boolean     = false; // Don't start a second chain of updates | ||||||
|     private var mTemplates      as Lang.Dictionary? = null;  // Cache of compiled templates |     private var mTemplates      as Lang.Dictionary? = null;  // Cache of compiled templates | ||||||
|   | |||||||
| @@ -148,7 +148,48 @@ class HomeAssistantMenuItemFactory { | |||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     //! Numeric menu item. | ||||||
|  |     //! | ||||||
|  |     //! @param definition Items array from the JSON that defines this sub menu. | ||||||
|  |     //! @param template   Template for Home Assistant to render (optional) | ||||||
|  |     // | ||||||
|  |     function numeric( | ||||||
|  |         label     as Lang.String or Lang.Symbol, | ||||||
|  |         entity_id as Lang.String?, | ||||||
|  |         template  as Lang.String?, | ||||||
|  |         service   as Lang.String?, | ||||||
|  |         data      as Lang.Dictionary?, | ||||||
|  |         options   as { | ||||||
|  |             :exit    as Lang.Boolean, | ||||||
|  |             :confirm as Lang.Boolean, | ||||||
|  |             :pin     as Lang.Boolean, | ||||||
|  |             :icon    as WatchUi.Bitmap | ||||||
|  |         } | ||||||
|  |     ) as WatchUi.MenuItem { | ||||||
|  |         if (entity_id != null) { | ||||||
|  |             if (data == null) { | ||||||
|  |                 data = { "entity_id" => entity_id }; | ||||||
|                  |                  | ||||||
|  |             } else { | ||||||
|  |                 data.put("entity_id", entity_id); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         var keys = mMenuItemOptions.keys(); | ||||||
|  |         for (var i = 0; i < keys.size(); i++) { | ||||||
|  |             options.put(keys[i], mMenuItemOptions.get(keys[i])); | ||||||
|  |         } | ||||||
|  |         options.put(:icon, mTapTypeIcon);     | ||||||
|  |          | ||||||
|  |         return new HomeAssistantNumericMenuItem( | ||||||
|  |             label, | ||||||
|  |             entity_id, | ||||||
|  |             template, | ||||||
|  |             service, | ||||||
|  |             data, | ||||||
|  |             options, | ||||||
|  |             mHomeAssistantService | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|     //! Group menu item. |     //! Group menu item. | ||||||
|     //! |     //! | ||||||
|     //! @param definition Items array from the JSON that defines this sub menu. |     //! @param definition Items array from the JSON that defines this sub menu. | ||||||
|   | |||||||
							
								
								
									
										231
									
								
								source/HomeAssistantNumericMenuItem.mc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								source/HomeAssistantNumericMenuItem.mc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | |||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // 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 & Someone0nEarth, 31 October 2023 | ||||||
|  | // | ||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | using Toybox.Lang; | ||||||
|  | using Toybox.WatchUi; | ||||||
|  | using Toybox.Graphics; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! Menu button with an icon that opens a sub-menu, i.e. group, and optionally renders | ||||||
|  | //! a Home Assistant Template. | ||||||
|  | // | ||||||
|  | class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | ||||||
|  |     private var mHomeAssistantService as HomeAssistantService?; | ||||||
|  |     private var mService              as Lang.String?; | ||||||
|  |     private var mConfirm              as Lang.Boolean; | ||||||
|  |     private var mExit                 as Lang.Boolean; | ||||||
|  |     private var mPin                  as Lang.Boolean; | ||||||
|  |     private var mData                 as Lang.Dictionary?; | ||||||
|  |     private var mStep                 as Lang.Float=1.0; | ||||||
|  |     private var mValueChanged         as Lang.Boolean = false; | ||||||
|  |     private var mValue                as Lang.Float?;   | ||||||
|  |     private var mEntity               as Lang.String?; | ||||||
|  |     private var mFormatString         as Lang.String="%.1f"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     //! Class Constructor | ||||||
|  |     //! | ||||||
|  |     //! @param label     Menu item label. | ||||||
|  |     //! @param template  Menu item template. | ||||||
|  |     //! @param service   Menu item service. | ||||||
|  |     //! @param data      Data to supply to the service call. | ||||||
|  |     //! @param exit      Should the service call complete and then exit? | ||||||
|  |     //! @param confirm   Should the service call be confirmed to avoid accidental invocation? | ||||||
|  |     //! @param pin       Should the service call be protected with a PIN for some low level of security? | ||||||
|  |     //! @param icon      Icon to use for the menu item. | ||||||
|  |     //! @param options   Menu item options to be passed on, including both SDK and menu options, e.g. exit, confirm & pin. | ||||||
|  |     //! @param haService Shared Home Assistant service object that will perform the required call. Only | ||||||
|  |     //!                  one of these objects is created for all menu items to re-use. | ||||||
|  |     // | ||||||
|  |     function initialize( | ||||||
|  |         label     as Lang.String or Lang.Symbol, | ||||||
|  |         entity    as Lang.String, | ||||||
|  |         template  as Lang.String, | ||||||
|  |         service   as Lang.String?, | ||||||
|  |         data      as Lang.Dictionary?, | ||||||
|  |         options   as { | ||||||
|  |             :alignment as WatchUi.MenuItem.Alignment, | ||||||
|  |             :icon      as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol, | ||||||
|  |             :exit      as Lang.Boolean, | ||||||
|  |             :confirm   as Lang.Boolean, | ||||||
|  |             :pin       as Lang.Boolean | ||||||
|  |         }?, | ||||||
|  |         haService as HomeAssistantService | ||||||
|  |     ) { | ||||||
|  |         mService              = service; | ||||||
|  |         mData                 = data; | ||||||
|  |         mExit                 = options[:exit]; | ||||||
|  |         mConfirm              = options[:confirm]; | ||||||
|  |         mPin                  = options[:pin]; | ||||||
|  |         mLabel                = label; | ||||||
|  |         mHomeAssistantService = haService; | ||||||
|  |         mEntity               = entity; | ||||||
|  |  | ||||||
|  |         HomeAssistantMenuItem.initialize( | ||||||
|  |             label, | ||||||
|  |             template, | ||||||
|  |             { | ||||||
|  |                 :alignment => options[:alignment], | ||||||
|  |                 :icon      => options[:icon] | ||||||
|  |             }  | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |        | ||||||
|  |         if  (mData.get("step") != null) { | ||||||
|  |             mStep = mData.get("step").toString().toFloat(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (mData.get("formatString") != null) { | ||||||
|  |             mFormatString=mData.get("formatString").toString(); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     function callService() as Void { | ||||||
|  |         if (!mValueChanged) { return; } | ||||||
|  |         var hasTouchScreen = System.getDeviceSettings().isTouchScreen; | ||||||
|  |         if (mPin && hasTouchScreen) { | ||||||
|  |             var pin = Settings.getPin(); | ||||||
|  |             if (pin != null) { | ||||||
|  |                 var pinConfirmationView = new HomeAssistantPinConfirmationView(); | ||||||
|  |                 WatchUi.pushView( | ||||||
|  |                     pinConfirmationView, | ||||||
|  |                     new HomeAssistantPinConfirmationDelegate({ | ||||||
|  |                         :callback    => method(:onConfirm), | ||||||
|  |                         :pin         => pin,  | ||||||
|  |                         :state       => false, | ||||||
|  |                         :view        => pinConfirmationView, | ||||||
|  |                     }), | ||||||
|  |                     WatchUi.SLIDE_IMMEDIATE | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |         } else if (mConfirm) { | ||||||
|  |             if ((! System.getDeviceSettings().phoneConnected || | ||||||
|  |                  ! System.getDeviceSettings().connectionAvailable) && | ||||||
|  |                 Settings.getWifiLteExecutionEnabled()) { | ||||||
|  |                 var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String; | ||||||
|  |                 var dialog = new WatchUi.Confirmation(dialogMsg); | ||||||
|  |                 WatchUi.pushView( | ||||||
|  |                     dialog, | ||||||
|  |                     new WifiLteExecutionConfirmDelegate({ | ||||||
|  |                         :type    => "service", | ||||||
|  |                         :service => mService, | ||||||
|  |                         :data    => mData, | ||||||
|  |                         :exit    => mExit, | ||||||
|  |                     }, dialog), | ||||||
|  |                     WatchUi.SLIDE_LEFT | ||||||
|  |                 ); | ||||||
|  |             } else { | ||||||
|  |                 var view = new HomeAssistantConfirmation(); | ||||||
|  |                 WatchUi.pushView( | ||||||
|  |                     view, | ||||||
|  |                     new HomeAssistantConfirmationDelegate({ | ||||||
|  |                         :callback         => method(:onConfirm), | ||||||
|  |                         :confirmationView => view, | ||||||
|  |                         :state            => false, | ||||||
|  |                     }), | ||||||
|  |                     WatchUi.SLIDE_IMMEDIATE | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             onConfirm(false); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |  | ||||||
|  |     //! Callback function after the menu items selection has been (optionally) confirmed. | ||||||
|  |     //! | ||||||
|  |     //! @param b Ignored. It is included in order to match the expected function prototype of the callback method. | ||||||
|  |     // | ||||||
|  |     function onConfirm(b as Lang.Boolean) as Void { | ||||||
|  |         if (mService != null) { | ||||||
|  |             mHomeAssistantService.call(mService, {"entity_id"  => mEntity,mData.get("valueLabel").toString() => mValue}, mExit); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     ///! Increase value when Up button is pressed or touch screen swipe down  | ||||||
|  |  | ||||||
|  |     function increaseValue() as Void { | ||||||
|  |         if (mValueChanged) | ||||||
|  |         { | ||||||
|  |             mValue += mStep; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             mValue= getSubLabel().toFloat() + mStep; | ||||||
|  |             mValueChanged=true; | ||||||
|  |         } | ||||||
|  |         setSubLabel(mValue.format(mFormatString)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ///! Decrease value when Down button is pressed or touch screen swipe up | ||||||
|  |     function decreaseValue() as Void { | ||||||
|  |         if (mValueChanged) | ||||||
|  |         { | ||||||
|  |             mValue -= mStep; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             mValue= getSubLabel().toFloat() - mStep; | ||||||
|  |             mValueChanged=true; | ||||||
|  |         } | ||||||
|  |         setSubLabel(mValue.format(mFormatString)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Update the menu item's sub label to display the template rendered by Home Assistant. | ||||||
|  |     //! | ||||||
|  |     //! @param data The rendered template (typically a string) to be placed in the sub label. This may | ||||||
|  |     //!             unusually be a number if the SDK interprets the JSON returned by Home Assistant as such. | ||||||
|  |     // | ||||||
|  |     function updateState(data as Lang.String or Lang.Dictionary or Lang.Number or Lang.Float or Null) as Void { | ||||||
|  |         // If vlue has changed, don't use value from HomeAssitant but display target value | ||||||
|  |         if (mValueChanged) { | ||||||
|  |             setSubLabel(mValue.format(mFormatString)); | ||||||
|  |             WatchUi.requestUpdate(); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if (data == null) { | ||||||
|  |             setSubLabel($.Rez.Strings.Empty); | ||||||
|  |         } else if(data instanceof Lang.String) { | ||||||
|  |             setSubLabel(data); | ||||||
|  |         } else if(data instanceof Lang.Number) { | ||||||
|  |             var d = data as Lang.Number; | ||||||
|  |             setSubLabel(d.format("%d")); | ||||||
|  |         } else if(data instanceof Lang.Float) { | ||||||
|  |             var f = data as Lang.Float; | ||||||
|  |             setSubLabel(f.format(mFormatString)); | ||||||
|  |         } else if(data instanceof Lang.Dictionary) { | ||||||
|  |             // System.println("HomeAssistantMenuItem updateState() data = " + data); | ||||||
|  |             if (data.get("error") != null) { | ||||||
|  |                 setSubLabel($.Rez.Strings.TemplateError); | ||||||
|  |             } else { | ||||||
|  |                 setSubLabel($.Rez.Strings.PotentialError); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             // The template must return a Lang.String, Number or Float, or the item cannot be formatted locally without error. | ||||||
|  |             setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String); | ||||||
|  |         } | ||||||
|  |         WatchUi.requestUpdate(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Set the mValuChanged value. | ||||||
|  |     //! | ||||||
|  |     //! Can be used to reenable update of subLabel | ||||||
|  |     // | ||||||
|  |     function setValueChanged(b as Lang.Boolean) as Void { | ||||||
|  |         mValueChanged = b; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										212
									
								
								source/HomeAssistantNumericView.mc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								source/HomeAssistantNumericView.mc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,212 @@ | |||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // 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 & Someone0nEarth & moesterheld, 31 October 2023 | ||||||
|  | // | ||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | using Toybox.Application; | ||||||
|  | using Toybox.Lang; | ||||||
|  | using Toybox.Graphics; | ||||||
|  | using Toybox.System; | ||||||
|  | using Toybox.WatchUi; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | using Toybox.Application.Properties; | ||||||
|  | using Toybox.Timer; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! Home Assistant menu construction. | ||||||
|  | // | ||||||
|  | class HomeAssistantNumericView extends WatchUi.Menu2 { | ||||||
|  |  | ||||||
|  |     private var mMenuItem as HomeAssistantNumericMenuItem; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     //! Class Constructor | ||||||
|  |     // | ||||||
|  |     function initialize( | ||||||
|  |        menuItem as HomeAssistantNumericMenuItem | ||||||
|  |  | ||||||
|  |     ) { | ||||||
|  |         mMenuItem = menuItem;         | ||||||
|  |  | ||||||
|  |         WatchUi.Menu2.initialize({:title => mMenuItem.getLabel()}); | ||||||
|  |          | ||||||
|  |         addItem(mMenuItem); | ||||||
|  |  | ||||||
|  |         //updateState(mData); | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     //! Return the menu item | ||||||
|  |     //! | ||||||
|  |     //! @return A HomeAssitantTapMenuItem (or null). | ||||||
|  |     // | ||||||
|  |     function getMenuItem() as HomeAssistantNumericMenuItem? { | ||||||
|  |         return mMenuItem; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Update the menu item's sub label to display the template rendered by Home Assistant. | ||||||
|  |     //! | ||||||
|  |     //! @param data The rendered template (typically a string) to be placed in the sub label. This may | ||||||
|  |     //!             unusually be a number if the SDK interprets the JSON returned by Home Assistant as such. | ||||||
|  |     // | ||||||
|  |     function updateState(data as Lang.String or Lang.Dictionary or Lang.Number or Lang.Float or Null) as Void { | ||||||
|  |         if (data == null) { | ||||||
|  |             mMenuItem.setSubLabel($.Rez.Strings.Empty); | ||||||
|  |         } else if(data instanceof Lang.String) { | ||||||
|  |             mMenuItem.setSubLabel(data); | ||||||
|  |         } else if(data instanceof Lang.Number) { | ||||||
|  |             var d = data as Lang.Number; | ||||||
|  |             mMenuItem.setSubLabel(d.format("%d")); | ||||||
|  |         } else if(data instanceof Lang.Float) { | ||||||
|  |             var f = data as Lang.Float; | ||||||
|  |             mMenuItem.setSubLabel(f.format("%f")); | ||||||
|  |         } else if(data instanceof Lang.Dictionary) { | ||||||
|  |             // System.println("HomeAssistantMenuItem updateState() data = " + data); | ||||||
|  |             if (data.get("error") != null) { | ||||||
|  |                 mMenuItem.setSubLabel($.Rez.Strings.TemplateError); | ||||||
|  |             } else { | ||||||
|  |                 mMenuItem.setSubLabel($.Rez.Strings.PotentialError); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             // The template must return a Lang.String, Number or Float, or the item cannot be formatted locally without error. | ||||||
|  |             mMenuItem.setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String); | ||||||
|  |         } | ||||||
|  |         WatchUi.requestUpdate(); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |  | ||||||
|  |     //! Return a list of items that need to be updated within this menu structure. | ||||||
|  |     //! | ||||||
|  |     //! MN. Lang.Array.addAll() fails structural type checking without including "Null" in the return type | ||||||
|  |     //! | ||||||
|  |     //! @return An array of menu items that need to be updated periodically to reflect the latest Home Assistant state. | ||||||
|  |     // | ||||||
|  |     function getItemsToUpdate() as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem or Null> { | ||||||
|  |         var fullList = []; | ||||||
|  |         var lmi = mItems as Lang.Array<WatchUi.MenuItem>; | ||||||
|  |  | ||||||
|  |         for(var i = 0; i < mItems.size(); i++) { | ||||||
|  |             var item = lmi[i]; | ||||||
|  |             if (item instanceof HomeAssistantGroupMenuItem) { | ||||||
|  |                 // Group menu items can now have an optional template to evaluate | ||||||
|  |                 var gmi = item as HomeAssistantGroupMenuItem; | ||||||
|  |                 if (gmi.hasTemplate()) { | ||||||
|  |                     fullList.add(item); | ||||||
|  |                 } | ||||||
|  |                 fullList.addAll(item.getMenuView().getItemsToUpdate()); | ||||||
|  |             } else if (item instanceof HomeAssistantToggleMenuItem) { | ||||||
|  |                 fullList.add(item); | ||||||
|  |             } else if (item instanceof HomeAssistantTapMenuItem) { | ||||||
|  |                 var tmi = item as HomeAssistantTapMenuItem; | ||||||
|  |                 if (tmi.hasTemplate()) { | ||||||
|  |                     fullList.add(item); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return fullList; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     //! 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 {} | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //! Delegate for the HomeAssistantView. | ||||||
|  | //! | ||||||
|  | //! Reference: https://developer.garmin.com/connect-iq/core-topics/input-handling/ | ||||||
|  | // | ||||||
|  | class HomeAssistantNumericViewDelegate extends WatchUi.Menu2InputDelegate { | ||||||
|  |     private var mIsRootMenuView as Lang.Boolean = false; | ||||||
|  |     private var mTimer          as QuitTimer; | ||||||
|  |     private var mItem           as HomeAssistantNumericMenuItem; | ||||||
|  |  | ||||||
|  |     //! Class Constructor | ||||||
|  |     //! | ||||||
|  |     //! @param isRootMenuView As menus can be nested, this state marks the top level menu so that the | ||||||
|  |     //!                       back event can exit the application completely rather than just popping | ||||||
|  |     //!                       a menu view. | ||||||
|  |     //tap | ||||||
|  |     function initialize(isRootMenuView as Lang.Boolean, item as HomeAssistantNumericMenuItem) { | ||||||
|  |         Menu2InputDelegate.initialize(); | ||||||
|  |         mIsRootMenuView = isRootMenuView; | ||||||
|  |         mTimer          = getApp().getQuitTimer(); | ||||||
|  |         mItem           = item; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Handle the back button (ESC) | ||||||
|  |     // | ||||||
|  |     function onBack() { | ||||||
|  |         mTimer.reset(); | ||||||
|  |  | ||||||
|  |         mItem.setValueChanged(false); | ||||||
|  |  | ||||||
|  |         if (mIsRootMenuView) { | ||||||
|  |             // If its started from glance or as an activity, directly exit the widget/app | ||||||
|  |             // (on widgets without glance, this exit() won't do anything, | ||||||
|  |             // so the base view will be shown instead, through the popView below this "if body") | ||||||
|  |             System.exit(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Only for CheckboxMenu | ||||||
|  |     // | ||||||
|  |     function onDone() { | ||||||
|  |         mTimer.reset(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Only for CustomMenu | ||||||
|  |     // | ||||||
|  |     function onFooter() { | ||||||
|  |         mTimer.reset(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Decrease Value | ||||||
|  |     function onNextPage() as Lang.Boolean { | ||||||
|  |         mItem.decreaseValue(); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     //Increase Value | ||||||
|  |     function onPreviousPage() as Lang.Boolean { | ||||||
|  |         mItem.increaseValue(); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | ||||||
|  |     //! Select event | ||||||
|  |     //! | ||||||
|  |     //! @param item Selected menu item. | ||||||
|  |     // | ||||||
|  |     function onSelect(item as WatchUi.MenuItem) as Void { | ||||||
|  |         mTimer.reset(); | ||||||
|  |         mItem.callService(); | ||||||
|  |         WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Only for CustomMenu | ||||||
|  |     // | ||||||
|  |     function onTitle() { | ||||||
|  |         mTimer.reset(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -126,6 +126,19 @@ class HomeAssistantView extends WatchUi.Menu2 { | |||||||
|                                 } |                                 } | ||||||
|                             )); |                             )); | ||||||
|                         } |                         } | ||||||
|  |                     } else if (type.equals("numeric") && service != null) { | ||||||
|  |                         addItem(HomeAssistantMenuItemFactory.create().numeric( | ||||||
|  |                             name, | ||||||
|  |                             entity, | ||||||
|  |                             content, | ||||||
|  |                             service, | ||||||
|  |                             data, | ||||||
|  |                             { | ||||||
|  |                                 :exit    => exit, | ||||||
|  |                                 :confirm => confirm, | ||||||
|  |                                 :pin     => pin | ||||||
|  |                             } | ||||||
|  |                         ));    | ||||||
|                     } else if (type.equals("info") && content != null) { |                     } else if (type.equals("info") && content != null) { | ||||||
|                         // Cannot exit from a non-actionable information only menu item. |                         // Cannot exit from a non-actionable information only menu item. | ||||||
|                         addItem(HomeAssistantMenuItemFactory.create().tap( |                         addItem(HomeAssistantMenuItemFactory.create().tap( | ||||||
| @@ -154,7 +167,8 @@ class HomeAssistantView extends WatchUi.Menu2 { | |||||||
|     //! |     //! | ||||||
|     //! @return An array of menu items that need to be updated periodically to reflect the latest Home Assistant state. |     //! @return An array of menu items that need to be updated periodically to reflect the latest Home Assistant state. | ||||||
|     // |     // | ||||||
|     function getItemsToUpdate() as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem or Null> { |  | ||||||
|  |     function getItemsToUpdate() as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem  or HomeAssistantNumericMenuItem or Null> { | ||||||
|         var fullList = []; |         var fullList = []; | ||||||
|         var lmi = mItems as Lang.Array<WatchUi.MenuItem>; |         var lmi = mItems as Lang.Array<WatchUi.MenuItem>; | ||||||
|  |  | ||||||
| @@ -167,6 +181,12 @@ class HomeAssistantView extends WatchUi.Menu2 { | |||||||
|                     fullList.add(item); |                     fullList.add(item); | ||||||
|                 } |                 } | ||||||
|                 fullList.addAll(item.getMenuView().getItemsToUpdate()); |                 fullList.addAll(item.getMenuView().getItemsToUpdate()); | ||||||
|  |             } else if (item instanceof HomeAssistantNumericMenuItem) { | ||||||
|  |                 // Numeric items can have an optional template to evaluate | ||||||
|  |                 var nmi = item as HomeAssistantNumericMenuItem; | ||||||
|  |                 if (nmi.hasTemplate()) { | ||||||
|  |                     fullList.add(item); | ||||||
|  |                 } | ||||||
|             } else if (item instanceof HomeAssistantToggleMenuItem) { |             } else if (item instanceof HomeAssistantToggleMenuItem) { | ||||||
|                 fullList.add(item); |                 fullList.add(item); | ||||||
|             } else if (item instanceof HomeAssistantTapMenuItem) { |             } else if (item instanceof HomeAssistantTapMenuItem) { | ||||||
| @@ -248,6 +268,12 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate { | |||||||
|             var haItem = item as HomeAssistantTapMenuItem; |             var haItem = item as HomeAssistantTapMenuItem; | ||||||
|             // System.println(haItem.getLabel() + " " + haItem.getId()); |             // System.println(haItem.getLabel() + " " + haItem.getId()); | ||||||
|             haItem.callService(); |             haItem.callService(); | ||||||
|  |         } else if (item instanceof HomeAssistantNumericMenuItem) { | ||||||
|  |             var haItem = item as HomeAssistantNumericMenuItem; | ||||||
|  |             // System.println(haItem.getLabel() + " " + haItem.getId()); | ||||||
|  |             // create new view to select new valu | ||||||
|  |             var numView = new HomeAssistantNumericView(haItem); | ||||||
|  |             WatchUi.pushView(numView, new HomeAssistantNumericViewDelegate(false,haItem), WatchUi.SLIDE_LEFT); | ||||||
|         } else if (item instanceof HomeAssistantGroupMenuItem) { |         } else if (item instanceof HomeAssistantGroupMenuItem) { | ||||||
|             var haMenuItem = item as HomeAssistantGroupMenuItem; |             var haMenuItem = item as HomeAssistantGroupMenuItem; | ||||||
|             // System.println("IconMenu: " + haMenuItem.getLabel() + " " + haMenuItem.getId()); |             // System.println("IconMenu: " + haMenuItem.getLabel() + " " + haMenuItem.getId()); | ||||||
|   | |||||||
| @@ -29,10 +29,10 @@ using Toybox.Time; | |||||||
| // | // | ||||||
| (:glance, :background) | (:glance, :background) | ||||||
| class Settings { | class Settings { | ||||||
|     private static var mApiKey                as Lang.String? = ""; |     private static var mApiKey                as Lang.String? = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJlNThlZDk1MjIwMmU0MmYyOTVmODYyMGVjNDQwZDk1MCIsImlhdCI6MTc0MjkwNzc4MSwiZXhwIjoyMDU4MjY3NzgxfQ.kM8pXYPRADMrDGqmYYEloZH50avOWtCSzpoZbC0gze0"; | ||||||
|     private static var mWebhookId             as Lang.String? = ""; |     private static var mWebhookId             as Lang.String? = ""; | ||||||
|     private static var mApiUrl                as Lang.String? = ""; |     private static var mApiUrl                as Lang.String? = "https://homeassistant.michel.ruhr/api"; | ||||||
|     private static var mConfigUrl             as Lang.String? = ""; |     private static var mConfigUrl             as Lang.String? = "https://homeassistant.michel.ruhr/local/garmin-test.json"; | ||||||
|     private static var mCacheConfig           as Lang.Boolean = false; |     private static var mCacheConfig           as Lang.Boolean = false; | ||||||
|     private static var mClearCache            as Lang.Boolean = false; |     private static var mClearCache            as Lang.Boolean = false; | ||||||
|     private static var mMenuCheck             as Lang.Boolean = false; |     private static var mMenuCheck             as Lang.Boolean = false; | ||||||
| @@ -63,10 +63,10 @@ class Settings { | |||||||
|     // |     // | ||||||
|     static function update() { |     static function update() { | ||||||
|         mIsApp                 = getApp().getIsApp(); |         mIsApp                 = getApp().getIsApp(); | ||||||
|         mApiKey                = Properties.getValue("api_key"); |         //mApiKey                = Properties.getValue("api_key"); | ||||||
|         mWebhookId             = Properties.getValue("webhook_id"); |         mWebhookId             = Properties.getValue("webhook_id"); | ||||||
|         mApiUrl                = Properties.getValue("api_url"); |         //mApiUrl                = Properties.getValue("api_url"); | ||||||
|         mConfigUrl             = Properties.getValue("config_url"); |         //mConfigUrl             = Properties.getValue("config_url"); | ||||||
|         mCacheConfig           = Properties.getValue("cache_config"); |         mCacheConfig           = Properties.getValue("cache_config"); | ||||||
|         mClearCache            = Properties.getValue("clear_cache"); |         mClearCache            = Properties.getValue("clear_cache"); | ||||||
|         mMenuCheck             = Properties.getValue("enable_menu_update_check"); |         mMenuCheck             = Properties.getValue("enable_menu_update_check"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user