From 2cd171637c6bf1359579b1289ac3985d58b49db4 Mon Sep 17 00:00:00 2001 From: thmichel Date: Sat, 25 Oct 2025 21:26:44 +0200 Subject: [PATCH] Reworked numericMenuItem to be able to display a different conten in the sublabel than jus a number. --- source/HomeAssistantApp.mc | 9 +++ source/HomeAssistantNumericMenuItem.mc | 59 +++++++++++++++++-- source/factory/HomeAssistantNumericFactory.mc | 6 +- source/picker/HomeAssistantNumericPicker.mc | 17 ++++-- 4 files changed, 78 insertions(+), 13 deletions(-) diff --git a/source/HomeAssistantApp.mc b/source/HomeAssistantApp.mc index 6f628c7..273ec4c 100644 --- a/source/HomeAssistantApp.mc +++ b/source/HomeAssistantApp.mc @@ -629,6 +629,10 @@ class HomeAssistantApp extends Application.AppBase { if (item instanceof HomeAssistantToggleMenuItem) { (item as HomeAssistantToggleMenuItem).updateToggleState(data[i.toString() + "t"]); } + if (item instanceof HomeAssistantNumericMenuItem) { + // (item as HomeAssistantNumericMenuItem).updateNumericState("22"); + (item as HomeAssistantNumericMenuItem).updateNumericState(data[i.toString() + "n"].toString()); + } } if (Settings.getMenuCheck() && Settings.getCacheConfig() && !mIsCacheChecked) { // We are caching the menu configuration, so let's fetch it and check if its been updated. @@ -723,6 +727,11 @@ class HomeAssistantApp extends Application.AppBase { "template" => (item as HomeAssistantToggleMenuItem).getToggleTemplate() }); } + if (item instanceof HomeAssistantNumericMenuItem) { + mTemplates.put(i.toString() + "n", { + "template" => (item as HomeAssistantNumericMenuItem).getNumericTemplate() + }); + } } } // https://developers.home-assistant.io/docs/api/native-app-integration/sending-data/#render-templates diff --git a/source/HomeAssistantNumericMenuItem.mc b/source/HomeAssistantNumericMenuItem.mc index af590ca..2cb2488 100644 --- a/source/HomeAssistantNumericMenuItem.mc +++ b/source/HomeAssistantNumericMenuItem.mc @@ -68,6 +68,15 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { mLabel = label; mHomeAssistantService = haService; + var val = data.get("display_format"); + if (val != null) { + mFormatString = val.toString(); + } + else { + mFormatString = "%.1f"; + } + + HomeAssistantMenuItem.initialize( label, template, @@ -75,7 +84,7 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { :alignment => options[:alignment], :icon => options[:icon] } - ); + ); } @@ -137,10 +146,47 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { //! @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 { - mHomeAssistantService.call(mService, {"entity_id" => mData.get("entity_id").toString(),mData.get("valueLabel").toString() => mValue}, mExit); - + //mHomeAssistantService.call(mService, {"entity_id" => mData.get("entity_id").toString(),mData.get("valueLabel").toString() => mValue}, mExit); + var dataAttribute = mData.get("data_attribute"); + if (dataAttribute == null) { + //return without call service if no data attribute is set to avoid crash + WatchUi.popView(WatchUi.SLIDE_RIGHT); + return; + } + var entity_id = mData.get("entity_id"); + if (entity_id == null) { + //return without call service if no entity_id is set to avoid crash + WatchUi.popView(WatchUi.SLIDE_RIGHT); + return; + } + mHomeAssistantService.call(mService, {"entity_id" => entity_id.toString(),dataAttribute.toString() => mValue}, mExit); + WatchUi.popView(WatchUi.SLIDE_RIGHT); } + //! Return a toggle menu item's state template. + //! + //! @return A string with the menu item's template definition (or null). + // + function getNumericTemplate() as Lang.String? { + var entity_id = mData.get("entity_id"); + if (entity_id != null) { + return "{{state_attr('" + entity_id.toString() + "','" + mData.get("attribute").toString() +"')}}"; + } + return null; + } + + function updateNumericState(data as Lang.String or Lang.Dictionary or Null) as Void { + if (data == null) { + mValue="0"; + return; + } else if(data instanceof Lang.String) { + mValue=data; + + } else { + // Catch possible error + mValue="0"; + } + } //! Update the menu item's sub label to display the template rendered by Home Assistant. @@ -158,10 +204,11 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { var f = data.toFloat() as Lang.Float; setSubLabel(f.format(mFormatString)); } else if (data instanceof Lang.String){ + // This should not happen setSubLabel(data); } else { - // The template must return a Float, or the item cannot be formatted locally without error. + // The template must return a Float on Numeric value, or the item cannot be formatted locally without error. setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String); } WatchUi.requestUpdate(); @@ -175,6 +222,10 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { mValue = value; } + function getValue() as Lang.String { + return mValue; + } + function getData() as Lang.Dictionary { return mData; } diff --git a/source/factory/HomeAssistantNumericFactory.mc b/source/factory/HomeAssistantNumericFactory.mc index 32c8645..bb1bee5 100644 --- a/source/factory/HomeAssistantNumericFactory.mc +++ b/source/factory/HomeAssistantNumericFactory.mc @@ -32,11 +32,11 @@ class HomeAssistantNumericFactory extends WatchUi.PickerFactory { // Get values from data - var val = data.get("start"); + var val = data.get("min"); if (val != null) { mStart = val.toString().toFloat(); } - val = data.get("stop"); + val = data.get("max"); if (val != null) { mStop = val.toString().toFloat(); } @@ -44,7 +44,7 @@ class HomeAssistantNumericFactory extends WatchUi.PickerFactory { if (val != null) { mStep = val.toString().toFloat(); } - val = data.get("formatString"); + val = data.get("display_format"); if (val != null) { mFormatString = val.toString(); } diff --git a/source/picker/HomeAssistantNumericPicker.mc b/source/picker/HomeAssistantNumericPicker.mc index a8d7317..05da47c 100644 --- a/source/picker/HomeAssistantNumericPicker.mc +++ b/source/picker/HomeAssistantNumericPicker.mc @@ -37,18 +37,24 @@ class HomeAssistantNumericPicker extends WatchUi.Picker { var data = mItem.getData(); - var start = 0.0; - var val = data.get("start"); + var min = 0.0; + var val = data.get("min"); if (val != null) { - start = val.toString().toFloat(); + min = val.toString().toFloat(); } var step = 1.0; val = data.get("step"); if (val != null) { step = val.toString().toFloat(); } - val = haItem.getSubLabel().toFloat(); - var index = ((val -start) / step).toNumber(); + val = haItem.getValue(); + if (val != null) { + val = val.toString().toFloat(); + } else { + // catch missing state to avoid crash + val = min; + } + var index = ((val -min) / step).toNumber(); pickerOptions[:defaults] =[index]; @@ -96,7 +102,6 @@ class HomeAssistantNumericPickerDelegate extends WatchUi.PickerDelegate { public function onAccept(values as Lang.Array) as Lang.Boolean { var chosenValue = values[0].toString(); mPicker.onConfirm(chosenValue); - WatchUi.popView(WatchUi.SLIDE_RIGHT); return true; } }