mirror of
https://github.com/house-of-abbey/GarminHomeAssistant.git
synced 2025-06-17 11:58:30 +00:00
Connection reporting improvements and update resumption
Separation of phone connectivity and Internet access tests for finer grained feedback to the user. Updates no longer stop on absence of Internet connectivity.
This commit is contained in:
@ -22,10 +22,13 @@ using Toybox.Lang;
|
||||
using Toybox.WatchUi;
|
||||
using Toybox.Graphics;
|
||||
using Toybox.Application.Properties;
|
||||
using Toybox.Timer;
|
||||
|
||||
class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
hidden var mApiKey as Lang.String;
|
||||
hidden var strNoPhone as Lang.String;
|
||||
hidden var strNoInternet as Lang.String;
|
||||
hidden var strNoResponse as Lang.String;
|
||||
hidden var strApiFlood as Lang.String;
|
||||
hidden var strApiUrlNotFound as Lang.String;
|
||||
hidden var strUnhandledHttpErr as Lang.String;
|
||||
@ -43,7 +46,9 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
:icon as Graphics.BitmapType or WatchUi.Drawable or Lang.Symbol
|
||||
} or Null
|
||||
) {
|
||||
strNoPhone = WatchUi.loadResource($.Rez.Strings.NoPhone);
|
||||
strNoInternet = WatchUi.loadResource($.Rez.Strings.NoInternet);
|
||||
strNoResponse = WatchUi.loadResource($.Rez.Strings.NoResponse);
|
||||
strApiFlood = WatchUi.loadResource($.Rez.Strings.ApiFlood);
|
||||
strApiUrlNotFound = WatchUi.loadResource($.Rez.Strings.ApiUrlNotFound);
|
||||
strUnhandledHttpErr = WatchUi.loadResource($.Rez.Strings.UnhandledHttpErr);
|
||||
@ -70,26 +75,41 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: " + responseCode);
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Data: " + data);
|
||||
}
|
||||
if (responseCode == Communications.BLE_QUEUE_FULL) {
|
||||
// Provide the ability to terminate updating chain of calls for a permanent network error.
|
||||
var keepUpdating = true;
|
||||
if (responseCode == Communications.BLE_HOST_TIMEOUT || responseCode == Communications.BLE_CONNECTION_UNAVAILABLE) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
|
||||
}
|
||||
if (!(WatchUi.getCurrentView()[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strNoPhone + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else if (responseCode == Communications.BLE_QUEUE_FULL) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
|
||||
}
|
||||
var cw = WatchUi.getCurrentView();
|
||||
if (!(cw[0] instanceof ErrorView)) {
|
||||
if (!(WatchUi.getCurrentView()[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
// Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer.
|
||||
getApp().updateNextMenuItem();
|
||||
} else if (responseCode == Communications.NETWORK_REQUEST_TIMED_OUT) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
|
||||
}
|
||||
if (!(WatchUi.getCurrentView()[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strNoResponse), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else if (responseCode == 404) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 404, page not found. Check API URL setting.");
|
||||
}
|
||||
var cw = WatchUi.getCurrentView();
|
||||
if (!(cw[0] instanceof ErrorView)) {
|
||||
if (!(WatchUi.getCurrentView()[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
keepUpdating = false;
|
||||
} else if (responseCode == 200) {
|
||||
var state = data.get("state") as Lang.String;
|
||||
if (Globals.scDebug) {
|
||||
@ -99,13 +119,19 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
setLabel((data.get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String);
|
||||
}
|
||||
setUiToggle(state);
|
||||
// Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer.
|
||||
getApp().updateNextMenuItem();
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState(): Unhandled HTTP response code = " + responseCode);
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strUnhandledHttpErr + responseCode ), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
if (!(WatchUi.getCurrentView()[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strUnhandledHttpErr + responseCode ), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
}
|
||||
if (keepUpdating) {
|
||||
// Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer.
|
||||
getApp().updateNextMenuItem();
|
||||
System.println("HomeAssistantToggleMenuItem onReturnGetState(): Updated " + mIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +143,24 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
},
|
||||
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
|
||||
};
|
||||
if (System.getDeviceSettings().phoneConnected && System.getDeviceSettings().connectionAvailable) {
|
||||
var keepUpdating = true;
|
||||
if (! System.getDeviceSettings().phoneConnected) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
|
||||
}
|
||||
if (!(WatchUi.getCurrentView()[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strNoPhone + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else if (! System.getDeviceSettings().connectionAvailable) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
|
||||
}
|
||||
if (!(WatchUi.getCurrentView()[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strNoInternet + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
} else {
|
||||
var url = Properties.getValue("api_url") + "/states/" + mIdentifier;
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem getState() URL=" + url);
|
||||
@ -128,11 +171,17 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
options,
|
||||
method(:onReturnGetState)
|
||||
);
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoInternet + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
// The update is called by onReturnGetState() instead
|
||||
keepUpdating = false;
|
||||
}
|
||||
// On temporary failure, keep the updating going.
|
||||
if (keepUpdating) {
|
||||
// Need to avoid an infinite loop where the pushed ErrorView does not appear before getState() is called again
|
||||
// and the call stack overflows. So continue the call chain from somewhere asynchronous.
|
||||
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.
|
||||
myTimer.start(getApp().method(:updateNextMenuItem), 500, false);
|
||||
System.println("HomeAssistantToggleMenuItem getState(): Updated failed " + mIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,20 +192,26 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: " + responseCode);
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Data: " + data);
|
||||
}
|
||||
if (responseCode == Communications.BLE_QUEUE_FULL) {
|
||||
if (responseCode == Communications.BLE_HOST_TIMEOUT || responseCode == Communications.BLE_CONNECTION_UNAVAILABLE) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: BLE_HOST_TIMEOUT or BLE_CONNECTION_UNAVAILABLE, Bluetooth connection severed.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoPhone + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (responseCode == Communications.BLE_QUEUE_FULL) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: BLE_QUEUE_FULL, API calls too rapid.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strApiFlood), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (responseCode == Communications.NETWORK_REQUEST_TIMED_OUT) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: NETWORK_REQUEST_TIMED_OUT, check Internet connection.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoResponse), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (responseCode == 404) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem onReturnSetState() Response Code: 404, page not found. Check API URL setting.");
|
||||
}
|
||||
var cw = WatchUi.getCurrentView();
|
||||
if (!(cw[0] instanceof ErrorView)) {
|
||||
// Avoid pushing multiple ErrorViews
|
||||
WatchUi.pushView(new ErrorView(strApiUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strApiUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (responseCode == 200) {
|
||||
var state;
|
||||
var d = data as Lang.Array;
|
||||
@ -186,7 +241,21 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
},
|
||||
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
|
||||
};
|
||||
if (System.getDeviceSettings().phoneConnected && System.getDeviceSettings().connectionAvailable) {
|
||||
if (! System.getDeviceSettings().phoneConnected) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
|
||||
}
|
||||
// Toggle the UI back
|
||||
setEnabled(!isEnabled());
|
||||
WatchUi.pushView(new ErrorView(strNoPhone + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else if (! System.getDeviceSettings().connectionAvailable) {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
|
||||
}
|
||||
// Toggle the UI back
|
||||
setEnabled(!isEnabled());
|
||||
WatchUi.pushView(new ErrorView(strNoInternet + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
} else {
|
||||
// Updated SDK and got a new error
|
||||
// ERROR: venu: Cannot find symbol ':substring' on type 'PolyType<Null or $.Toybox.Lang.Object>'.
|
||||
var id = mIdentifier as Lang.String;
|
||||
@ -208,11 +277,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
|
||||
options,
|
||||
method(:onReturnSetState)
|
||||
);
|
||||
} else {
|
||||
if (Globals.scDebug) {
|
||||
System.println("HomeAssistantToggleMenuItem setState(): No Internet connection, skipping API call.");
|
||||
}
|
||||
WatchUi.pushView(new ErrorView(strNoInternet + "."), new ErrorDelegate(), WatchUi.SLIDE_UP);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user