From 7ffbd84785dd92ce2a889038f9b05fb3bad1362d Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Wed, 17 Jan 2024 23:31:27 +0000 Subject: [PATCH 1/9] Initial working version --- resources-icons-18/drawables.xml | 1 + resources-icons-18/info_type.svg | 1 + resources-icons-21/drawables.xml | 1 + resources-icons-21/info_type.svg | 1 + resources-icons-24/drawables.xml | 1 + resources-icons-24/info_type.svg | 1 + resources-icons-26/drawables.xml | 1 + resources-icons-26/info_type.svg | 1 + resources-icons-28/drawables.xml | 1 + resources-icons-28/info_type.svg | 1 + resources-icons-30/drawables.xml | 1 + resources-icons-30/info_type.svg | 1 + resources-icons-32/drawables.xml | 1 + resources-icons-32/info_type.svg | 1 + resources-icons-38/drawables.xml | 1 + resources-icons-38/info_type.svg | 1 + resources-icons-42/drawables.xml | 1 + resources-icons-42/info_type.svg | 1 + resources-icons-46/drawables.xml | 1 + resources-icons-46/info_type.svg | 1 + resources-icons-48/drawables.xml | 1 + resources-icons-48/info_type.svg | 1 + resources-icons-53/drawables.xml | 1 + resources-icons-53/info_type.svg | 1 + source/HomeAssistantMenuItem.mc | 11 +++++-- source/HomeAssistantMenuItemFactory.mc | 39 +++++++++++++++++++++++-- source/HomeAssistantService.mc | 18 ++++++++---- source/HomeAssistantTemplateMenuItem.mc | 17 ++++++++--- source/HomeAssistantView.mc | 17 +++++++---- 29 files changed, 106 insertions(+), 20 deletions(-) create mode 100644 resources-icons-18/info_type.svg create mode 100644 resources-icons-21/info_type.svg create mode 100644 resources-icons-24/info_type.svg create mode 100644 resources-icons-26/info_type.svg create mode 100644 resources-icons-28/info_type.svg create mode 100644 resources-icons-30/info_type.svg create mode 100644 resources-icons-32/info_type.svg create mode 100644 resources-icons-38/info_type.svg create mode 100644 resources-icons-42/info_type.svg create mode 100644 resources-icons-46/info_type.svg create mode 100644 resources-icons-48/info_type.svg create mode 100644 resources-icons-53/info_type.svg diff --git a/resources-icons-18/drawables.xml b/resources-icons-18/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-18/drawables.xml +++ b/resources-icons-18/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-18/info_type.svg b/resources-icons-18/info_type.svg new file mode 100644 index 0000000..50db92a --- /dev/null +++ b/resources-icons-18/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-21/drawables.xml b/resources-icons-21/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-21/drawables.xml +++ b/resources-icons-21/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-21/info_type.svg b/resources-icons-21/info_type.svg new file mode 100644 index 0000000..d9d5806 --- /dev/null +++ b/resources-icons-21/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-24/drawables.xml b/resources-icons-24/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-24/drawables.xml +++ b/resources-icons-24/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-24/info_type.svg b/resources-icons-24/info_type.svg new file mode 100644 index 0000000..f8e316c --- /dev/null +++ b/resources-icons-24/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-26/drawables.xml b/resources-icons-26/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-26/drawables.xml +++ b/resources-icons-26/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-26/info_type.svg b/resources-icons-26/info_type.svg new file mode 100644 index 0000000..4e5492d --- /dev/null +++ b/resources-icons-26/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-28/drawables.xml b/resources-icons-28/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-28/drawables.xml +++ b/resources-icons-28/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-28/info_type.svg b/resources-icons-28/info_type.svg new file mode 100644 index 0000000..a2acf01 --- /dev/null +++ b/resources-icons-28/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-30/drawables.xml b/resources-icons-30/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-30/drawables.xml +++ b/resources-icons-30/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-30/info_type.svg b/resources-icons-30/info_type.svg new file mode 100644 index 0000000..65fc0b8 --- /dev/null +++ b/resources-icons-30/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-32/drawables.xml b/resources-icons-32/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-32/drawables.xml +++ b/resources-icons-32/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-32/info_type.svg b/resources-icons-32/info_type.svg new file mode 100644 index 0000000..427d108 --- /dev/null +++ b/resources-icons-32/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-38/drawables.xml b/resources-icons-38/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-38/drawables.xml +++ b/resources-icons-38/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-38/info_type.svg b/resources-icons-38/info_type.svg new file mode 100644 index 0000000..9aa14b3 --- /dev/null +++ b/resources-icons-38/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-42/drawables.xml b/resources-icons-42/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-42/drawables.xml +++ b/resources-icons-42/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-42/info_type.svg b/resources-icons-42/info_type.svg new file mode 100644 index 0000000..087960e --- /dev/null +++ b/resources-icons-42/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-46/drawables.xml b/resources-icons-46/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-46/drawables.xml +++ b/resources-icons-46/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-46/info_type.svg b/resources-icons-46/info_type.svg new file mode 100644 index 0000000..3c9329a --- /dev/null +++ b/resources-icons-46/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-48/drawables.xml b/resources-icons-48/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-48/drawables.xml +++ b/resources-icons-48/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-48/info_type.svg b/resources-icons-48/info_type.svg new file mode 100644 index 0000000..9825159 --- /dev/null +++ b/resources-icons-48/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources-icons-53/drawables.xml b/resources-icons-53/drawables.xml index d560ef6..33c0707 100644 --- a/resources-icons-53/drawables.xml +++ b/resources-icons-53/drawables.xml @@ -19,4 +19,5 @@ + diff --git a/resources-icons-53/info_type.svg b/resources-icons-53/info_type.svg new file mode 100644 index 0000000..d8ec47d --- /dev/null +++ b/resources-icons-53/info_type.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/source/HomeAssistantMenuItem.mc b/source/HomeAssistantMenuItem.mc index ce0330f..5bcf623 100644 --- a/source/HomeAssistantMenuItem.mc +++ b/source/HomeAssistantMenuItem.mc @@ -26,6 +26,7 @@ class HomeAssistantMenuItem extends WatchUi.IconMenuItem { private var mHomeAssistantService as HomeAssistantService; private var mService as Lang.String; private var mConfirm as Lang.Boolean; + private var mData as Lang.Dictionary or Null; function initialize( label as Lang.String or Lang.Symbol, @@ -33,6 +34,7 @@ class HomeAssistantMenuItem extends WatchUi.IconMenuItem { identifier as Lang.Object or Null, service as Lang.String or Null, confirm as Lang.Boolean, + data as Lang.Dictionary or Null, icon as Graphics.BitmapType or WatchUi.Drawable, options as { :alignment as WatchUi.MenuItem.Alignment @@ -48,9 +50,14 @@ class HomeAssistantMenuItem extends WatchUi.IconMenuItem { ); mHomeAssistantService = haService; - mIdentifier = identifier; mService = service; mConfirm = confirm; + mData = data; + if (mData == null) { + mData = {"entity_id" => identifier}; + } else { + mData.put("entity_id", identifier); + } } function callService() as Void { @@ -66,7 +73,7 @@ class HomeAssistantMenuItem extends WatchUi.IconMenuItem { } function onConfirm() as Void { - mHomeAssistantService.call(mIdentifier as Lang.String, mService); + mHomeAssistantService.call(mIdentifier as Lang.String, mService, mData); } } diff --git a/source/HomeAssistantMenuItemFactory.mc b/source/HomeAssistantMenuItemFactory.mc index 2ff7fb0..76437a1 100644 --- a/source/HomeAssistantMenuItemFactory.mc +++ b/source/HomeAssistantMenuItemFactory.mc @@ -26,6 +26,7 @@ class HomeAssistantMenuItemFactory { private var mMenuItemOptions as Lang.Dictionary; private var mTapTypeIcon as WatchUi.Bitmap; private var mGroupTypeIcon as WatchUi.Bitmap; + private var mInfoTypeIcon as WatchUi.Bitmap; private var mHomeAssistantService as HomeAssistantService; private static var instance; @@ -47,6 +48,12 @@ class HomeAssistantMenuItemFactory { :locY => WatchUi.LAYOUT_VALIGN_CENTER }); + mInfoTypeIcon = new WatchUi.Bitmap({ + :rezId => $.Rez.Drawables.InfoTypeIcon, + :locX => WatchUi.LAYOUT_HALIGN_CENTER, + :locY => WatchUi.LAYOUT_VALIGN_CENTER + }); + mHomeAssistantService = new HomeAssistantService(); } @@ -67,12 +74,13 @@ class HomeAssistantMenuItemFactory { ); } - function template( + function template_tap( label as Lang.String or Lang.Symbol, identifier as Lang.Object or Null, template as Lang.String or Null, service as Lang.String or Null, - confirm as Lang.Boolean + confirm as Lang.Boolean, + data as Lang.Dictionary or Null ) as WatchUi.MenuItem { return new HomeAssistantTemplateMenuItem( label, @@ -80,6 +88,29 @@ class HomeAssistantMenuItemFactory { template, service, confirm, + data, + mTapTypeIcon, + mMenuItemOptions, + mHomeAssistantService + ); + } + + function template_notap( + label as Lang.String or Lang.Symbol, + identifier as Lang.Object or Null, + template as Lang.String or Null, + service as Lang.String or Null, + confirm as Lang.Boolean, + data as Lang.Dictionary or Null + ) as WatchUi.MenuItem { + return new HomeAssistantTemplateMenuItem( + label, + identifier, + template, + service, + confirm, + data, + mInfoTypeIcon, mMenuItemOptions, mHomeAssistantService ); @@ -89,7 +120,8 @@ class HomeAssistantMenuItemFactory { label as Lang.String or Lang.Symbol, identifier as Lang.Object or Null, service as Lang.String or Null, - confirm as Lang.Boolean + confirm as Lang.Boolean, + data as Lang.Dictionary or Null ) as WatchUi.MenuItem { return new HomeAssistantMenuItem( label, @@ -97,6 +129,7 @@ class HomeAssistantMenuItemFactory { identifier, service, confirm, + data, mTapTypeIcon, mMenuItemOptions, mHomeAssistantService diff --git a/source/HomeAssistantService.mc b/source/HomeAssistantService.mc index 77b4996..19af6d9 100644 --- a/source/HomeAssistantService.mc +++ b/source/HomeAssistantService.mc @@ -27,7 +27,7 @@ class HomeAssistantService { private var mHasToast as Lang.Boolean = false; private var mHasVibrate as Lang.Boolean = false; - function initialise() { + function initialize() { if (WatchUi has :showToast) { mHasToast = true; } @@ -38,7 +38,11 @@ class HomeAssistantService { // Callback function after completing the POST request to call a service. // - function onReturnCall(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String, context as Lang.Object) as Void { + function onReturnCall( + responseCode as Lang.Number, + data as Null or Lang.Dictionary or Lang.String, + context as Lang.Object + ) as Void { var identifier = context as Lang.String; if (Globals.scDebug) { System.println("HomeAssistantService onReturnCall() Response Code: " + responseCode); @@ -120,7 +124,11 @@ class HomeAssistantService { } } - function call(identifier as Lang.String, service as Lang.String) as Void { + function call( + identifier as Lang.String, + service as Lang.String, + data as Lang.Dictionary or Null + ) as Void { if (! System.getDeviceSettings().phoneConnected) { if (Globals.scDebug) { System.println("HomeAssistantService call(): No Phone connection, skipping API call."); @@ -140,9 +148,7 @@ class HomeAssistantService { } Communications.makeWebRequest( url, - { - "entity_id" => identifier - }, + data, // Includes {"entity_id": identifier} { :method => Communications.HTTP_REQUEST_METHOD_POST, :headers => { diff --git a/source/HomeAssistantTemplateMenuItem.mc b/source/HomeAssistantTemplateMenuItem.mc index c8ba460..f2a8555 100644 --- a/source/HomeAssistantTemplateMenuItem.mc +++ b/source/HomeAssistantTemplateMenuItem.mc @@ -26,11 +26,12 @@ using Toybox.Lang; using Toybox.WatchUi; using Toybox.Graphics; -class HomeAssistantTemplateMenuItem extends WatchUi.MenuItem { +class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem { private var mHomeAssistantService as HomeAssistantService; private var mTemplate as Lang.String; private var mService as Lang.String or Null; private var mConfirm as Lang.Boolean; + private var mData as Lang.Dictionary or Null; function initialize( label as Lang.String or Lang.Symbol, @@ -38,16 +39,18 @@ class HomeAssistantTemplateMenuItem extends WatchUi.MenuItem { template as Lang.String, service as Lang.String or Null, confirm as Lang.Boolean, + data as Lang.Dictionary or Null, + icon as Graphics.BitmapType or WatchUi.Drawable, options as { :alignment as WatchUi.MenuItem.Alignment, - :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol } or Null, haService as HomeAssistantService ) { - WatchUi.MenuItem.initialize( + WatchUi.IconMenuItem.initialize( label, null, identifier, + icon, options ); @@ -55,6 +58,12 @@ class HomeAssistantTemplateMenuItem extends WatchUi.MenuItem { mTemplate = template; mService = service; mConfirm = confirm; + mData = data; + if (mData == null) { + mData = {"entity_id" => identifier}; + } else { + mData.put("entity_id", identifier); + } } function callService() as Void { @@ -71,7 +80,7 @@ class HomeAssistantTemplateMenuItem extends WatchUi.MenuItem { function onConfirm() as Void { if (mService != null) { - mHomeAssistantService.call(mIdentifier as Lang.String, mService); + mHomeAssistantService.call(mIdentifier as Lang.String, mService, mData); } } diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc index 1a65c98..df70ccd 100644 --- a/source/HomeAssistantView.mc +++ b/source/HomeAssistantView.mc @@ -51,11 +51,13 @@ class HomeAssistantView extends WatchUi.Menu2 { var content = items[i].get("content") as Lang.String or Null; var entity = items[i].get("entity") as Lang.String or Null; var tap_action = items[i].get("tap_action") as Lang.Dictionary or Null; - var service = items[i].get("service") as Lang.String or Null; - var confirm = false as Lang.Boolean; + var service = items[i].get("service") as Lang.String or Null; // Deprecated schema + var confirm = false as Lang.Boolean or Null; + var data = null as Lang.Dictionary or Null; if (tap_action != null) { service = tap_action.get("service"); - confirm = tap_action.get("confirm"); + confirm = tap_action.get("confirm"); // Optional + data = tap_action.get("data"); // Optional if (confirm == null) { confirm = false; } @@ -64,9 +66,14 @@ class HomeAssistantView extends WatchUi.Menu2 { if (type.equals("toggle") && entity != null) { addItem(HomeAssistantMenuItemFactory.create().toggle(name, entity)); } else if (type.equals("template") && content != null) { - addItem(HomeAssistantMenuItemFactory.create().template(name, entity, content, service, confirm)); + if (tap_action == null) { + addItem(HomeAssistantMenuItemFactory.create().template_notap(name, entity, content, service, confirm, data)); + } else { + addItem(HomeAssistantMenuItemFactory.create().template_tap(name, entity, content, service, confirm, data)); + } + } else if (type.equals("tap") && entity != null && service != null) { - addItem(HomeAssistantMenuItemFactory.create().tap(name, entity, service, confirm)); + addItem(HomeAssistantMenuItemFactory.create().tap(name, entity, service, confirm, data)); } else if (type.equals("group")) { addItem(HomeAssistantMenuItemFactory.create().group(items[i])); } From 4e96036d66b510e393c8f42bded7d674c8636880 Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Thu, 18 Jan 2024 21:15:59 +0000 Subject: [PATCH 2/9] Removed code to dismiss the ErrorView The automatic ErrorView.unShow() when the HTTP Request callback success was preventing errors being read. Removing to see if they are really required. --- source/HomeAssistantTemplateMenuItem.mc | 1 - source/HomeAssistantToggleMenuItem.mc | 1 - 2 files changed, 2 deletions(-) diff --git a/source/HomeAssistantTemplateMenuItem.mc b/source/HomeAssistantTemplateMenuItem.mc index f2a8555..71dc398 100644 --- a/source/HomeAssistantTemplateMenuItem.mc +++ b/source/HomeAssistantTemplateMenuItem.mc @@ -154,7 +154,6 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem { status = RezStrings.getAvailable(); setSubLabel(data); requestUpdate(); - ErrorView.unShow(); // Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer. getApp().updateNextMenuItem(); break; diff --git a/source/HomeAssistantToggleMenuItem.mc b/source/HomeAssistantToggleMenuItem.mc index 497dd75..ee0f388 100644 --- a/source/HomeAssistantToggleMenuItem.mc +++ b/source/HomeAssistantToggleMenuItem.mc @@ -143,7 +143,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { setLabel((data.get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String); } setUiToggle(state); - ErrorView.unShow(); // Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer. getApp().updateNextMenuItem(); break; From a48c6a38fe6d688b756733026ba7ecbdd2c7e961 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Thu, 18 Jan 2024 21:17:54 +0000 Subject: [PATCH 3/9] Restyled by whitespace --- resources-icons-18/info_type.svg | 2 +- resources-icons-21/info_type.svg | 2 +- resources-icons-24/info_type.svg | 2 +- resources-icons-26/info_type.svg | 2 +- resources-icons-28/info_type.svg | 2 +- resources-icons-30/info_type.svg | 2 +- resources-icons-32/info_type.svg | 2 +- resources-icons-38/info_type.svg | 2 +- resources-icons-42/info_type.svg | 2 +- resources-icons-46/info_type.svg | 2 +- resources-icons-48/info_type.svg | 2 +- resources-icons-53/info_type.svg | 2 +- source/HomeAssistantView.mc | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/resources-icons-18/info_type.svg b/resources-icons-18/info_type.svg index 50db92a..3d05232 100644 --- a/resources-icons-18/info_type.svg +++ b/resources-icons-18/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-21/info_type.svg b/resources-icons-21/info_type.svg index d9d5806..4d21404 100644 --- a/resources-icons-21/info_type.svg +++ b/resources-icons-21/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-24/info_type.svg b/resources-icons-24/info_type.svg index f8e316c..cdab733 100644 --- a/resources-icons-24/info_type.svg +++ b/resources-icons-24/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-26/info_type.svg b/resources-icons-26/info_type.svg index 4e5492d..a52188f 100644 --- a/resources-icons-26/info_type.svg +++ b/resources-icons-26/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-28/info_type.svg b/resources-icons-28/info_type.svg index a2acf01..f8a23be 100644 --- a/resources-icons-28/info_type.svg +++ b/resources-icons-28/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-30/info_type.svg b/resources-icons-30/info_type.svg index 65fc0b8..d21f4cf 100644 --- a/resources-icons-30/info_type.svg +++ b/resources-icons-30/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-32/info_type.svg b/resources-icons-32/info_type.svg index 427d108..b62fabe 100644 --- a/resources-icons-32/info_type.svg +++ b/resources-icons-32/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-38/info_type.svg b/resources-icons-38/info_type.svg index 9aa14b3..c1a797a 100644 --- a/resources-icons-38/info_type.svg +++ b/resources-icons-38/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-42/info_type.svg b/resources-icons-42/info_type.svg index 087960e..bd0a6e7 100644 --- a/resources-icons-42/info_type.svg +++ b/resources-icons-42/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-46/info_type.svg b/resources-icons-46/info_type.svg index 3c9329a..7e28228 100644 --- a/resources-icons-46/info_type.svg +++ b/resources-icons-46/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-48/info_type.svg b/resources-icons-48/info_type.svg index 9825159..889ec4b 100644 --- a/resources-icons-48/info_type.svg +++ b/resources-icons-48/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/resources-icons-53/info_type.svg b/resources-icons-53/info_type.svg index d8ec47d..16b10d6 100644 --- a/resources-icons-53/info_type.svg +++ b/resources-icons-53/info_type.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc index df70ccd..36a3fb4 100644 --- a/source/HomeAssistantView.mc +++ b/source/HomeAssistantView.mc @@ -71,7 +71,7 @@ class HomeAssistantView extends WatchUi.Menu2 { } else { addItem(HomeAssistantMenuItemFactory.create().template_tap(name, entity, content, service, confirm, data)); } - + } else if (type.equals("tap") && entity != null && service != null) { addItem(HomeAssistantMenuItemFactory.create().tap(name, entity, service, confirm, data)); } else if (type.equals("group")) { From 52d9a0ec3d8b5be8383bc681f9ae731c316e0959 Mon Sep 17 00:00:00 2001 From: Joseph Abbey Date: Thu, 18 Jan 2024 21:20:34 +0000 Subject: [PATCH 4/9] Update iconResize.py --- iconResize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iconResize.py b/iconResize.py index fdbb378..24fb633 100644 --- a/iconResize.py +++ b/iconResize.py @@ -91,7 +91,7 @@ for screen_size, icon_sizes in lookup.items(): svg.attrs["width"] = lookup[screen_size][Half] svg.attrs["height"] = lookup[screen_size][Half] with open(output_dir + "/" + entry, "wb") as o: - o.write(svg.encode("utf-8")) + o.write(svg.encode("utf-8") + b"\n") elif entry.endswith(".xml"): print("Create file: ", entry.ljust(40) + " XML - Copy file") shutil.copyfile(input_dir + "/" + entry, output_dir + "/" + entry) From 67a5f0a14e910e68208f3380c5e32f03c3213a9d Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Fri, 19 Jan 2024 16:11:30 +0000 Subject: [PATCH 5/9] Amending naming convention Removing some inconsistencies --- ...ViewMenuItem.mc => HomeAssistantGroupMenuItem.mc} | 12 ++++++++---- source/HomeAssistantMenuItemFactory.mc | 4 ++-- ...istantMenuItem.mc => HomeAssistantTapMenuItem.mc} | 2 +- source/HomeAssistantTemplateMenuItem.mc | 2 +- source/HomeAssistantView.mc | 10 +++++----- 5 files changed, 17 insertions(+), 13 deletions(-) rename source/{HomeAssistantViewMenuItem.mc => HomeAssistantGroupMenuItem.mc} (79%) rename source/{HomeAssistantMenuItem.mc => HomeAssistantTapMenuItem.mc} (97%) diff --git a/source/HomeAssistantViewMenuItem.mc b/source/HomeAssistantGroupMenuItem.mc similarity index 79% rename from source/HomeAssistantViewMenuItem.mc rename to source/HomeAssistantGroupMenuItem.mc index 5a92d55..193a6dc 100644 --- a/source/HomeAssistantViewMenuItem.mc +++ b/source/HomeAssistantGroupMenuItem.mc @@ -14,20 +14,24 @@ // // Description: // -// Menu button with an icon that opens a sub-menu. +// Menu button with an icon that opens a sub-menu, i.e. group. // //----------------------------------------------------------------------------------- using Toybox.Lang; using Toybox.WatchUi; -class HomeAssistantViewMenuItem extends WatchUi.IconMenuItem { +class HomeAssistantGroupMenuItem extends WatchUi.IconMenuItem { private var mMenu as HomeAssistantView; - function initialize(definition as Lang.Dictionary, icon as WatchUi.Drawable, options as { + function initialize( + definition as Lang.Dictionary, + icon as WatchUi.Drawable, + options as { :alignment as WatchUi.MenuItem.Alignment } or Null) { - var label = definition.get("name") as Lang.String; + + var label = definition.get("name") as Lang.String; var identifier = definition.get("entity") as Lang.String; WatchUi.IconMenuItem.initialize( diff --git a/source/HomeAssistantMenuItemFactory.mc b/source/HomeAssistantMenuItemFactory.mc index 76437a1..c8e3114 100644 --- a/source/HomeAssistantMenuItemFactory.mc +++ b/source/HomeAssistantMenuItemFactory.mc @@ -123,7 +123,7 @@ class HomeAssistantMenuItemFactory { confirm as Lang.Boolean, data as Lang.Dictionary or Null ) as WatchUi.MenuItem { - return new HomeAssistantMenuItem( + return new HomeAssistantTapMenuItem( label, null, identifier, @@ -137,6 +137,6 @@ class HomeAssistantMenuItemFactory { } function group(definition as Lang.Dictionary) as WatchUi.MenuItem { - return new HomeAssistantViewMenuItem(definition, mGroupTypeIcon, mMenuItemOptions); + return new HomeAssistantGroupMenuItem(definition, mGroupTypeIcon, mMenuItemOptions); } } diff --git a/source/HomeAssistantMenuItem.mc b/source/HomeAssistantTapMenuItem.mc similarity index 97% rename from source/HomeAssistantMenuItem.mc rename to source/HomeAssistantTapMenuItem.mc index 5bcf623..23a9542 100644 --- a/source/HomeAssistantMenuItem.mc +++ b/source/HomeAssistantTapMenuItem.mc @@ -22,7 +22,7 @@ using Toybox.Lang; using Toybox.WatchUi; using Toybox.Graphics; -class HomeAssistantMenuItem extends WatchUi.IconMenuItem { +class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem { private var mHomeAssistantService as HomeAssistantService; private var mService as Lang.String; private var mConfirm as Lang.Boolean; diff --git a/source/HomeAssistantTemplateMenuItem.mc b/source/HomeAssistantTemplateMenuItem.mc index 71dc398..e53c9c6 100644 --- a/source/HomeAssistantTemplateMenuItem.mc +++ b/source/HomeAssistantTemplateMenuItem.mc @@ -14,7 +14,7 @@ // // Description: // -// Rendering a Home Assistant Template. +// Menu button that renders a Home Assistant Template, and optionally triggers a service. // // Reference: // * https://developers.home-assistant.io/docs/api/rest/ diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc index 36a3fb4..e31722f 100644 --- a/source/HomeAssistantView.mc +++ b/source/HomeAssistantView.mc @@ -87,7 +87,7 @@ class HomeAssistantView extends WatchUi.Menu2 { var lmi = mItems as Lang.Array; for(var i = 0; i < mItems.size(); i++) { var item = lmi[i]; - if (item instanceof HomeAssistantViewMenuItem) { + if (item instanceof HomeAssistantGroupMenuItem) { fullList.addAll(item.getMenuView().getItemsToUpdate()); } else if (item instanceof HomeAssistantToggleMenuItem) { fullList.add(item); @@ -150,8 +150,8 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate { System.println(haToggleItem.getLabel() + " " + haToggleItem.getId() + " " + haToggleItem.isEnabled()); } haToggleItem.setState(haToggleItem.isEnabled()); - } else if (item instanceof HomeAssistantMenuItem) { - var haItem = item as HomeAssistantMenuItem; + } else if (item instanceof HomeAssistantTapMenuItem) { + var haItem = item as HomeAssistantTapMenuItem; if (Globals.scDebug) { System.println(haItem.getLabel() + " " + haItem.getId()); } @@ -162,8 +162,8 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate { System.println(haItem.getLabel() + " " + haItem.getId()); } haItem.callService(); - } else if (item instanceof HomeAssistantViewMenuItem) { - var haMenuItem = item as HomeAssistantViewMenuItem; + } else if (item instanceof HomeAssistantGroupMenuItem) { + var haMenuItem = item as HomeAssistantGroupMenuItem; if (Globals.scDebug) { System.println("IconMenu: " + haMenuItem.getLabel() + " " + haMenuItem.getId()); } From 2be255bb71f63f735d9274324ba6306f119083eb Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Fri, 19 Jan 2024 18:04:55 +0000 Subject: [PATCH 6/9] Removal of menu identifiers as not actually required Toggle menu is now consistent with the use of data objects in tap and template. HA 'notify' actions now work. Co-Authored-By: Joseph Abbey --- source/HomeAssistantGroupMenuItem.mc | 7 ++--- source/HomeAssistantMenuItemFactory.mc | 42 ++++++++++++++----------- source/HomeAssistantService.mc | 19 ++++++----- source/HomeAssistantTapMenuItem.mc | 13 ++------ source/HomeAssistantTemplateMenuItem.mc | 12 ++----- source/HomeAssistantToggleMenuItem.mc | 33 +++++++++---------- source/HomeAssistantView.mc | 6 ++-- 7 files changed, 60 insertions(+), 72 deletions(-) diff --git a/source/HomeAssistantGroupMenuItem.mc b/source/HomeAssistantGroupMenuItem.mc index 193a6dc..bf52204 100644 --- a/source/HomeAssistantGroupMenuItem.mc +++ b/source/HomeAssistantGroupMenuItem.mc @@ -31,13 +31,10 @@ class HomeAssistantGroupMenuItem extends WatchUi.IconMenuItem { :alignment as WatchUi.MenuItem.Alignment } or Null) { - var label = definition.get("name") as Lang.String; - var identifier = definition.get("entity") as Lang.String; - WatchUi.IconMenuItem.initialize( - label, + definition.get("name") as Lang.String, + null, null, - identifier, icon, options ); diff --git a/source/HomeAssistantMenuItemFactory.mc b/source/HomeAssistantMenuItemFactory.mc index c8e3114..60cb49c 100644 --- a/source/HomeAssistantMenuItemFactory.mc +++ b/source/HomeAssistantMenuItemFactory.mc @@ -64,27 +64,31 @@ class HomeAssistantMenuItemFactory { return instance; } - function toggle(label as Lang.String or Lang.Symbol, identifier as Lang.Object or Null) as WatchUi.MenuItem { + function toggle(label as Lang.String or Lang.Symbol, entity_id as Lang.String or Null) as WatchUi.MenuItem { return new HomeAssistantToggleMenuItem( label, - null, - identifier, - false, + { "entity_id" => entity_id }, mMenuItemOptions ); } function template_tap( label as Lang.String or Lang.Symbol, - identifier as Lang.Object or Null, + entity as Lang.String or Null, template as Lang.String or Null, service as Lang.String or Null, confirm as Lang.Boolean, data as Lang.Dictionary or Null ) as WatchUi.MenuItem { + if (entity != null) { + if (data == null) { + data = { "entity_id" => entity }; + } else { + data.put("entity_id", entity); + } + } return new HomeAssistantTemplateMenuItem( label, - identifier, template, service, confirm, @@ -96,20 +100,15 @@ class HomeAssistantMenuItemFactory { } function template_notap( - label as Lang.String or Lang.Symbol, - identifier as Lang.Object or Null, - template as Lang.String or Null, - service as Lang.String or Null, - confirm as Lang.Boolean, - data as Lang.Dictionary or Null + label as Lang.String or Lang.Symbol, + template as Lang.String or Null ) as WatchUi.MenuItem { return new HomeAssistantTemplateMenuItem( label, - identifier, template, - service, - confirm, - data, + null, + false, + null, mInfoTypeIcon, mMenuItemOptions, mHomeAssistantService @@ -118,15 +117,20 @@ class HomeAssistantMenuItemFactory { function tap( label as Lang.String or Lang.Symbol, - identifier as Lang.Object or Null, + entity as Lang.String or Null, service as Lang.String or Null, confirm as Lang.Boolean, data as Lang.Dictionary or Null ) as WatchUi.MenuItem { + if (entity != null) { + if (data == null) { + data = { "entity_id" => entity }; + } else { + data.put("entity_id", entity); + } + } return new HomeAssistantTapMenuItem( label, - null, - identifier, service, confirm, data, diff --git a/source/HomeAssistantService.mc b/source/HomeAssistantService.mc index 19af6d9..02e1408 100644 --- a/source/HomeAssistantService.mc +++ b/source/HomeAssistantService.mc @@ -43,7 +43,7 @@ class HomeAssistantService { data as Null or Lang.Dictionary or Lang.String, context as Lang.Object ) as Void { - var identifier = context as Lang.String; + var entity_id = context as Lang.String or Null; if (Globals.scDebug) { System.println("HomeAssistantService onReturnCall() Response Code: " + responseCode); System.println("HomeAssistantService onReturnCall() Response Data: " + data); @@ -99,7 +99,7 @@ class HomeAssistantService { var d = data as Lang.Array; var toast = RezStrings.getExecuted(); for(var i = 0; i < d.size(); i++) { - if ((d[i].get("entity_id") as Lang.String).equals(identifier)) { + if ((d[i].get("entity_id") as Lang.String).equals(entity_id)) { toast = (d[i].get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String; } } @@ -125,9 +125,8 @@ class HomeAssistantService { } function call( - identifier as Lang.String, - service as Lang.String, - data as Lang.Dictionary or Null + service as Lang.String, + data as Lang.Dictionary or Null ) as Void { if (! System.getDeviceSettings().phoneConnected) { if (Globals.scDebug) { @@ -146,9 +145,15 @@ class HomeAssistantService { System.println("HomeAssistantService call() URL=" + url); System.println("HomeAssistantService call() service=" + service); } + + var entity_id = data.get("entity_id"); + if (entity_id == null) { + entity_id = ""; + } + Communications.makeWebRequest( url, - data, // Includes {"entity_id": identifier} + data, // Includes {"entity_id": xxxx} { :method => Communications.HTTP_REQUEST_METHOD_POST, :headers => { @@ -156,7 +161,7 @@ class HomeAssistantService { "Authorization" => "Bearer " + Settings.getApiKey() }, :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON, - :context => identifier + :context => entity_id }, method(:onReturnCall) ); diff --git a/source/HomeAssistantTapMenuItem.mc b/source/HomeAssistantTapMenuItem.mc index 23a9542..238cce5 100644 --- a/source/HomeAssistantTapMenuItem.mc +++ b/source/HomeAssistantTapMenuItem.mc @@ -30,8 +30,6 @@ class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem { function initialize( label as Lang.String or Lang.Symbol, - subLabel as Lang.String or Lang.Symbol or Null, - identifier as Lang.Object or Null, service as Lang.String or Null, confirm as Lang.Boolean, data as Lang.Dictionary or Null, @@ -43,8 +41,8 @@ class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem { ) { WatchUi.IconMenuItem.initialize( label, - subLabel, - identifier, + null, + null, icon, options ); @@ -53,11 +51,6 @@ class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem { mService = service; mConfirm = confirm; mData = data; - if (mData == null) { - mData = {"entity_id" => identifier}; - } else { - mData.put("entity_id", identifier); - } } function callService() as Void { @@ -73,7 +66,7 @@ class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem { } function onConfirm() as Void { - mHomeAssistantService.call(mIdentifier as Lang.String, mService, mData); + mHomeAssistantService.call(mService, mData); } } diff --git a/source/HomeAssistantTemplateMenuItem.mc b/source/HomeAssistantTemplateMenuItem.mc index e53c9c6..e617237 100644 --- a/source/HomeAssistantTemplateMenuItem.mc +++ b/source/HomeAssistantTemplateMenuItem.mc @@ -35,21 +35,20 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem { function initialize( label as Lang.String or Lang.Symbol, - identifier as Lang.Object or Null, template as Lang.String, service as Lang.String or Null, confirm as Lang.Boolean, data as Lang.Dictionary or Null, icon as Graphics.BitmapType or WatchUi.Drawable, options as { - :alignment as WatchUi.MenuItem.Alignment, + :alignment as WatchUi.MenuItem.Alignment } or Null, haService as HomeAssistantService ) { WatchUi.IconMenuItem.initialize( label, null, - identifier, + null, icon, options ); @@ -59,11 +58,6 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem { mService = service; mConfirm = confirm; mData = data; - if (mData == null) { - mData = {"entity_id" => identifier}; - } else { - mData.put("entity_id", identifier); - } } function callService() as Void { @@ -80,7 +74,7 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem { function onConfirm() as Void { if (mService != null) { - mHomeAssistantService.call(mIdentifier as Lang.String, mService, mData); + mHomeAssistantService.call(mService, mData); } } diff --git a/source/HomeAssistantToggleMenuItem.mc b/source/HomeAssistantToggleMenuItem.mc index ee0f388..9dd1d10 100644 --- a/source/HomeAssistantToggleMenuItem.mc +++ b/source/HomeAssistantToggleMenuItem.mc @@ -25,21 +25,18 @@ using Toybox.Application.Properties; using Toybox.Timer; class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { + private var mData as Lang.Dictionary; function initialize( label as Lang.String or Lang.Symbol, - subLabel as Lang.String or Lang.Symbol or { - :enabled as Lang.String or Lang.Symbol or Null, - :disabled as Lang.String or Lang.Symbol or Null - } or Null, - identifier, - enabled as Lang.Boolean, + data as Lang.Dictionary or Null, options as { :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); + WatchUi.ToggleMenuItem.initialize(label, null, null, false, options); + mData = data; } private function setUiToggle(state as Null or Lang.String) as Void { @@ -114,9 +111,9 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { if (msg != null) { // Should be an HTTP 404 according to curl queries if (Globals.scDebug) { - System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 404. " + mIdentifier + " " + msg); + System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 404. " + mData.get("entity_id") + " " + msg); } - ErrorView.show("HTTP 404, " + mIdentifier + ". " + data.get("message")); + ErrorView.show("HTTP 404, " + mData.get("entity_id") + ". " + data.get("message")); } else { if (Globals.scDebug) { System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 404, page not found. Check API URL setting."); @@ -127,9 +124,9 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { case 405: if (Globals.scDebug) { - System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 405. " + mIdentifier + " " + data.get("message")); + System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 405. " + mData.get("entity_id") + " " + data.get("message")); } - ErrorView.show("HTTP 405, " + mIdentifier + ". " + data.get("message")); + ErrorView.show("HTTP 405, " + mData.get("entity_id") + ". " + data.get("message")); break; @@ -170,7 +167,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { ErrorView.show(RezStrings.getNoInternet() + "."); getApp().setApiStatus(RezStrings.getUnavailable()); } else { - var url = Settings.getApiUrl() + "/states/" + mIdentifier; + var url = Settings.getApiUrl() + "/states/" + mData.get("entity_id"); if (Globals.scDebug) { System.println("HomeAssistantToggleMenuItem getState() URL=" + url); } @@ -239,7 +236,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { var state; var d = data as Lang.Array; for(var i = 0; i < d.size(); i++) { - if ((d[i].get("entity_id") as Lang.String).equals(mIdentifier)) { + if ((d[i].get("entity_id") as Lang.String).equals(mData.get("entity_id"))) { state = d[i].get("state") as Lang.String; if (Globals.scDebug) { System.println((d[i].get("attributes") as Lang.Dictionary).get("friendly_name") + " State=" + state); @@ -277,7 +274,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { } else { // Updated SDK and got a new error // ERROR: venu: Cannot find symbol ':substring' on type 'PolyType'. - var id = mIdentifier as Lang.String; + var id = mData.get("entity_id") as Lang.String; var url = Settings.getApiUrl() + "/services/"; if (s) { url = url + id.substring(0, id.find(".")) + "/turn_on"; @@ -285,14 +282,12 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { url = url + id.substring(0, id.find(".")) + "/turn_off"; } if (Globals.scDebug) { - System.println("HomeAssistantToggleMenuItem setState() URL=" + url); - System.println("HomeAssistantToggleMenuItem setState() mIdentifier=" + mIdentifier); + System.println("HomeAssistantToggleMenuItem setState() URL = " + url); + System.println("HomeAssistantToggleMenuItem setState() entity_id = " + id); } Communications.makeWebRequest( url, - { - "entity_id" => mIdentifier - }, + mData, { :method => Communications.HTTP_REQUEST_METHOD_POST, :headers => { diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc index e31722f..12b1e5e 100644 --- a/source/HomeAssistantView.mc +++ b/source/HomeAssistantView.mc @@ -66,13 +66,13 @@ class HomeAssistantView extends WatchUi.Menu2 { if (type.equals("toggle") && entity != null) { addItem(HomeAssistantMenuItemFactory.create().toggle(name, entity)); } else if (type.equals("template") && content != null) { - if (tap_action == null) { - addItem(HomeAssistantMenuItemFactory.create().template_notap(name, entity, content, service, confirm, data)); + if (service == null) { + addItem(HomeAssistantMenuItemFactory.create().template_notap(name, content)); } else { addItem(HomeAssistantMenuItemFactory.create().template_tap(name, entity, content, service, confirm, data)); } - } else if (type.equals("tap") && entity != null && service != null) { + } else if (type.equals("tap") && service != null) { addItem(HomeAssistantMenuItemFactory.create().tap(name, entity, service, confirm, data)); } else if (type.equals("group")) { addItem(HomeAssistantMenuItemFactory.create().group(items[i])); From 44ec2e2eb12f1a94ebd9154e2a30d63a43dbf905 Mon Sep 17 00:00:00 2001 From: Philip Abbey Date: Fri, 19 Jan 2024 19:26:02 +0000 Subject: [PATCH 7/9] Initial Solution --- config.schema.json | 122 +++++++++--------------- source/Alert.mc | 25 ++--- source/ErrorView.mc | 10 +- source/HomeAssistantApp.mc | 4 +- source/HomeAssistantConfirmation.mc | 12 ++- source/HomeAssistantMenuItemFactory.mc | 29 +++--- source/HomeAssistantTapMenuItem.mc | 7 +- source/HomeAssistantTemplateMenuItem.mc | 11 +-- source/HomeAssistantToggleMenuItem.mc | 29 +++++- source/HomeAssistantView.mc | 4 +- source/WebhookManager.mc | 4 +- 11 files changed, 123 insertions(+), 134 deletions(-) diff --git a/config.schema.json b/config.schema.json index 1b105f1..c8d273e 100644 --- a/config.schema.json +++ b/config.schema.json @@ -2,12 +2,8 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { - "title": { - "type": "string" - }, - "items": { - "$ref": "#/$defs/items" - }, + "title": { "type": "string" }, + "items": { "$ref": "#/$defs/items" }, "required": ["title", "items"], "additionalProperties": false }, @@ -15,17 +11,19 @@ "toggle": { "type": "object", "properties": { - "entity": { - "$ref": "#/$defs/entity" - }, - "name": { - "title": "Your familiar name", - "type": "string" - }, + "entity": { "$ref": "#/$defs/entity" }, + "name": { "title": "Your familiar name", "type": "string" }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", "const": "toggle" + }, + "tap_action": { + "type": "object", + "properties": { + "confirm": { "$ref": "#/$defs/confirm" } + }, + "additionalProperties": false } }, "required": ["entity", "name", "type"], @@ -34,39 +32,24 @@ "template": { "type": "object", "properties": { - "entity": { - "$ref": "#/$defs/entity" - }, - "name": { - "title": "Your familiar name", - "type": "string" - }, - "content": { - "title": "What to display (template)", - "type": "string" - }, + "entity": { "$ref": "#/$defs/entity" }, + "name": { "title": "Your familiar name", "type": "string" }, + "content": { "title": "What to display (template)", "type": "string" }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", "const": "template" }, - "tap_action": { - "$ref": "#/$defs/action" - } + "tap_action": { "$ref": "#/$defs/tap_action" } }, - "required": ["name", "entity", "content", "type"], + "required": ["name", "content", "type"], "additionalProperties": false }, "tap": { "type": "object", "properties": { - "entity": { - "$ref": "#/$defs/entity" - }, - "name": { - "title": "Your familiar name", - "type": "string" - }, + "entity": { "$ref": "#/$defs/entity" }, + "name": { "title": "Your familiar name", "type": "string" }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", @@ -78,61 +61,43 @@ "title": "Schema change:", "description": "Use 'tap_action' instead to mirror Home Assistant." }, - "tap_action": { - "$ref": "#/$defs/action" - } + "tap_action": { "$ref": "#/$defs/tap_action" } }, "oneOf": [ - { - "required": ["entity", "name", "type", "service"] - }, - { - "required": ["entity", "name", "type", "tap_action"] - } + { "required": ["name", "type", "service"] }, + { "required": ["name", "type", "tap_action"] } ], "additionalProperties": false }, - "menu": { + "group": { "type": "object", "properties": { "entity": { - "$ref": "#/$defs/entity" - }, - "name": { - "title": "Your familiar name", - "type": "string" - }, - "title": { - "type": "string" + "$ref": "#/$defs/entity", + "deprecated": true, + "title": "Schema change:", + "description": "'entity' is no longer necessary and should be removed." }, + "name": { "title": "Your familiar name", "type": "string" }, + "title": { "type": "string" }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", "const": "group" }, - "items": { - "$ref": "#/$defs/items" - } + "items": { "$ref": "#/$defs/items" } }, - "required": ["entity", "name", "title", "type", "items"], + "required": ["name", "title", "type", "items"], "additionalProperties": false }, "items": { "type": "array", "items": { "oneOf": [ - { - "$ref": "#/$defs/toggle" - }, - { - "$ref": "#/$defs/template" - }, - { - "$ref": "#/$defs/tap" - }, - { - "$ref": "#/$defs/menu" - } + { "$ref": "#/$defs/toggle" }, + { "$ref": "#/$defs/template" }, + { "$ref": "#/$defs/tap" }, + { "$ref": "#/$defs/group" } ] } }, @@ -141,21 +106,24 @@ "type": "string", "pattern": "^[^.]+\\.[^.]+$" }, - "action": { + "tap_action": { "title": "Action", "description": "'confirm' field is optional.", "type": "object", "properties": { - "service": { - "$ref": "#/$defs/entity" - }, - "confirm": { - "type": "boolean", - "default": false, - "description": "Confirm the action before execution as a precaution." + "service": { "$ref": "#/$defs/entity" }, + "confirm": { "$ref": "#/$defs/confirm" }, + "data": { + "type": "object", + "description": "The object containing the parameters and their values to be passed to the entity. No schema checking can be done here, you are on your own! On application crash, remove the parameters." } }, "required": ["service"] + }, + "confirm": { + "type": "boolean", + "default": false, + "description": "Confirm the action before execution as a precaution." } } } diff --git a/source/Alert.mc b/source/Alert.mc index 51ca1dc..4ef730c 100644 --- a/source/Alert.mc +++ b/source/Alert.mc @@ -28,14 +28,13 @@ using Toybox.WatchUi; using Toybox.Timer; class Alert extends WatchUi.View { - private static const bRadius = 10; - private var mTimer as Timer.Timer; - private var mTimeout as Lang.Number; - private var mText as Lang.String; - private var mFont as Graphics.FontType; - private var mFgcolor as Graphics.ColorType; - private var mBgcolor as Graphics.ColorType; - private var mAntiAlias as Lang.Boolean = false; + private static const scRadius = 10; + private var mTimer as Timer.Timer; + private var mTimeout as Lang.Number; + private var mText as Lang.String; + private var mFont as Graphics.FontType; + private var mFgcolor as Graphics.ColorType; + private var mBgcolor as Graphics.ColorType; function initialize(params as Lang.Dictionary) { View.initialize(); @@ -65,10 +64,6 @@ class Alert extends WatchUi.View { mTimeout = 2000; } - if (Graphics.Dc has :setAntiAlias) { - mAntiAlias = true; - } - mTimer = new Timer.Timer(); } @@ -88,7 +83,7 @@ class Alert extends WatchUi.View { var bX = (dc.getWidth() - bWidth) / 2; var bY = (dc.getHeight() - bHeight) / 2; - if (mAntiAlias) { + if (Graphics.Dc has :setAntiAlias) { dc.setAntiAlias(true); } @@ -98,7 +93,7 @@ class Alert extends WatchUi.View { ); dc.clear(); dc.setColor(mBgcolor, mBgcolor); - dc.fillRoundedRectangle(bX, bY, bWidth, bHeight, bRadius); + dc.fillRoundedRectangle(bX, bY, bWidth, bHeight, scRadius); dc.setColor(mFgcolor, mBgcolor); for (var i = 0; i < 3; ++i) { @@ -106,7 +101,7 @@ class Alert extends WatchUi.View { bY += i; bWidth -= (2 * i); bHeight -= (2 * i); - dc.drawRoundedRectangle(bX, bY, bWidth, bHeight, bRadius); + dc.drawRoundedRectangle(bX, bY, bWidth, bHeight, scRadius); } var tX = dc.getWidth() / 2; diff --git a/source/ErrorView.mc b/source/ErrorView.mc index 114a763..f4a99da 100644 --- a/source/ErrorView.mc +++ b/source/ErrorView.mc @@ -36,16 +36,14 @@ using Toybox.Communications; using Toybox.Timer; class ErrorView extends ScalableView { - private var mText as Lang.String = ""; + private static const scErrorIconMargin as Lang.Float = 7f; + private var mText as Lang.String = ""; private var mDelegate as ErrorDelegate; - private const cSettings as Lang.Dictionary = { - :errorIconMargin => 7f - }; // Vertical spacing between the top of the face and the error icon private var mErrorIconMargin as Lang.Number; private var mErrorIcon; private var mTextArea as WatchUi.TextArea or Null; - private var mAntiAlias as Lang.Boolean = false; + private var mAntiAlias as Lang.Boolean = false; private static var instance; private static var mShown as Lang.Boolean = false; @@ -54,7 +52,7 @@ class ErrorView extends ScalableView { ScalableView.initialize(); mDelegate = new ErrorDelegate(self); // Convert the settings from % of screen size to pixels - mErrorIconMargin = pixelsForScreen(cSettings.get(:errorIconMargin) as Lang.Float); + mErrorIconMargin = pixelsForScreen(scErrorIconMargin); mErrorIcon = Application.loadResource(Rez.Drawables.ErrorIcon) as Graphics.BitmapResource; if (Graphics.Dc has :setAntiAlias) { mAntiAlias = true; diff --git a/source/HomeAssistantApp.mc b/source/HomeAssistantApp.mc index 902ffb3..460e7f4 100644 --- a/source/HomeAssistantApp.mc +++ b/source/HomeAssistantApp.mc @@ -86,8 +86,8 @@ class HomeAssistantApp extends Application.AppBase { // Return the initial view of your application here function getInitialView() as Lang.Array? { - mIsApp = true; - mQuitTimer = new QuitTimer(); + mIsApp = true; + mQuitTimer = new QuitTimer(); RezStrings.update(); mApiStatus = RezStrings.getChecking(); mMenuStatus = RezStrings.getChecking(); diff --git a/source/HomeAssistantConfirmation.mc b/source/HomeAssistantConfirmation.mc index ce3abe7..c42918f 100644 --- a/source/HomeAssistantConfirmation.mc +++ b/source/HomeAssistantConfirmation.mc @@ -34,12 +34,14 @@ class HomeAssistantConfirmation extends WatchUi.Confirmation { } class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate { - private var mConfirmMethod; - private var mTimer; + private var mConfirmMethod as Method(state as Lang.Boolean) as Void; + private var mTimer as Timer.Timer or Null; + private var mState as Lang.Boolean; - function initialize(callback as Method() as Void) { + function initialize(callback as Method(state as Lang.Boolean) as Void, state as Lang.Boolean) { WatchUi.ConfirmationDelegate.initialize(); mConfirmMethod = callback; + mState = state; var timeout = Settings.getConfirmTimeout(); // ms if (timeout > 0) { mTimer = new Timer.Timer(); @@ -49,11 +51,11 @@ class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate { function onResponse(response) as Lang.Boolean { getApp().getQuitTimer().reset(); - if (mTimer) { + if (mTimer != null) { mTimer.stop(); } if (response == WatchUi.CONFIRM_YES) { - mConfirmMethod.invoke(); + mConfirmMethod.invoke(mState); } return true; } diff --git a/source/HomeAssistantMenuItemFactory.mc b/source/HomeAssistantMenuItemFactory.mc index 60cb49c..67003ec 100644 --- a/source/HomeAssistantMenuItemFactory.mc +++ b/source/HomeAssistantMenuItemFactory.mc @@ -64,21 +64,26 @@ class HomeAssistantMenuItemFactory { return instance; } - function toggle(label as Lang.String or Lang.Symbol, entity_id as Lang.String or Null) as WatchUi.MenuItem { + function toggle( + label as Lang.String or Lang.Symbol, + entity_id as Lang.String or Null, + confirm as Lang.Boolean + ) as WatchUi.MenuItem { return new HomeAssistantToggleMenuItem( label, + confirm, { "entity_id" => entity_id }, mMenuItemOptions ); } function template_tap( - label as Lang.String or Lang.Symbol, - entity as Lang.String or Null, - template as Lang.String or Null, - service as Lang.String or Null, - confirm as Lang.Boolean, - data as Lang.Dictionary or Null + label as Lang.String or Lang.Symbol, + entity as Lang.String or Null, + template as Lang.String or Null, + service as Lang.String or Null, + confirm as Lang.Boolean, + data as Lang.Dictionary or Null ) as WatchUi.MenuItem { if (entity != null) { if (data == null) { @@ -116,11 +121,11 @@ class HomeAssistantMenuItemFactory { } function tap( - label as Lang.String or Lang.Symbol, - entity as Lang.String or Null, - service as Lang.String or Null, - confirm as Lang.Boolean, - data as Lang.Dictionary or Null + label as Lang.String or Lang.Symbol, + entity as Lang.String or Null, + service as Lang.String or Null, + confirm as Lang.Boolean, + data as Lang.Dictionary or Null ) as WatchUi.MenuItem { if (entity != null) { if (data == null) { diff --git a/source/HomeAssistantTapMenuItem.mc b/source/HomeAssistantTapMenuItem.mc index 238cce5..9623a63 100644 --- a/source/HomeAssistantTapMenuItem.mc +++ b/source/HomeAssistantTapMenuItem.mc @@ -57,15 +57,16 @@ class HomeAssistantTapMenuItem extends WatchUi.IconMenuItem { if (mConfirm) { WatchUi.pushView( new HomeAssistantConfirmation(), - new HomeAssistantConfirmationDelegate(method(:onConfirm)), + new HomeAssistantConfirmationDelegate(method(:onConfirm), false), WatchUi.SLIDE_IMMEDIATE ); } else { - onConfirm(); + mHomeAssistantService.call(mService, mData); } } - function onConfirm() as Void { + // NB. Parameter 'b' is ignored + function onConfirm(b as Lang.Boolean) as Void { mHomeAssistantService.call(mService, mData); } diff --git a/source/HomeAssistantTemplateMenuItem.mc b/source/HomeAssistantTemplateMenuItem.mc index e617237..2d60a1c 100644 --- a/source/HomeAssistantTemplateMenuItem.mc +++ b/source/HomeAssistantTemplateMenuItem.mc @@ -64,15 +64,16 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem { if (mConfirm) { WatchUi.pushView( new HomeAssistantConfirmation(), - new HomeAssistantConfirmationDelegate(method(:onConfirm)), + new HomeAssistantConfirmationDelegate(method(:onConfirm), false), WatchUi.SLIDE_IMMEDIATE ); } else { - onConfirm(); + onConfirm(false); } } - function onConfirm() as Void { + // NB. Parameter 'b' is ignored + function onConfirm(b as Lang.Boolean) as Void { if (mService != null) { mHomeAssistantService.call(mService, mData); } @@ -181,9 +182,7 @@ class HomeAssistantTemplateMenuItem extends WatchUi.IconMenuItem { } Communications.makeWebRequest( url, - { - "template" => mTemplate - }, + { "template" => mTemplate }, { :method => Communications.HTTP_REQUEST_METHOD_POST, :headers => { diff --git a/source/HomeAssistantToggleMenuItem.mc b/source/HomeAssistantToggleMenuItem.mc index 9dd1d10..793d011 100644 --- a/source/HomeAssistantToggleMenuItem.mc +++ b/source/HomeAssistantToggleMenuItem.mc @@ -25,18 +25,21 @@ using Toybox.Application.Properties; using Toybox.Timer; class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { - private var mData as Lang.Dictionary; + private var mConfirm as Lang.Boolean; + private var mData as Lang.Dictionary; function initialize( - label as Lang.String or Lang.Symbol, - data as Lang.Dictionary or Null, - options as { + label as Lang.String or Lang.Symbol, + confirm as Lang.Boolean, + data as Lang.Dictionary or Null, + options as { :alignment as WatchUi.MenuItem.Alignment, :icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol } or Null ) { WatchUi.ToggleMenuItem.initialize(label, null, null, false, options); - mData = data; + mConfirm = confirm; + mData = data; } private function setUiToggle(state as Null or Lang.String) as Void { @@ -301,4 +304,20 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { } } + function callService(b as Lang.Boolean) as Void { + if (mConfirm) { + WatchUi.pushView( + new HomeAssistantConfirmation(), + new HomeAssistantConfirmationDelegate(method(:onConfirm), b), + WatchUi.SLIDE_IMMEDIATE + ); + } else { + setState(b); + } + } + + function onConfirm(b as Lang.Boolean) as Void { + setState(b); + } + } diff --git a/source/HomeAssistantView.mc b/source/HomeAssistantView.mc index 12b1e5e..c689111 100644 --- a/source/HomeAssistantView.mc +++ b/source/HomeAssistantView.mc @@ -64,7 +64,7 @@ class HomeAssistantView extends WatchUi.Menu2 { } if (type != null && name != null) { if (type.equals("toggle") && entity != null) { - addItem(HomeAssistantMenuItemFactory.create().toggle(name, entity)); + addItem(HomeAssistantMenuItemFactory.create().toggle(name, entity, confirm)); } else if (type.equals("template") && content != null) { if (service == null) { addItem(HomeAssistantMenuItemFactory.create().template_notap(name, content)); @@ -149,7 +149,7 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate { if (Globals.scDebug) { System.println(haToggleItem.getLabel() + " " + haToggleItem.getId() + " " + haToggleItem.isEnabled()); } - haToggleItem.setState(haToggleItem.isEnabled()); + haToggleItem.callService(haToggleItem.isEnabled()); } else if (item instanceof HomeAssistantTapMenuItem) { var haItem = item as HomeAssistantTapMenuItem; if (Globals.scDebug) { diff --git a/source/WebhookManager.mc b/source/WebhookManager.mc index 5fc2f3f..9d1cf70 100644 --- a/source/WebhookManager.mc +++ b/source/WebhookManager.mc @@ -27,6 +27,7 @@ using Toybox.System; // Can use push view so must never be run in a glance context class WebhookManager { + function onReturnRequestWebhookId(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void { switch (responseCode) { case Communications.BLE_HOST_TIMEOUT: @@ -236,11 +237,12 @@ class WebhookManager { { :method => Communications.HTTP_REQUEST_METHOD_POST, :headers => { - "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON + "Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON }, :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON }, method(:onReturnRegisterWebhookSensor) ); } + } From 018d2d96119aec430c79b8304f5403eb2695acd7 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Fri, 19 Jan 2024 19:39:22 +0000 Subject: [PATCH 8/9] Restyled by jq --- config.schema.json | 133 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 28 deletions(-) diff --git a/config.schema.json b/config.schema.json index c8d273e..6464f02 100644 --- a/config.schema.json +++ b/config.schema.json @@ -2,17 +2,29 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { - "title": { "type": "string" }, - "items": { "$ref": "#/$defs/items" }, - "required": ["title", "items"], + "title": { + "type": "string" + }, + "items": { + "$ref": "#/$defs/items" + }, + "required": [ + "title", + "items" + ], "additionalProperties": false }, "$defs": { "toggle": { "type": "object", "properties": { - "entity": { "$ref": "#/$defs/entity" }, - "name": { "title": "Your familiar name", "type": "string" }, + "entity": { + "$ref": "#/$defs/entity" + }, + "name": { + "title": "Your familiar name", + "type": "string" + }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", @@ -21,35 +33,60 @@ "tap_action": { "type": "object", "properties": { - "confirm": { "$ref": "#/$defs/confirm" } + "confirm": { + "$ref": "#/$defs/confirm" + } }, "additionalProperties": false } }, - "required": ["entity", "name", "type"], + "required": [ + "entity", + "name", + "type" + ], "additionalProperties": false }, "template": { "type": "object", "properties": { - "entity": { "$ref": "#/$defs/entity" }, - "name": { "title": "Your familiar name", "type": "string" }, - "content": { "title": "What to display (template)", "type": "string" }, + "entity": { + "$ref": "#/$defs/entity" + }, + "name": { + "title": "Your familiar name", + "type": "string" + }, + "content": { + "title": "What to display (template)", + "type": "string" + }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", "const": "template" }, - "tap_action": { "$ref": "#/$defs/tap_action" } + "tap_action": { + "$ref": "#/$defs/tap_action" + } }, - "required": ["name", "content", "type"], + "required": [ + "name", + "content", + "type" + ], "additionalProperties": false }, "tap": { "type": "object", "properties": { - "entity": { "$ref": "#/$defs/entity" }, - "name": { "title": "Your familiar name", "type": "string" }, + "entity": { + "$ref": "#/$defs/entity" + }, + "name": { + "title": "Your familiar name", + "type": "string" + }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", @@ -61,11 +98,25 @@ "title": "Schema change:", "description": "Use 'tap_action' instead to mirror Home Assistant." }, - "tap_action": { "$ref": "#/$defs/tap_action" } + "tap_action": { + "$ref": "#/$defs/tap_action" + } }, "oneOf": [ - { "required": ["name", "type", "service"] }, - { "required": ["name", "type", "tap_action"] } + { + "required": [ + "name", + "type", + "service" + ] + }, + { + "required": [ + "name", + "type", + "tap_action" + ] + } ], "additionalProperties": false }, @@ -78,26 +129,46 @@ "title": "Schema change:", "description": "'entity' is no longer necessary and should be removed." }, - "name": { "title": "Your familiar name", "type": "string" }, - "title": { "type": "string" }, + "name": { + "title": "Your familiar name", + "type": "string" + }, + "title": { + "type": "string" + }, "type": { "title": "Menu item type", "description": "One of 'tap', 'template', 'toggle' or 'group'.", "const": "group" }, - "items": { "$ref": "#/$defs/items" } + "items": { + "$ref": "#/$defs/items" + } }, - "required": ["name", "title", "type", "items"], + "required": [ + "name", + "title", + "type", + "items" + ], "additionalProperties": false }, "items": { "type": "array", "items": { "oneOf": [ - { "$ref": "#/$defs/toggle" }, - { "$ref": "#/$defs/template" }, - { "$ref": "#/$defs/tap" }, - { "$ref": "#/$defs/group" } + { + "$ref": "#/$defs/toggle" + }, + { + "$ref": "#/$defs/template" + }, + { + "$ref": "#/$defs/tap" + }, + { + "$ref": "#/$defs/group" + } ] } }, @@ -111,14 +182,20 @@ "description": "'confirm' field is optional.", "type": "object", "properties": { - "service": { "$ref": "#/$defs/entity" }, - "confirm": { "$ref": "#/$defs/confirm" }, + "service": { + "$ref": "#/$defs/entity" + }, + "confirm": { + "$ref": "#/$defs/confirm" + }, "data": { "type": "object", "description": "The object containing the parameters and their values to be passed to the entity. No schema checking can be done here, you are on your own! On application crash, remove the parameters." } }, - "required": ["service"] + "required": [ + "service" + ] }, "confirm": { "type": "boolean", From b7c48db60463ed3e6541497ffb51ee481aecf4fe Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Fri, 19 Jan 2024 19:39:25 +0000 Subject: [PATCH 9/9] Restyled by prettier-json --- config.schema.json | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/config.schema.json b/config.schema.json index 6464f02..1fb63ef 100644 --- a/config.schema.json +++ b/config.schema.json @@ -8,10 +8,7 @@ "items": { "$ref": "#/$defs/items" }, - "required": [ - "title", - "items" - ], + "required": ["title", "items"], "additionalProperties": false }, "$defs": { @@ -40,11 +37,7 @@ "additionalProperties": false } }, - "required": [ - "entity", - "name", - "type" - ], + "required": ["entity", "name", "type"], "additionalProperties": false }, "template": { @@ -70,11 +63,7 @@ "$ref": "#/$defs/tap_action" } }, - "required": [ - "name", - "content", - "type" - ], + "required": ["name", "content", "type"], "additionalProperties": false }, "tap": { @@ -104,18 +93,10 @@ }, "oneOf": [ { - "required": [ - "name", - "type", - "service" - ] + "required": ["name", "type", "service"] }, { - "required": [ - "name", - "type", - "tap_action" - ] + "required": ["name", "type", "tap_action"] } ], "additionalProperties": false @@ -145,12 +126,7 @@ "$ref": "#/$defs/items" } }, - "required": [ - "name", - "title", - "type", - "items" - ], + "required": ["name", "title", "type", "items"], "additionalProperties": false }, "items": { @@ -193,9 +169,7 @@ "description": "The object containing the parameters and their values to be passed to the entity. No schema checking can be done here, you are on your own! On application crash, remove the parameters." } }, - "required": [ - "service" - ] + "required": ["service"] }, "confirm": { "type": "boolean",