Is there a way to handle asynchronous operations?

I am working on a project where I need the Wifi status (connected or disconnected) for further Operations. I made a class for the wifi with some basic function:

using Toybox.Communications as Comm;
using Toybox.System as Sys;

class wifiScan {
    var wifiStatus = false;
    var errorCode;

    function initialize() {
        System.println("initialize() called: wifiStatus=" + wifiStatus);
    }

    function getStatus(){
        System.println("getStatus() called: Returning wifiStatus=" + wifiStatus);
        return wifiStatus;
    }

    function getError(){
        return errorCode;
    }

    function checkWifiConnection() {
        Comm.checkWifiConnection(method(:onWifiConnectionStatus));
        System.println("checkWifiConnection() called");
    }

    // Callback method for checkWifiConnection
    function onWifiConnectionStatus(result) {
        wifiStatus = result[:wifiAvailable];
        errorCode = result[:errorCode];
        System.println("onWifiConnectionStatus() called: wifiAvailable=" + wifiStatus);
    }

}

The problem is that if I want to use the getStatus() function in another file but I get the wrong result (false) because it runs quicker than onWifiConnectionStatus. The result in the console is as follows:


initialize() called: wifiStatus=false
checkWifiConnection() called
getStatus() called: Returning wifiStatus=false
onWifiConnectionStatus() called: wifiAvailable=true

Naturally, I tried to handle this by setting up a callback. I setup the callback as follows:
using Toybox.Communications as Comm;
using Toybox.System as Sys;

class wifiScan {
    var wifiStatus = false;
    var errorCode;
    var callbackMethod;
    
    function initialize() {
        System.println("initialize() called: wifiStatus=" + wifiStatus);
    }

    function getStatus(){
        System.println("getStatus() called: Returning wifiStatus=" + wifiStatus);
        return wifiStatus;
        //System.println("Wifi connection unavailable");
    }

    function getError(){
        return errorCode;
        //System.println("Error: " + errorCode);
    }

    function checkWifiConnection(methodObj) {
        callbackMethod = methodObj; // Store the Method object
        Comm.checkWifiConnection(method(:onWifiConnectionStatus));
        System.println("checkWifiConnection() called");
    }

    // Callback method for checkWifiConnection
    function onWifiConnectionStatus(result) {
        wifiStatus = result[:wifiAvailable];
        errorCode = result[:errorCode];
        System.println("onWifiConnectionStatus() called: wifiAvailable=" + wifiStatus);

                // Invoke the callback, if it exists
        if (callbackMethod != null) {
            callbackMethod.invoke(); // Invoke the callback method
        }
    }
}
 
and I call it as such:
var result = gps.method(:getStatus);
var wifi = new wifiScan(result);
This made the code in the intended order. However, there is no way for me to use the variable wifiStatus outside the class since the variable 'result' is of type Obj. Is there a way to get around this? like 'await' in other programming languages for example? I tried polling but I ran into a watchdog error
  • Ok, the first thing is on a watch with wifi, it is RARLEY connected.  Only if there is a bulk download (including new firmware when requested) or media sync (think music - when requested)

    Wifi available and wifi connected are two very different things.  Available means the device has wifi.  Connected means it's connected (again, very rare on a watch.)  Wifi burns a whole bunch of battery when it's on.  In fact, some devices won't allow you to get music or download new firmware over wifi if the battery is too low.  With some you can't download music unless you are connected to a charger

    If wifi is turned on it can take some time (a minute?) to find a connection.

    Also, Monkey C is single threaded.  Everything is syncronous, If your code is running, it is never interrupted by any of your other code.  It's only when your code returns to the VM can some of your other code run.

    Let's say you create a timer that fires every 100ms but your onUpdate() function runs for 200ms.  When the timer ticks, it's callback won't run until onUpdate() completes

  • Yes I do understand the difference between them, t was just pure miswording on my part. I apologize for that. I am indeed trying to use Wifi Available for a geofencing application. The idea is that when there is no wifi available it will trigger another function. What I am struggling with though is being able to use this value outside a class. the value is stored in the callback method which in turn, is not callable outside the class. And if I try to call it through another a seperate method like getStatus, it ends up running before the callback method.

  • The simplest solution (but maybe not the best) is to just save the value in a global that you can access wherever you want.

    Your larger problem is that the watch won't even be scanning for networks the vast majority of the time

  • I was planning to check for WiFi availability every specific interval (on a timer). Do you recommend that I do the whole program in one file then?

  • Again understand that you can't see what you might think you can.  Your app could be one file or 10 files.  It makes no difference as your app gets compiled into the prg file.

    Have you ever used a Garmin watch with wifi?

  • it's clear now thank you! to answer your question it's my first time using a Garmin watch and my first time programming one.