Found a path to a crash condition

Preventing a de-reference of null when the HA server is unreachable.
This commit is contained in:
Philip Abbey
2025-08-10 20:50:12 +01:00
parent 57128bf7a4
commit 166b5f4ec3
2 changed files with 74 additions and 70 deletions

View File

@ -4,6 +4,8 @@
"Venu" "Venu"
], ],
"files.exclude": { "files.exclude": {
"resources-*": true "resources-*": true,
"bin": true,
"export": true
} }
} }

View File

@ -430,85 +430,87 @@ class HomeAssistantApp extends Application.AppBase {
//! Construct the GET request to update all menu items. //! Construct the GET request to update all menu items.
// //
function updateMenuItems() as Void { function updateMenuItems() as Void {
var phoneConnected = System.getDeviceSettings().phoneConnected; if (mUpdating) {
var connectionAvailable = System.getDeviceSettings().connectionAvailable; var phoneConnected = System.getDeviceSettings().phoneConnected;
var connectionAvailable = System.getDeviceSettings().connectionAvailable;
// In Wi-Fi/LTE execution mode, we should not show an error page but use a toast instead. // In Wi-Fi/LTE execution mode, we should not show an error page but use a toast instead.
if (Settings.getWifiLteExecutionEnabled() && (! phoneConnected || ! connectionAvailable)) { if (Settings.getWifiLteExecutionEnabled() && (! phoneConnected || ! connectionAvailable)) {
// Notify only once per disconnection cycle // Notify only once per disconnection cycle
if (!mNotifiedNoBle) { if (!mNotifiedNoBle) {
var toast = WatchUi.loadResource($.Rez.Strings.NoPhone); var toast = WatchUi.loadResource($.Rez.Strings.NoPhone);
if (!connectionAvailable) { if (!connectionAvailable) {
toast = WatchUi.loadResource($.Rez.Strings.NoInternet); toast = WatchUi.loadResource($.Rez.Strings.NoInternet);
}
if (mHasToast) {
WatchUi.showToast(toast, null);
} else {
new Alert({
:timeout => Globals.scAlertTimeoutMs,
:font => Graphics.FONT_MEDIUM,
:text => toast,
:fgcolor => Graphics.COLOR_WHITE,
:bgcolor => Graphics.COLOR_BLACK
}).pushView(WatchUi.SLIDE_IMMEDIATE);
}
} }
if (mHasToast) { mNotifiedNoBle = true;
WatchUi.showToast(toast, null); setApiStatus(WatchUi.loadResource($.Rez.Strings.Unavailable) as Lang.String);
} else { mUpdateTimer.start(method(:startUpdates), Globals.wifiPollResumeDelayMs, false);
new Alert({
:timeout => Globals.scAlertTimeoutMs, mUpdating = false;
:font => Graphics.FONT_MEDIUM, return;
:text => toast,
:fgcolor => Graphics.COLOR_WHITE,
:bgcolor => Graphics.COLOR_BLACK
}).pushView(WatchUi.SLIDE_IMMEDIATE);
}
} }
mNotifiedNoBle = true; if (! phoneConnected) {
setApiStatus(WatchUi.loadResource($.Rez.Strings.Unavailable) as Lang.String); // System.println("HomeAssistantApp updateMenuItems(): No Phone connection, skipping API call.");
mUpdateTimer.start(method(:startUpdates), Globals.wifiPollResumeDelayMs, false); ErrorView.show(WatchUi.loadResource($.Rez.Strings.NoPhone) as Lang.String);
setApiStatus(WatchUi.loadResource($.Rez.Strings.Unavailable) as Lang.String);
} else if (! connectionAvailable) {
// System.println("HomeAssistantApp updateMenuItems(): No Internet connection, skipping API call.");
ErrorView.show(WatchUi.loadResource($.Rez.Strings.NoInternet) as Lang.String);
setApiStatus(WatchUi.loadResource($.Rez.Strings.Unavailable) as Lang.String);
} else {
mNotifiedNoBle = false;
mUpdating = false; if (mItemsToUpdate == null or mTemplates == null) {
return; mItemsToUpdate = mHaMenu.getItemsToUpdate();
} mTemplates = {};
for (var i = 0; i < mItemsToUpdate.size(); i++) {
if (! phoneConnected) { var item = mItemsToUpdate[i];
// System.println("HomeAssistantApp updateMenuItems(): No Phone connection, skipping API call."); var template = item.getTemplate();
ErrorView.show(WatchUi.loadResource($.Rez.Strings.NoPhone) as Lang.String); if (template != null) {
setApiStatus(WatchUi.loadResource($.Rez.Strings.Unavailable) as Lang.String); mTemplates.put(i.toString(), {
} else if (! connectionAvailable) { "template" => template
// System.println("HomeAssistantApp updateMenuItems(): No Internet connection, skipping API call."); });
ErrorView.show(WatchUi.loadResource($.Rez.Strings.NoInternet) as Lang.String); }
setApiStatus(WatchUi.loadResource($.Rez.Strings.Unavailable) as Lang.String); if (item instanceof HomeAssistantToggleMenuItem) {
} else { mTemplates.put(i.toString() + "t", {
mNotifiedNoBle = false; "template" => (item as HomeAssistantToggleMenuItem).getToggleTemplate()
if (mItemsToUpdate == null or mTemplates == null) {
mItemsToUpdate = mHaMenu.getItemsToUpdate();
mTemplates = {};
for (var i = 0; i < mItemsToUpdate.size(); i++) {
var item = mItemsToUpdate[i];
var template = item.getTemplate();
if (template != null) {
mTemplates.put(i.toString(), {
"template" => template
}); });
} }
if (item instanceof HomeAssistantToggleMenuItem) { }
mTemplates.put(i.toString() + "t", {
"template" => (item as HomeAssistantToggleMenuItem).getToggleTemplate()
});
}
} }
// https://developers.home-assistant.io/docs/api/native-app-integration/sending-data/#render-templates
// System.println("HomeAssistantApp updateMenuItems() URL=" + url + ", Template='" + mTemplate + "'");
Communications.makeWebRequest(
Settings.getApiUrl() + "/webhook/" + Settings.getWebhookId(),
{
"type" => "render_template",
"data" => mTemplates
},
{
:method => Communications.HTTP_REQUEST_METHOD_POST,
:headers => Settings.augmentHttpHeaders({
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON
}),
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
},
method(:onReturnUpdateMenuItems)
);
} }
// https://developers.home-assistant.io/docs/api/native-app-integration/sending-data/#render-templates
// System.println("HomeAssistantApp updateMenuItems() URL=" + url + ", Template='" + mTemplate + "'");
Communications.makeWebRequest(
Settings.getApiUrl() + "/webhook/" + Settings.getWebhookId(),
{
"type" => "render_template",
"data" => mTemplates
},
{
:method => Communications.HTTP_REQUEST_METHOD_POST,
:headers => Settings.augmentHttpHeaders({
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_JSON
}),
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
},
method(:onReturnUpdateMenuItems)
);
} }
} }