mirror of
				https://github.com/house-of-abbey/GarminHomeAssistant.git
				synced 2025-11-04 00:48:14 +00:00 
			
		
		
		
	Finishing off widget+app code changes.
Glance now updates the status. Fix for quitting the application when persistently displaying an ErrorView. Added option for Widget RootView to immediately start HomeAssistant without waiting for a tap as requested by a user.
This commit is contained in:
		@@ -29,37 +29,37 @@ using Toybox.Timer;
 | 
			
		||||
 | 
			
		||||
class Alert extends WatchUi.View {
 | 
			
		||||
    private static const bRadius = 10;
 | 
			
		||||
    private var mTimer;
 | 
			
		||||
    private var mTimeout;
 | 
			
		||||
    private var mText;
 | 
			
		||||
    private var mFont;
 | 
			
		||||
    private var mFgcolor;
 | 
			
		||||
    private var mBgcolor;
 | 
			
		||||
    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();
 | 
			
		||||
 | 
			
		||||
        mText = params.get(:text);
 | 
			
		||||
        mText = params.get(:text) as Lang.String;
 | 
			
		||||
        if (mText == null) {
 | 
			
		||||
            mText = "Alert";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mFont = params.get(:font);
 | 
			
		||||
        mFont = params.get(:font) as Graphics.FontType;
 | 
			
		||||
        if (mFont == null) {
 | 
			
		||||
            mFont = Graphics.FONT_MEDIUM;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mFgcolor = params.get(:fgcolor);
 | 
			
		||||
        mFgcolor = params.get(:fgcolor) as Graphics.ColorType;
 | 
			
		||||
        if (mFgcolor == null) {
 | 
			
		||||
            mFgcolor = Graphics.COLOR_BLACK;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mBgcolor = params.get(:bgcolor);
 | 
			
		||||
        mBgcolor = params.get(:bgcolor) as Graphics.ColorType;
 | 
			
		||||
        if (mBgcolor == null) {
 | 
			
		||||
            mBgcolor = Graphics.COLOR_WHITE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mTimeout = params.get(:timeout);
 | 
			
		||||
        mTimeout = params.get(:timeout) as Lang.Number;
 | 
			
		||||
        if (mTimeout == null) {
 | 
			
		||||
            mTimeout = 2000;
 | 
			
		||||
        }
 | 
			
		||||
@@ -83,7 +83,7 @@ class Alert extends WatchUi.View {
 | 
			
		||||
        var bX      = (dc.getWidth()  - bWidth)  / 2;
 | 
			
		||||
        var bY      = (dc.getHeight() - bHeight) / 2;
 | 
			
		||||
 | 
			
		||||
        if(dc has :setAntiAlias) {
 | 
			
		||||
        if (dc has :setAntiAlias) {
 | 
			
		||||
            dc.setAntiAlias(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -112,30 +112,30 @@ class Alert extends WatchUi.View {
 | 
			
		||||
 | 
			
		||||
    // Remove the alert from view, usually on user input, but that is defined by the calling function.
 | 
			
		||||
    //
 | 
			
		||||
    function dismiss() {
 | 
			
		||||
    function dismiss() as Void {
 | 
			
		||||
        WatchUi.popView(SLIDE_IMMEDIATE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function pushView(transition) {
 | 
			
		||||
    function pushView(transition) as Void {
 | 
			
		||||
        WatchUi.pushView(self, new AlertDelegate(self), transition);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class AlertDelegate extends WatchUi.InputDelegate {
 | 
			
		||||
    hidden var mView;
 | 
			
		||||
    private var mView;
 | 
			
		||||
 | 
			
		||||
    function initialize(view) {
 | 
			
		||||
        InputDelegate.initialize();
 | 
			
		||||
        mView = view;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onKey(evt) {
 | 
			
		||||
    function onKey(evt) as Lang.Boolean {
 | 
			
		||||
        mView.dismiss();
 | 
			
		||||
        getApp().getQuitTimer().reset();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onTap(evt) {
 | 
			
		||||
    function onTap(evt) as Lang.Boolean {
 | 
			
		||||
        mView.dismiss();
 | 
			
		||||
        getApp().getQuitTimer().reset();
 | 
			
		||||
        return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@ using Toybox.Graphics;
 | 
			
		||||
using Toybox.Lang;
 | 
			
		||||
using Toybox.WatchUi;
 | 
			
		||||
using Toybox.Communications;
 | 
			
		||||
using Toybox.Timer;
 | 
			
		||||
 | 
			
		||||
class ErrorView extends ScalableView {
 | 
			
		||||
    private var mText            as Lang.String = "";
 | 
			
		||||
@@ -94,14 +95,15 @@ class ErrorView extends ScalableView {
 | 
			
		||||
        }
 | 
			
		||||
        if (!mShown) {
 | 
			
		||||
            instance.setText(text);
 | 
			
		||||
            mShown = true;
 | 
			
		||||
        }
 | 
			
		||||
        return [instance, instance.getDelegate()];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create or reuse an existing ErrorView, and pass on the text.
 | 
			
		||||
    static function show(text as Lang.String) as Void {
 | 
			
		||||
        create(text); // Ignore returned values
 | 
			
		||||
        if (!mShown) {
 | 
			
		||||
            create(text); // Ignore returned values
 | 
			
		||||
            WatchUi.pushView(instance, instance.getDelegate(), WatchUi.SLIDE_UP);
 | 
			
		||||
            // This must be last to avoid a race condition with unShow(), where the
 | 
			
		||||
            // ErrorView can't be dismissed.
 | 
			
		||||
@@ -112,6 +114,10 @@ class ErrorView extends ScalableView {
 | 
			
		||||
    static function unShow() as Void {
 | 
			
		||||
        if (mShown) {
 | 
			
		||||
            WatchUi.popView(WatchUi.SLIDE_DOWN);
 | 
			
		||||
            // The call to 'updateNextMenuItem()' must be on another thread so that the view is popped above.
 | 
			
		||||
            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), Globals.scApiResume, false);
 | 
			
		||||
            // This must be last to avoid a race condition with show(), where the
 | 
			
		||||
            // ErrorView can't be dismissed.
 | 
			
		||||
            mShown = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,5 +26,10 @@ class Globals {
 | 
			
		||||
    static const scDebug        = false;
 | 
			
		||||
    static const scAlertTimeout = 2000; // ms
 | 
			
		||||
    static const scTapTimeout   = 1000; // ms
 | 
			
		||||
    // Time to let the existing HTTP responses get serviced after a
 | 
			
		||||
    // Communications.NETWORK_RESPONSE_OUT_OF_MEMORY response code.
 | 
			
		||||
    static const scApiBackoff   = 1000; // ms
 | 
			
		||||
    // Needs to be long enough to enable a "double ESC" to quit the application from
 | 
			
		||||
    // an ErrorView.
 | 
			
		||||
    static const scApiResume    = 200;  // ms
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ using Toybox.Application;
 | 
			
		||||
using Toybox.Lang;
 | 
			
		||||
using Toybox.WatchUi;
 | 
			
		||||
using Toybox.Application.Properties;
 | 
			
		||||
using Toybox.Timer;
 | 
			
		||||
 | 
			
		||||
class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
    private var strNoApiKey          as Lang.String or Null;
 | 
			
		||||
@@ -37,19 +38,23 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
    private var strTrailingSlashErr  as Lang.String or Null;
 | 
			
		||||
    private var strAvailable         = WatchUi.loadResource($.Rez.Strings.Available);
 | 
			
		||||
    private var strUnavailable       = WatchUi.loadResource($.Rez.Strings.Unavailable);
 | 
			
		||||
    private var strUnconfigured       = WatchUi.loadResource($.Rez.Strings.Unconfigured);
 | 
			
		||||
 | 
			
		||||
    private var mApiKey              as Lang.String;
 | 
			
		||||
    private var mApiKey              as Lang.String or Null; // The compiler can't tell these are updated by
 | 
			
		||||
    private var mApiUrl              as Lang.String or Null; // initialize(), hence the "or Null".
 | 
			
		||||
    private var mConfigUrl           as Lang.String or Null; //
 | 
			
		||||
    private var mApiStatus           as Lang.String = WatchUi.loadResource($.Rez.Strings.Checking);
 | 
			
		||||
    private var mMenuStatus          as Lang.String = WatchUi.loadResource($.Rez.Strings.Checking);
 | 
			
		||||
    private var mHaMenu              as HomeAssistantView or Null;
 | 
			
		||||
    private var mQuitTimer           as QuitTimer or Null;
 | 
			
		||||
    private var mQuitTimer           as QuitTimer         or Null;
 | 
			
		||||
    private var mTimer               as Timer.Timer       or Null;
 | 
			
		||||
    private var mItemsToUpdate;           // Array initialised by onReturnFetchMenuConfig()
 | 
			
		||||
    private var mNextItemToUpdate    = 0; // Index into the above array
 | 
			
		||||
    private var mIsGlance            as Lang.Boolean = false;
 | 
			
		||||
 | 
			
		||||
    function initialize() {
 | 
			
		||||
        AppBase.initialize();
 | 
			
		||||
        mApiKey = Properties.getValue("api_key");
 | 
			
		||||
        onSettingsChanged();
 | 
			
		||||
        // ATTENTION when adding stuff into this block:
 | 
			
		||||
        // Because of the >>GlanceView<<, it should contain only
 | 
			
		||||
        // code, which is used as well for the glance:
 | 
			
		||||
@@ -110,24 +115,22 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
        strTrailingSlashErr  = WatchUi.loadResource($.Rez.Strings.TrailingSlashErr);
 | 
			
		||||
        mQuitTimer           = new QuitTimer();
 | 
			
		||||
 | 
			
		||||
        var api_url = Properties.getValue("api_url") as Lang.String;
 | 
			
		||||
 | 
			
		||||
        if ((Properties.getValue("api_key") as Lang.String).length() == 0) {
 | 
			
		||||
        if (mApiKey.length() == 0) {
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
                System.println("HomeAssistantApp getInitialView(): No API key in the application settings.");
 | 
			
		||||
            }
 | 
			
		||||
            return ErrorView.create(strNoApiKey + ".");
 | 
			
		||||
        } else if (api_url.length() == 0) {
 | 
			
		||||
        } else if (mApiUrl.length() == 0) {
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
                System.println("HomeAssistantApp getInitialView(): No API URL in the application settings.");
 | 
			
		||||
            }
 | 
			
		||||
            return ErrorView.create(strNoApiUrl + ".");
 | 
			
		||||
        } else if (api_url.substring(-1, api_url.length()).equals("/")) {
 | 
			
		||||
        } else if (mApiUrl.substring(-1, mApiUrl.length()).equals("/")) {
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
                System.println("HomeAssistantApp getInitialView(): API URL must not have a trailing slash '/'.");
 | 
			
		||||
            }
 | 
			
		||||
            return ErrorView.create(strTrailingSlashErr + ".");
 | 
			
		||||
        } else if ((Properties.getValue("config_url") as Lang.String).length() == 0) {
 | 
			
		||||
        } else if (mConfigUrl.length() == 0) {
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
                System.println("HomeAssistantApp getInitialView(): No configuration URL in the application settings.");
 | 
			
		||||
            }
 | 
			
		||||
@@ -215,6 +218,12 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
                if (!mIsGlance) {
 | 
			
		||||
                    mHaMenu = new HomeAssistantView(data, null);
 | 
			
		||||
                    mQuitTimer.begin();
 | 
			
		||||
                    if (Properties.getValue("widget_start_no_tap")) {
 | 
			
		||||
                        // As soon as the menu has been fetched start show the menu of items.
 | 
			
		||||
                        // This behaviour is inconsistent with the standard Garmin User Interface, but has been
 | 
			
		||||
                        // requested by users so has been made the non-default option.
 | 
			
		||||
                        pushHomeAssistantMenuView();
 | 
			
		||||
                    }
 | 
			
		||||
                    mItemsToUpdate = mHaMenu.getItemsToUpdate();
 | 
			
		||||
                    // Start the continuous update process that continues for as long as the application is running.
 | 
			
		||||
                    // The chain of functions from 'updateNextMenuItem()' calls 'updateNextMenuItem()' on completion.
 | 
			
		||||
@@ -225,7 +234,6 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
                        WatchUi.switchToView(mHaMenu, new HomeAssistantViewDelegate(false), WatchUi.SLIDE_IMMEDIATE);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                WatchUi.requestUpdate();
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
@@ -237,20 +245,48 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        WatchUi.requestUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    (:glance)
 | 
			
		||||
    function fetchMenuConfig() as Void {
 | 
			
		||||
        var options = {
 | 
			
		||||
            :method       => Communications.HTTP_REQUEST_METHOD_GET,
 | 
			
		||||
            :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
 | 
			
		||||
        };
 | 
			
		||||
        Communications.makeWebRequest(
 | 
			
		||||
            Properties.getValue("config_url"),
 | 
			
		||||
            null,
 | 
			
		||||
            options,
 | 
			
		||||
            method(:onReturnFetchMenuConfig)
 | 
			
		||||
        );
 | 
			
		||||
        if (mConfigUrl.equals("")) {
 | 
			
		||||
            mMenuStatus = strUnconfigured;
 | 
			
		||||
            WatchUi.requestUpdate();
 | 
			
		||||
        } else {
 | 
			
		||||
            var options = {
 | 
			
		||||
                :method       => Communications.HTTP_REQUEST_METHOD_GET,
 | 
			
		||||
                :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
 | 
			
		||||
            };
 | 
			
		||||
            if (! System.getDeviceSettings().phoneConnected) {
 | 
			
		||||
                if (Globals.scDebug) {
 | 
			
		||||
                    System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
 | 
			
		||||
                }
 | 
			
		||||
                if (mIsGlance) {
 | 
			
		||||
                    WatchUi.requestUpdate();
 | 
			
		||||
                } else {
 | 
			
		||||
                    ErrorView.show(strNoPhone + ".");
 | 
			
		||||
                }
 | 
			
		||||
                mMenuStatus = strUnavailable;
 | 
			
		||||
            } else if (! System.getDeviceSettings().connectionAvailable) {
 | 
			
		||||
                if (Globals.scDebug) {
 | 
			
		||||
                    System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
 | 
			
		||||
                }
 | 
			
		||||
                if (mIsGlance) {
 | 
			
		||||
                    WatchUi.requestUpdate();
 | 
			
		||||
                } else {
 | 
			
		||||
                    ErrorView.show(strNoInternet + ".");
 | 
			
		||||
                }
 | 
			
		||||
                mMenuStatus = strUnavailable;
 | 
			
		||||
            } else {
 | 
			
		||||
                Communications.makeWebRequest(
 | 
			
		||||
                    mConfigUrl,
 | 
			
		||||
                    null,
 | 
			
		||||
                    options,
 | 
			
		||||
                    method(:onReturnFetchMenuConfig)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Callback function after completing the GET request to fetch the API status.
 | 
			
		||||
@@ -322,7 +358,6 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
                        ErrorView.show("API " + mApiStatus + ".");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                WatchUi.requestUpdate();
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
@@ -333,23 +368,51 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
                    ErrorView.show(strUnhandledHttpErr + responseCode);
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
        WatchUi.requestUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    (:glance)
 | 
			
		||||
    function fetchApiStatus() as Void {
 | 
			
		||||
        var options = {
 | 
			
		||||
            :method       => Communications.HTTP_REQUEST_METHOD_GET,
 | 
			
		||||
            :headers      => {
 | 
			
		||||
                "Authorization" => "Bearer " + mApiKey
 | 
			
		||||
            },
 | 
			
		||||
            :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
 | 
			
		||||
        };
 | 
			
		||||
        Communications.makeWebRequest(
 | 
			
		||||
            Properties.getValue("api_url") + "/",
 | 
			
		||||
            null,
 | 
			
		||||
            options,
 | 
			
		||||
            method(:onReturnFetchApiStatus)
 | 
			
		||||
        );
 | 
			
		||||
        if (mApiUrl.equals("")) {
 | 
			
		||||
            mApiStatus = strUnconfigured;
 | 
			
		||||
            WatchUi.requestUpdate();
 | 
			
		||||
        } else {
 | 
			
		||||
            var options = {
 | 
			
		||||
                :method       => Communications.HTTP_REQUEST_METHOD_GET,
 | 
			
		||||
                :headers      => {
 | 
			
		||||
                    "Authorization" => "Bearer " + mApiKey
 | 
			
		||||
                },
 | 
			
		||||
                :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
 | 
			
		||||
            };
 | 
			
		||||
            if (! System.getDeviceSettings().phoneConnected) {
 | 
			
		||||
                if (Globals.scDebug) {
 | 
			
		||||
                    System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
 | 
			
		||||
                }
 | 
			
		||||
                mApiStatus = strUnavailable;
 | 
			
		||||
                if (mIsGlance) {
 | 
			
		||||
                    WatchUi.requestUpdate();
 | 
			
		||||
                } else {
 | 
			
		||||
                    ErrorView.show(strNoPhone + ".");
 | 
			
		||||
                }
 | 
			
		||||
            } else if (! System.getDeviceSettings().connectionAvailable) {
 | 
			
		||||
                if (Globals.scDebug) {
 | 
			
		||||
                    System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
 | 
			
		||||
                }
 | 
			
		||||
                mApiStatus = strUnavailable;
 | 
			
		||||
                if (mIsGlance) {
 | 
			
		||||
                    WatchUi.requestUpdate();
 | 
			
		||||
                } else {
 | 
			
		||||
                    ErrorView.show(strNoInternet + ".");
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                Communications.makeWebRequest(
 | 
			
		||||
                    mApiUrl + "/",
 | 
			
		||||
                    null,
 | 
			
		||||
                    options,
 | 
			
		||||
                    method(:onReturnFetchApiStatus)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setApiStatus(s as Lang.String) {
 | 
			
		||||
@@ -387,11 +450,26 @@ class HomeAssistantApp extends Application.AppBase {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    (:glance)
 | 
			
		||||
    function getGlanceView() {
 | 
			
		||||
    function getGlanceView() as Lang.Array<WatchUi.GlanceView or WatchUi.GlanceViewDelegate> or Null {
 | 
			
		||||
        mIsGlance = true;
 | 
			
		||||
        updateGlance();
 | 
			
		||||
        mTimer = new Timer.Timer();
 | 
			
		||||
        mTimer.start(method(:updateGlance), Globals.scApiBackoff, true);
 | 
			
		||||
        return [new HomeAssistantGlanceView(self)];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Required for the Glance update timer.
 | 
			
		||||
    function updateGlance() as Void {
 | 
			
		||||
        fetchMenuConfig();
 | 
			
		||||
        fetchApiStatus();
 | 
			
		||||
        return [new HomeAssistantGlanceView(self)];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Replace this functionality with a more central settings class as proposed in
 | 
			
		||||
    // https://github.com/house-of-abbey/GarminHomeAssistant/pull/17.
 | 
			
		||||
    function onSettingsChanged() as Void {
 | 
			
		||||
        mApiKey    = Properties.getValue("api_key");
 | 
			
		||||
        mApiUrl    = Properties.getValue("api_url");
 | 
			
		||||
        mConfigUrl = Properties.getValue("config_url");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,8 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Callback function after completing the GET request to fetch the status.
 | 
			
		||||
    // Terminate updating the toggle menu items via the chain of calls for a permanent network
 | 
			
		||||
    // error. The ErrorView cancellation will resume the call chain.
 | 
			
		||||
    //
 | 
			
		||||
    function onReturnGetState(responseCode as Lang.Number, data as Null or Lang.Dictionary or Lang.String) as Void {
 | 
			
		||||
        if (Globals.scDebug) {
 | 
			
		||||
@@ -74,8 +76,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
            System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Data: " + data);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Provide the ability to terminate updating chain of calls for a permanent network error.
 | 
			
		||||
        var keepUpdating = true;
 | 
			
		||||
        var status       = strUnavailable;
 | 
			
		||||
        switch (responseCode) {
 | 
			
		||||
            case Communications.BLE_HOST_TIMEOUT:
 | 
			
		||||
@@ -111,8 +111,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
                if (Globals.scDebug) {
 | 
			
		||||
                    System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: NETWORK_RESPONSE_OUT_OF_MEMORY, are we going too fast?");
 | 
			
		||||
                }
 | 
			
		||||
                // Pause updates
 | 
			
		||||
                keepUpdating = false;
 | 
			
		||||
                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), Globals.scApiBackoff, false);
 | 
			
		||||
@@ -135,7 +133,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
                    }
 | 
			
		||||
                    ErrorView.show(strApiUrlNotFound);
 | 
			
		||||
                }
 | 
			
		||||
                keepUpdating = false;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 405:
 | 
			
		||||
@@ -143,7 +140,7 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
                    System.println("HomeAssistantToggleMenuItem onReturnGetState() Response Code: 405. " + mIdentifier + " " + data.get("message"));
 | 
			
		||||
                }
 | 
			
		||||
                ErrorView.show("HTTP 405, " + mIdentifier + ". " + data.get("message"));
 | 
			
		||||
                keepUpdating = false;
 | 
			
		||||
                
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 200:
 | 
			
		||||
@@ -157,6 +154,8 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
                }
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
@@ -165,10 +164,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
                }
 | 
			
		||||
                ErrorView.show(strUnhandledHttpErr + responseCode);
 | 
			
		||||
        }
 | 
			
		||||
        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();
 | 
			
		||||
        }
 | 
			
		||||
        getApp().setApiStatus(status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -180,17 +175,18 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
            },
 | 
			
		||||
            :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
 | 
			
		||||
        };
 | 
			
		||||
        var keepUpdating = true;
 | 
			
		||||
        if (! System.getDeviceSettings().phoneConnected) {
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
                System.println("HomeAssistantToggleMenuItem getState(): No Phone connection, skipping API call.");
 | 
			
		||||
            }
 | 
			
		||||
            ErrorView.show(strNoPhone + ".");
 | 
			
		||||
            getApp().setApiStatus(strUnavailable);
 | 
			
		||||
        } else if (! System.getDeviceSettings().connectionAvailable) {
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
                System.println("HomeAssistantToggleMenuItem getState(): No Internet connection, skipping API call.");
 | 
			
		||||
            }
 | 
			
		||||
            ErrorView.show(strNoInternet + ".");
 | 
			
		||||
            getApp().setApiStatus(strUnavailable);
 | 
			
		||||
        } else {
 | 
			
		||||
            var url = Properties.getValue("api_url") + "/states/" + mIdentifier;
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
@@ -202,19 +198,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem {
 | 
			
		||||
                options,
 | 
			
		||||
                method(:onReturnGetState)
 | 
			
		||||
            );
 | 
			
		||||
            // 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);
 | 
			
		||||
            if (Globals.scDebug) {
 | 
			
		||||
                System.println("HomeAssistantToggleMenuItem getState(): Updated failed " + mIdentifier);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user