diff --git a/HISTORY.md b/HISTORY.md index 64f2226..24b3ea0 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -49,3 +49,4 @@ | 3.1 | Added the ability for users to provide [custom HTTP headers](HTTP_Headers.md) for their Home Assistant server. Improved German language translations. Thanks to [@tispokes](https://github.com/tispokes) for assisting with both of those. Removed all groups in settings as the SDK is buggy. Fixed a bug with templates in glances causing application crash on startup. | | 3.2 | Only enable or disable sensors on Home Assistant when the background service options is changed, i.e. do not call the API to enable on start up every time. | | 3.3 | Providing automatic detection for menu definition updates, but still requires an application restart. | +| 3.4 | Fixed a bug where templates failed to display in toggle menu items (at least on some devices). Fixed a bug where a menu item requesting to exit on completion appeared to indicate failure when using Wi-Fi or LTE. The fix uses a delay in exiting the application modelled as sufficient for a Venu 2 device, so this might need tweaking for other devices. | diff --git a/README.md b/README.md index e033265..5b24243 100644 --- a/README.md +++ b/README.md @@ -347,6 +347,8 @@ Check the latest unresolved [issues](https://github.com/house-of-abbey/GarminHom - [Garmin Express - Wrong Language](https://forums.garmin.com/developer/connect-iq/i/bug-reports/garmin-express---wrong-language) - [Incorrect language displayed for custom data fields](https://forums.garmin.com/developer/connect-iq/f/discussion/388137/incorrect-language-displayed-for-custom-data-fields) +9. When using Wi-Fi or LTE to toggle a light, the `toggle` will fail when the default or current state of the application's menu does not match the state of the light. The same applies to a cover or other thing that can be toggled. This is because the application is unable to initialise the menu with the current state without Bluetooth. Hence the Wi-Fi/LTE functionality is best used with `tap` items only. + # Authors & Contributors For an up to date list of all authors and contributors, please check the [contributor's page](https://github.com/house-of-abbey/GarminHomeAssistant/graphs/contributors). Thank you all for improving this application. diff --git a/source/Globals.mc b/source/Globals.mc index 65f6574..99cf902 100644 --- a/source/Globals.mc +++ b/source/Globals.mc @@ -49,4 +49,9 @@ class Globals { //! After running a task by Wi-Fi/LTE synchronisation the periodic updates need to resume. This //! is the delay between synchronisation completion and resumption of updates. static const wifiPollResumeDelayMs = 2000; // ms + + //! After running a task by Wi-Fi/LTE synchronisation the if the menu item requests to quit the + //! application, this is the delay to wait after synchronisation completion before quitting. + //! Failure to wait causes the transfer to indicate a failure. + static const wifiQuitDelayMs = 5000; // ms } diff --git a/source/HomeAssistantApp.mc b/source/HomeAssistantApp.mc index 2fcdc5e..50b29a2 100644 --- a/source/HomeAssistantApp.mc +++ b/source/HomeAssistantApp.mc @@ -482,6 +482,8 @@ class HomeAssistantApp extends Application.AppBase { break; case Communications.NETWORK_RESPONSE_OUT_OF_MEMORY: + // As we're out of memory, pretend we've checked and don't try again. + mIsCacheChecked = true; // System.println("HomeAssistantApp onReturnCheckMenuConfig() Response Code: NETWORK_RESPONSE_OUT_OF_MEMORY, are we going too fast?"); var myTimer = new Timer.Timer(); // Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer. diff --git a/source/HomeAssistantSyncDelegate.mc b/source/HomeAssistantSyncDelegate.mc index 31210aa..558b3c1 100644 --- a/source/HomeAssistantSyncDelegate.mc +++ b/source/HomeAssistantSyncDelegate.mc @@ -21,7 +21,7 @@ using Toybox.Lang; // class HomeAssistantSyncDelegate extends Communications.SyncDelegate { //! Retain the last synchronisation error. - private static var syncError as Lang.String?; + private static var mSyncError as Lang.String?; //! Class Constructor // @@ -38,9 +38,9 @@ class HomeAssistantSyncDelegate extends Communications.SyncDelegate { //! Called by the system when starting a bulk synchronisation. // public function onStartSync() as Void { - syncError = null; + mSyncError = null; if (WifiLteExecutionConfirmDelegate.mCommandData == null) { - syncError = WatchUi.loadResource($.Rez.Strings.WifiLteExecutionDataError) as Lang.String; + mSyncError = WatchUi.loadResource($.Rez.Strings.WifiLteExecutionDataError) as Lang.String; onStopSync(); return; } @@ -98,42 +98,48 @@ class HomeAssistantSyncDelegate extends Communications.SyncDelegate { // public function haCallback(code as Lang.Number, data as Lang.Dictionary?) as Void { Communications.notifySyncProgress(100); - if (code == 200) { - syncError = null; - if (WifiLteExecutionConfirmDelegate.mCommandData[:type].equals("entity")) { - var callbackMethod = WifiLteExecutionConfirmDelegate.mCommandData[:callback]; - if (callbackMethod != null) { - var d = data as Lang.Array; - callbackMethod.invoke(d); - } - } - onStopSync(); - return; - } - switch(code) { case Communications.NETWORK_REQUEST_TIMED_OUT: - syncError = WatchUi.loadResource($.Rez.Strings.TimedOut) as Lang.String; + mSyncError = WatchUi.loadResource($.Rez.Strings.TimedOut); break; + case Communications.NETWORK_RESPONSE_OUT_OF_MEMORY: case Communications.INVALID_HTTP_BODY_IN_NETWORK_RESPONSE: - syncError = WatchUi.loadResource($.Rez.Strings.NoJson) as Lang.String; - syncError = ""; + mSyncError = WatchUi.loadResource($.Rez.Strings.PotentialError); + break; + case 404: + mSyncError = WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound); + break; + case 200: + mSyncError = null; + if (WifiLteExecutionConfirmDelegate.mCommandData[:type].equals("entity")) { + var callbackMethod = WifiLteExecutionConfirmDelegate.mCommandData[:callback]; + if (callbackMethod != null) { + callbackMethod.invoke(data as Lang.Array); + } + } + break; default: - var codeMsg = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr) as Lang.String; - syncError = codeMsg + code; + mSyncError = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr) + code; break; } - onStopSync(); } //! Clean up // public function onStopSync() as Void { - if (WifiLteExecutionConfirmDelegate.mCommandData[:exit]) { - System.exit(); - } + Communications.notifySyncComplete(mSyncError); Communications.cancelAllRequests(); - Communications.notifySyncComplete(syncError); + // Need to delay the exit here or the transfer shows as failed (and it might not be). + if (WifiLteExecutionConfirmDelegate.mCommandData[:exit]) { + var myTimer = new Timer.Timer(); + myTimer.start(method(:exit), Globals.wifiQuitDelayMs, false); + } + } + + //! Required for `method(:exit)` to be able to find a method at all. + // + public function exit() as Void { + System.exit(); } } diff --git a/source/HomeAssistantToggleMenuItem.mc b/source/HomeAssistantToggleMenuItem.mc index 5142ea5..95d7261 100644 --- a/source/HomeAssistantToggleMenuItem.mc +++ b/source/HomeAssistantToggleMenuItem.mc @@ -104,7 +104,11 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { if (data == null) { setSubLabel(null); } else if(data instanceof Lang.String) { - setSubLabel(data); + // Need to set both labels, you can't just 'setSubLabel(data)' or nothing displays. + setSubLabel({ + :enabled => data, + :disabled => data + }); } else if(data instanceof Lang.Number) { var d = data as Lang.Number; setSubLabel(d.format("%d"));