From 75ea23dfbd96e2ce12410e5e528dfb590c5ae81d Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Thu, 5 Sep 2024 21:23:49 +0100 Subject: [PATCH 1/3] 7 New devices, mainly Fenix SDK updated to 7.3.0 in order to get new devices to work in simulation. This means some function prototypes have had to be amended. --- README.md | 2 +- manifest.xml | 235 +++++++++++++------------ monkey.jungle | 22 ++- resources-icons-55/drawables.xml | 23 +++ resources-icons-55/error.svg | 1 + resources-icons-55/group_type.svg | 7 + resources-icons-55/info_type.svg | 1 + resources-icons-55/tap_type.svg | 1 + resources-launcher-68-68/drawables.xml | 17 ++ resources-launcher-68-68/launcher.svg | 4 + source/ErrorView.mc | 2 +- source/HomeAssistantApp.mc | 38 ++-- source/HomeAssistantView.mc | 3 +- source/WebhookManager.mc | 87 ++++----- 14 files changed, 261 insertions(+), 182 deletions(-) create mode 100644 resources-icons-55/drawables.xml create mode 100644 resources-icons-55/error.svg create mode 100644 resources-icons-55/group_type.svg create mode 100644 resources-icons-55/info_type.svg create mode 100644 resources-icons-55/tap_type.svg create mode 100644 resources-launcher-68-68/drawables.xml create mode 100644 resources-launcher-68-68/launcher.svg diff --git a/README.md b/README.md index 29f2d8b..af99dc5 100644 --- a/README.md +++ b/README.md @@ -321,6 +321,6 @@ The `id` attribute values are taken from the same names used in [`strings.xml`]( 5. Parameters to tap menu items cannot have their parameter usage verified. If you get this wrong and crash the application, that's your fault not the application's. In this case, start by removing the parameters for the menu item causing the crash, and add them back one at a time until you find your fault. **Please don't give the application a poor review for your bad parameter definition!** -6. We are unable to support Edge 540 and Edge 840 devices at this time. The simulation of both these devices has two unexpected errors when toggling or executing taps. We get both `Communications.NETWORK_RESPONSE_OUT_OF_MEMORY` and `Communications.BLE_QUEUE_FULL` even though the memory usage is about 6% of the available RAM. Based on a lead from user @Petucky, both devices are being re-enabled as testing on a real Edge 840 device has proven successful, however we remain unable to support either devices until the simulator is fixed. +6. We are unable to support Edge 540, Edge 840 and Edge 1050 devices at this time. The simulation of these devices has two unexpected errors when toggling or executing taps. We get both `Communications.NETWORK_RESPONSE_OUT_OF_MEMORY` and `Communications.BLE_QUEUE_FULL` even though the memory usage is about 6% of the available RAM. Based on a lead from user @Petucky, both devices are being re-enabled as testing on a real Edge 840 device has proven successful, however we remain unable to support either devices until the simulator is fixed. 7. We are unable to support HTTP without HTTPS. This is a limitation placed upon us by the Connect IQ API which for security reasons refuses to work with HTTP requests. There is nothing developers can do about this limitation. You will have to put an HTTPS proxy in front of your local Home Assistant to work with this application. See the [Trouble Shooting](TroubleShooting.md#do-it-yourself-setup) guide for an example setup. We would appreciate it if users did not leave poor reviews for the lack of this feature which is beyond our control to fix. diff --git a/manifest.xml b/manifest.xml index 438faa8..14d1424 100644 --- a/manifest.xml +++ b/manifest.xml @@ -37,122 +37,129 @@ "Monkey C: Edit Products" - Lets you add or remove any product --> - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + slo slv spa swe @@ -195,11 +199,14 @@ tur ukr vie + zhs + zht + zsm - + \ No newline at end of file diff --git a/monkey.jungle b/monkey.jungle index 5c913ce..f432ed6 100644 --- a/monkey.jungle +++ b/monkey.jungle @@ -31,8 +31,8 @@ project.manifest = manifest.xml # # The icons need to scale as a ratio of screen size 48:416 pixels # -# Icon 53 48 46 42 37 32 30 28 26 24 21 18 -# Screen 454 416 390 360 320 280 260 240 218 208 176 156 +# Icon 55 53 48 46 42 37 32 30 28 26 24 21 18 +# Screen 480 454 416 390 360 320 280 260 240 218 208 176 156 # Screen Size 390x390 launcher icon size 70x70 approachs7042mm.resourcePath = $(approachs7042mm.resourcePath);resources-launcher-70-70;resources-icons-46 @@ -64,6 +64,8 @@ edge1030bontrager.resourcePath = $(edge1030bontrager.resourcePath);resources-lau edge1030plus.resourcePath = $(edge1030plus.resourcePath);resources-launcher-36-36;resources-icons-32 # Screen Size 282x470 launcher icon size 40x40 edge1040.resourcePath = $(edge1040.resourcePath);resources-launcher-40-40;resources-icons-32 +# Screen Size 480x800 launcher icon size 68x68 +edge1050.resourcePath = $(edge1050.resourcePath);resources-launcher-68-68;resources-icons-55 # Screen Size 200x265 launcher icon size 35x35 edge520plus.resourcePath = $(edge520plus.resourcePath);resources-launcher-35-35;resources-icons-24 # Screen Size 246x322 launcher icon size 35x35 @@ -79,6 +81,8 @@ edgeexplore.resourcePath = $(edgeexplore.resourcePath);resources-launcher-36-36; edgeexplore2.resourcePath = $(edgeexplore2.resourcePath);resources-launcher-36-36;resources-icons-28 # Screen Size 280x280 launcher icon size 40x40 enduro.resourcePath = $(enduro.resourcePath);resources-launcher-40-40;resources-icons-32 +# Screen Size 280x280 launcher icon size 40x40 +enduro3.resourcePath = $(enduro3.resourcePath);resources-launcher-40-40;resources-icons-32 # Screen Size 416x416 launcher icon size 60x60 epix2.resourcePath = $(epix2.resourcePath);resources-launcher-60-60;resources-icons-48 # Screen Size 390x390 launcher icon size 60x60 @@ -108,8 +112,6 @@ fenix7.resourcePath = $(fenix7.resourcePath);resources-launcher-40-40;resources- # Screen Size 260x260 launcher icon size 40x40 fenix7pro.resourcePath = $(fenix7pro.resourcePath);resources-launcher-40-40;resources-icons-30 fenix7pronowifi.resourcePath = $(fenix7pronowifi.resourcePath);resources-launcher-40-40;resources-icons-30 -# Screen Size 218x218 launcher icon size 36x36 -fenixchronos.resourcePath = $(fenixchronos.resourcePath);resources-launcher-36-36;resources-icons-26 # Screen Size 240x240 launcher icon size 40x40 fenix7s.resourcePath = $(fenix7s.resourcePath);resources-launcher-40-40;resources-icons-28 # Screen Size 240x240 launcher icon size 40x40 @@ -119,6 +121,18 @@ fenix7x.resourcePath = $(fenix7x.resourcePath);resources-launcher-40-40;resource # Screen Size 280x280 launcher icon size 40x40 fenix7xpro.resourcePath = $(fenix7xpro.resourcePath);resources-launcher-40-40;resources-icons-32 fenix7xpronowifi.resourcePath = $(fenix7xpronowifi.resourcePath);resources-launcher-40-40;resources-icons-32 +# Screen Size 416x416 launcher icon size 60x60 +fenix843mm.resourcePath = $(fenix843mm.resourcePath);resources-launcher-60-60;resources-icons-48 +# Screen Size 454x454 launcher icon size 65x65 +fenix847mm.resourcePath = $(fenix847mm.resourcePath);resources-launcher-65-65;resources-icons-53 +# Screen Size 260x260 launcher icon size 40x40 +fenix8solar47mm.resourcePath = $(fenix8solar47mm.resourcePath);resources-launcher-40-40;resources-icons-30 +# Screen Size 280x280 launcher icon size 40x40 +fenix8solar51mm.resourcePath = $(fenix8solar51mm.resourcePath);resources-launcher-40-40;resources-icons-32 +# Screen Size 218x218 launcher icon size 36x36 +fenixchronos.resourcePath = $(fenixchronos.resourcePath);resources-launcher-36-36;resources-icons-26 +# Screen Size 416x416 launcher icon size 60x60 +fenixe.resourcePath = $(fenixe.resourcePath);resources-launcher-60-60;resources-icons-48 # Screen Size 390 x 390 launcher icon size 54x54 fr165.resourcePath = $(descentmk2s.resourcePath);resources-launcher-54-54;resources-icons-46 # Screen Size 390 x 390 launcher icon size 54x54 diff --git a/resources-icons-55/drawables.xml b/resources-icons-55/drawables.xml new file mode 100644 index 0000000..33c0707 --- /dev/null +++ b/resources-icons-55/drawables.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/resources-icons-55/error.svg b/resources-icons-55/error.svg new file mode 100644 index 0000000..863aab2 --- /dev/null +++ b/resources-icons-55/error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-55/group_type.svg b/resources-icons-55/group_type.svg new file mode 100644 index 0000000..62aadad --- /dev/null +++ b/resources-icons-55/group_type.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/resources-icons-55/info_type.svg b/resources-icons-55/info_type.svg new file mode 100644 index 0000000..7e33a82 --- /dev/null +++ b/resources-icons-55/info_type.svg @@ -0,0 +1 @@ + diff --git a/resources-icons-55/tap_type.svg b/resources-icons-55/tap_type.svg new file mode 100644 index 0000000..61d638c --- /dev/null +++ b/resources-icons-55/tap_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-launcher-68-68/drawables.xml b/resources-launcher-68-68/drawables.xml new file mode 100644 index 0000000..44c0b71 --- /dev/null +++ b/resources-launcher-68-68/drawables.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/resources-launcher-68-68/launcher.svg b/resources-launcher-68-68/launcher.svg new file mode 100644 index 0000000..2d63153 --- /dev/null +++ b/resources-launcher-68-68/launcher.svg @@ -0,0 +1,4 @@ + + + + diff --git a/source/ErrorView.mc b/source/ErrorView.mc index b696381..9032200 100644 --- a/source/ErrorView.mc +++ b/source/ErrorView.mc @@ -91,7 +91,7 @@ class ErrorView extends ScalableView { return mDelegate; } - static function create(text as Lang.String) as Lang.Array { + static function create(text as Lang.String) as [ WatchUi.Views ] or [ WatchUi.Views, WatchUi.InputDelegates ] { if (instance == null) { instance = new ErrorView(); } diff --git a/source/HomeAssistantApp.mc b/source/HomeAssistantApp.mc index 4223337..10f11d3 100644 --- a/source/HomeAssistantApp.mc +++ b/source/HomeAssistantApp.mc @@ -27,17 +27,18 @@ using Toybox.Timer; (:glance, :background) class HomeAssistantApp extends Application.AppBase { - private var mApiStatus as Lang.String or Null; - private var mMenuStatus as Lang.String or Null; - private var mHaMenu as HomeAssistantView or Null; - private var mQuitTimer as QuitTimer or Null; - private var mGlanceTimer as Timer.Timer or Null; - private var mUpdateTimer as Timer.Timer or Null; + private var mApiStatus as Lang.String or Null; + private var mMenuStatus as Lang.String or Null; + private var mHaMenu as HomeAssistantView or Null; + private var mQuitTimer as QuitTimer or Null; + private var mGlanceTimer as Timer.Timer or Null; + private var mUpdateTimer as Timer.Timer or Null; // Array initialised by onReturnFetchMenuConfig() - private var mItemsToUpdate as Lang.Array or Null; - private var mIsGlance as Lang.Boolean = false; - 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 mItemsToUpdate as Lang.Array or Null; + private var mIsGlance as Lang.Boolean = false; + 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 mTemplates as Lang.Dictionary = {}; function initialize() { AppBase.initialize(); @@ -87,7 +88,7 @@ class HomeAssistantApp extends Application.AppBase { } // Return the initial view of your application here - function getInitialView() as Lang.Array? { + function getInitialView() as [ WatchUi.Views ] or [ WatchUi.Views, WatchUi.InputDelegates ] { mIsApp = true; mQuitTimer = new QuitTimer(); mUpdateTimer = new Timer.Timer(); @@ -117,9 +118,9 @@ class HomeAssistantApp extends Application.AppBase { var isCached = fetchMenuConfig(); fetchApiStatus(); if (isCached) { - return [mHaMenu, new HomeAssistantViewDelegate(true)] as Lang.Array; + return [mHaMenu, new HomeAssistantViewDelegate(true)]; } else { - return [new WatchUi.View(), new WatchUi.BehaviorDelegate()] as Lang.Array; + return [new WatchUi.View(), new WatchUi.BehaviorDelegate()]; } } } @@ -260,7 +261,6 @@ class HomeAssistantApp extends Application.AppBase { mQuitTimer.begin(); } - var mTemplates as Lang.Dictionary = {}; function startUpdates() { if (mHaMenu != null and !mUpdating) { mItemsToUpdate = mHaMenu.getItemsToUpdate(); @@ -432,11 +432,7 @@ class HomeAssistantApp extends Application.AppBase { break; case 200: - var msg = null; - if (data != null) { - msg = data.get("message"); - } - if (msg.equals("API running.")) { + if ((data != null) && data.get("message").equals("API running.")) { mApiStatus = WatchUi.loadResource($.Rez.Strings.Available) as Lang.String; } else { if (!mIsGlance) { @@ -530,7 +526,7 @@ class HomeAssistantApp extends Application.AppBase { return mQuitTimer; } - function getGlanceView() as Lang.Array or Null { + function getGlanceView() as [ WatchUi.GlanceView ] or [ WatchUi.GlanceView, WatchUi.GlanceViewDelegate ] or Null { mIsGlance = true; mApiStatus = WatchUi.loadResource($.Rez.Strings.Checking) as Lang.String; mMenuStatus = WatchUi.loadResource($.Rez.Strings.Checking) as Lang.String; @@ -555,7 +551,7 @@ class HomeAssistantApp extends Application.AppBase { // Called each time the Registered Temporal Event is to be invoked. So the object is created each time on request and // then destroyed on completion (to save resources). - function getServiceDelegate() as Lang.Array { + function getServiceDelegate() as [ System.ServiceDelegate ] { return [new BackgroundServiceDelegate()]; } diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc index 3107552..1f75f32 100644 --- a/source/HomeAssistantView.mc +++ b/source/HomeAssistantView.mc @@ -73,7 +73,8 @@ class HomeAssistantView extends WatchUi.Menu2 { } } - function getItemsToUpdate() as Lang.Array { + // Lang.Array.addAll() fails structural type checking without including "Null" in the return type + function getItemsToUpdate() as Lang.Array { var fullList = []; var lmi = mItems as Lang.Array; diff --git a/source/WebhookManager.mc b/source/WebhookManager.mc index d682d5b..be2d6f0 100644 --- a/source/WebhookManager.mc +++ b/source/WebhookManager.mc @@ -181,7 +181,8 @@ class WebhookManager { // Webhook ID might have been deleted on Home Assistant server and a Lang.String is trying to tell us an error message Settings.unsetWebhookId(); Settings.unsetIsSensorsLevelEnabled(); - ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + data.toString()); +// ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String + "\n" + data.toString()); + ErrorView.show(WatchUi.loadResource($.Rez.Strings.WebhookFailed) as Lang.String); } break; @@ -217,8 +218,7 @@ class WebhookManager { } function registerWebhookSensors() { - var activityInfo = ActivityMonitor.getInfo(); - var heartRate = Activity.getActivityInfo().currentHeartRate; + var heartRate = Activity.getActivityInfo().currentHeartRate; var sensors = [ { @@ -243,15 +243,6 @@ class WebhookManager { "entity_category" => "diagnostic", "disabled" => !Settings.isSensorsLevelEnabled() }, - { - "name" => "Steps today", - "state" => activityInfo.steps == null ? "unknown" : activityInfo.steps, - "type" => "sensor", - "unique_id" => "steps_today", - "icon" => "mdi:walk", - "state_class" => "total", - "disabled" => !Settings.isSensorsLevelEnabled() - }, { "name" => "Heart rate", "state" => heartRate == null ? "unknown" : heartRate, @@ -264,41 +255,57 @@ class WebhookManager { } ]; - if (ActivityMonitor.Info has :floorsClimbed) { + if (Toybox has :ActivityMonitor) { + System.println("WebhookManager registerWebhookSensors(): has ActivityMonitor class"); + var activityInfo = ActivityMonitor.getInfo(); sensors.add({ - "name" => "Floors climbed today", - "state" => activityInfo.floorsClimbed == null ? "unknown" : activityInfo.floorsClimbed, + "name" => "Steps today", + "state" => activityInfo.steps == null ? "unknown" : activityInfo.steps, "type" => "sensor", - "unique_id" => "floors_climbed_today", - "icon" => "mdi:stairs-up", + "unique_id" => "steps_today", + "icon" => "mdi:walk", "state_class" => "total", "disabled" => !Settings.isSensorsLevelEnabled() }); - } - if (ActivityMonitor.Info has :floorsDescended) { - sensors.add({ - "name" => "Floors descended today", - "state" => activityInfo.floorsDescended == null ? "unknown" : activityInfo.floorsDescended, - "type" => "sensor", - "unique_id" => "floors_descended_today", - "icon" => "mdi:stairs-down", - "state_class" => "total", - "disabled" => !Settings.isSensorsLevelEnabled() - }); - } + if (ActivityMonitor.Info has :floorsClimbed) { + sensors.add({ + "name" => "Floors climbed today", + "state" => activityInfo.floorsClimbed == null ? "unknown" : activityInfo.floorsClimbed, + "type" => "sensor", + "unique_id" => "floors_climbed_today", + "icon" => "mdi:stairs-up", + "state_class" => "total", + "disabled" => !Settings.isSensorsLevelEnabled() + }); + } - if (ActivityMonitor.Info has :respirationRate) { - sensors.add({ - "name" => "Respiration rate", - "state" => activityInfo.respirationRate == null ? "unknown" : activityInfo.respirationRate, - "type" => "sensor", - "unique_id" => "respiration_rate", - "icon" => "mdi:lungs", - "unit_of_measurement" => "bpm", - "state_class" => "measurement", - "disabled" => !Settings.isSensorsLevelEnabled() - }); + if (ActivityMonitor.Info has :floorsDescended) { + sensors.add({ + "name" => "Floors descended today", + "state" => activityInfo.floorsDescended == null ? "unknown" : activityInfo.floorsDescended, + "type" => "sensor", + "unique_id" => "floors_descended_today", + "icon" => "mdi:stairs-down", + "state_class" => "total", + "disabled" => !Settings.isSensorsLevelEnabled() + }); + } + + if (ActivityMonitor.Info has :respirationRate) { + sensors.add({ + "name" => "Respiration rate", + "state" => activityInfo.respirationRate == null ? "unknown" : activityInfo.respirationRate, + "type" => "sensor", + "unique_id" => "respiration_rate", + "icon" => "mdi:lungs", + "unit_of_measurement" => "bpm", + "state_class" => "measurement", + "disabled" => !Settings.isSensorsLevelEnabled() + }); + } + } else { + System.println("WebhookManager registerWebhookSensors(): has no ActivityMonitor class"); } if (Activity has :getProfileInfo) { From 881700d0ed0f63c58c702bdb2a632daf726df5d4 Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Thu, 5 Sep 2024 21:28:33 +0100 Subject: [PATCH 2/3] Update HISTORY.md v2.21 text --- HISTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/HISTORY.md b/HISTORY.md index dc861bf..9aa07ee 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -33,3 +33,4 @@ | 2.18 | Bug fix for reporting activity metrics that might be `null` sometimes. This is unsimulatable situation, so this version is a change based on an informed guess. | | 2.19 | A template to evaluate is now optionally allowed on both `group` and `toggle` menu items. The template to evaluate is non-optional on a `template` menu item. All updates are performed in a single HTTP GET request for efficiency. Bug fix for negative heading values. Vibration now (optionally) confirms toggle menu items being tapped. | | 2.20 | Simplified the code base now that templates have been requested in all menu items. This means the `template` menu item became a superset of `tap`. Therefore the `tap` code has been has been upgraded to include `template` and the latter deprecated. JSON menu definitions continue to support `template` items by instantiating a `tap` menu item, but the schema marks them as deprecated and users should migrate their menu definitions now. Use the [web editor](https://house-of-abbey.github.io/GarminHomeAssistant/web/) for assistance with changes. | +| 2.21 | Added 7 new devices (`edge1050`, `enduro3`, `fenix843mm`, `fenix847mm`, `fenix8solar47mm`, `fenix8solar51mm`, `fenixe`) and upgraded the SDK to 7.3.0. | From ecb2e8bc96030b7eee7695c343a582a59713ecbf Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Thu, 5 Sep 2024 21:57:35 +0000 Subject: [PATCH 3/3] Restyled by whitespace --- resources-icons-55/error.svg | 2 +- resources-icons-55/group_type.svg | 2 +- resources-icons-55/tap_type.svg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources-icons-55/error.svg b/resources-icons-55/error.svg index 863aab2..47ef4c9 100644 --- a/resources-icons-55/error.svg +++ b/resources-icons-55/error.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-55/group_type.svg b/resources-icons-55/group_type.svg index 62aadad..3596e4c 100644 --- a/resources-icons-55/group_type.svg +++ b/resources-icons-55/group_type.svg @@ -4,4 +4,4 @@ - \ No newline at end of file + diff --git a/resources-icons-55/tap_type.svg b/resources-icons-55/tap_type.svg index 61d638c..913a870 100644 --- a/resources-icons-55/tap_type.svg +++ b/resources-icons-55/tap_type.svg @@ -1 +1 @@ - \ No newline at end of file +