Background.registerForTemporalEvent update problem.

Hello, I have a question and I would like to ask for your help if possible.
Here I will describe my problem in more detail.
I am making a WatchFace (only for myself), I use OpenWeatherMap as a provider for weather data.

When I try to call Refresh weather, sometimes it only updates after an hour.
Is there any way to detect that the weather update failed and call it immediately (back)? I know that Background.registerForTemporalEvent
can only be called every five minutes, but I don't know how to call the update request back.
The weather refresh interval is set by myself via Application.Properties.getValue("WU")
Before I wrote to this forum, I tried to find a solution that would be useful but unsuccessfully.

Here I am attaching my code that I am using:

var lastTime = Background.getLastTemporalEventTime();
var nextEvent = lastTime != null ? lastTime.add(new Time.Duration(5)) : Time.now();
Background.registerForTemporalEvent(nextEvent);
System.println("WU =  5 min.");
}
            } else {
            
            }   
  Background.registerForTemporalEvent(new Time.Duration(Application.Properties.getValue("WU") * 60));
System.println("WU User."+ Application.Properties.getValue("WU"));
            }
        }

Thank you

  • if I change the update time (number) in the string (wu)
    , the weather will be updated according to the string setting, in our case "WU", where wu represents a number.

    Again, it's not clear to me whether WU is a string setting or a numerical setting.

    It sounds like it's a string setting where the user is supposed to type a number or "disable"? I don't think this is a good idea: the user can type anything they want, so it's not very user friendly. You wouldn't be able to restrict the range of input like you could with a numerical setting.

    It makes more sense to have an optional numerical setting, which will come back as Number or Null. Something like this:

    <setting propertyKey="@Properties.WU" title="@Strings.WU>
        <settingConfig type="numeric" required="false" min=5>
    </setting>

    I wanted to achieve that if I have Bluetooth turned off and the user-set time (wu) after the update evaluates that Bluetooth is off, the next update will be 5*60, and after five minutes, if Bluetooth is turned on again, the weather will be updated according to the string setting,

    I get it, that is something you can work on yourself.

    Here's a hint:

    function isNetworkAvailable() as Boolean {
        var settings = System.getDeviceSettings();
        if (settings has :connectionAvailable) {
            return settings.connectionAvailable;
        }
        return settings.phoneConnected;
    }
    

    You can call this function every so often, and save the last value (true or false). When the value changes, you can re-register your temporal event using the logic you want (i.e. 5 minutes when network is not available, user-defined time when network is available.)

  • Understand that not being connected to the phone is only one of the things to deal with, as you can get other errors with the makeWebRequest. like the phone doesn't have cell service. or the server you are trying to get to is down, so you may not want to focus on just one thing. and there could be cases where you don't even want to do the makeWebrRequest, like if an API Key or location is required and you don't have that.

    And when it comes to weather data. while you may request it every X minutes, it doesn't mean it's new data every X minutes.  That can depend on the service you are using, as well as the specific weather station you are referencing.  I've seen cases where the data might change on the server every few seconds, to only changing every hour.  With the Garmin Weather API, I never see the data more than once an hour for example.

    I'd start simple and get things working and handling different errors, etc.

  • no, WU is predefined in Settings.xml and selection is possible with fixed values. I don't want the weather update time to be written in the settings

  • Ok, so it's an enum. Gotcha. Honestly it doesn't matter as long as you are able to able to read the value and act on it appropriately.

    I just wasn't sure what type of setting "WU" was supposed to be, since you said it could have a value of "Disable" and you also said "if I change the update time (number) in the string (wu)".

    If I can't see the code for the "WU" setting, then I just have to guess what it is based on the code you posted, and if you say stuff like ""WU" limit is set to "Disable"" and WU is somehow both a number and a string, it's confusing to me.

    You realize that you didn't post your code for the "WU" setting and the code you did post says nothing about "Disable", so when you mention "Disable", it doesn't mean anything to the reader beyond what can be guessed.

    I don't want the weather update time to be written in the settings

    I'm not sure exactly what you mean by this, but the suggestion was just to allow the user to type any number of minutes they wanted (like 5, 6, 7, ..., 60, ...), as long as the value is greater or equal to 5. Whether you use a predefined enum or you allow the user to freely type in a number, the value is still "written in the settings".

    If you mean you don't want the weather update date/time to be written to settings (like 2025-04-11 11:01:30), I was not suggesting that at all.

    An enum is fine, and probably more user-friendly.

  • Sorry I can't be of much help, but I can't post the source code on the forum, so I'm just relying on short snippets. I know you have no divination skills and I appreciate your patience. I'm putting here what is WU and what is Disable, it's zero, so there's no time for weather updates.

    <setting propertyKey="@Properties.WU" title="@Strings.WU">
    <settingConfig type="list">
    <listEntry value="0">@Strings.m0</listEntry>
    <listEntry value="15">@Strings.m15</listEntry>
    <listEntry value="30">@Strings.m30</listEntry>
    <listEntry value="60">@Strings.m60</listEntry>
    <listEntry value="120">@Strings.m120</listEntry>
    <listEntry value="180">@Strings.m180</listEntry>
    <listEntry value="240">@Strings.m240</listEntry>
    </settingConfig>
    </setting>

    Now I would still need to put all the codes you wrote into one common function. I think you already know what I wanted and I tried to explain how I would like the weather update to work on my watch. Even though Jimm is right that it is different when the web request fails, but despite that I want to have one function that will work as follows:

    - default value for weather update 5*60

    - after the user selects the update time, it will be updated at user-set intervals

    - if Bluetooth is turned off, the weather update is 5*60

    - if Bluetooth is turned on, the next weather update frequency will be according to the user-set I don't want anything else and I understand the consequences.

    Thank you

  • I'm putting here what is WU and what is Disable, it's zero, so there's no time for weather updates.

    Thank you for explaining this.

    <setting propertyKey="@Properties.WU" title="@Strings.WU">
    <settingConfig type="list">
    <listEntry value="0">@Strings.m0</listEntry>
    <listEntry value="15">@Strings.m15</listEntry>
    <listEntry value="30">@Strings.m30</listEntry>
    <listEntry value="60">@Strings.m60</listEntry>
    <listEntry value="120">@Strings.m120</listEntry>
    <listEntry value="180">@Strings.m180</listEntry>
    <listEntry value="240">@Strings.m240</listEntry>
    </settingConfig>
    </setting>

    As this is a list setting, the values are in fact numbers [and they come back as Number when you call Properties.getValue]. I know you know this, but it wasn't 100% clear/certain before you said you had predefined values.

    [1/x]

  • I assume you must have a WU property whose type is number:

    it's zero, so there's no time for weather updates.

    The example code I posted would need to be changed slightly to handle this case.

    Now I would still need to put all the codes you wrote into one common function.

    Yeah, and I was kinda hoping this was something you could try on your own. Of course as a new dev to Monkey C you cannot know everything, but at some point you have to learn to put the building blocks together.

    Anyway, here's some code which should do what you want.

    EDIT:

    - fixed logic for using user update setting when network is connected

    - assume that when user update setting is 0 (disabled) and bluetooth is disconnected, updates should be disabled (this wasn't in the "requirements" above, it makes sense to me though). If you want something different, you should be able to change the code yourself.

    https://pastebin.com/gXhU7vUh

    [2/2]

  • btw I think it's pointless to have logic which changes the update period to 5 minutes when the network isn't connected, because when that happens, you *know* that all update requests will fail. If you are trying to get the first update after the network reconnects to come out immediately (or asap), there are other ways to do that.

    If I was going to have logic that's conditional on the network status at all, I would do it this way:

    - while network is connected, use user update setting for recurring temporal events

    - when network changes from connected to disconnected, stop temporal events

    - when network changes from disconnected to connected, use user update setting for temporal events. I *think* this should result in a temporal event being triggered asap, but if you want to be sure, you could schedule a one-time temporal event for last event time + 5 minutes, and when that event is triggered, you could reschedule the recurring temporal events based on user settings again.

    But it's up to you.

  • Let me thank you very much and give recognition for the great help.

    Maybe it's unnecessary, but I don't want things to remain unexplained, so I'll try to defend my logic more, why I wanted to have the weather function built like this.

    I work in a place where there are certain signal jammers and other technologies that do not allow me to have an overview of the current weather data.

    Now the explanation why I wanted to have the weather update time repeated in the interval (5*60).

    Imagine that you are in a place where you don't have regular Bluetooth coverage and you want to occasionally look at your watch and see, for example, how many degrees Celsius it is outside currently.

    But a few minutes ago the watch was disconnected from the phone, so without a signal, including Bluetooth, you won't get any data.

    So if you show up in another place (for example, lunch) where you already have a regular signal, you have to wait for it again until the interval you set, i.e. "WU", expires. And that can easily be 15-20 minutes. Originally, I wanted to do it so that if the watch loses signal and I don't get the desired weather, a small icon would appear on the watch display, but that's a lot of programming.

    Since you suggested a function that can return the weather update to five minutes out of coverage, I have to assume that the data on the watch is outdated and that the update did not take place. I will only see that the update was successful when I see the update time, for example 20:15, on the watch display.

    On the other hand, it's WF only for me, so I don't limit anyone else, just myself.

    Yes, you are certainly right that things can be solved in other ways, but that is more demanding for me and I am happy with what I have.

    Thanks again.

    If you want to put your logic that you write about here for other users, I will be happy. And then I can decide what will be more comfortable for me to use.

  • So if you show up in another place (for example, lunch) where you already have a regular signal, you have to wait for it again until the interval you set, i.e. "WU", expires. And that can easily be 15-20 minutes. Originally, I wanted to do it so that if the watch loses signal and I don't get the desired weather, a small icon would appear on the watch display, but that's a lot of programming.

    Yes that was my understanding - thank you for clarifying. As I said above, I don't think the logic that you requested is necessary to accomplish what you want: when the network connection changes from disabled to enabled, you want the next request to go out as soon as possible.

    And it's possibly not sufficient.

    Suppose I call registerForTemporalEvent with a duration of X minutes (repeating event). There's two possible ways it can work, for the next event:

    A) the next event happens in X minutes (which is too slow for your requirements, if the X is the user setting, and the network connection was just enabled)

    or

    B) the next event happens as soon as possible (either now, or at the time of the last event + 5 minutes, which ever is later).

    I think you are assuming A), based on what you said, which is fine. (Honestly I'm not 100% sure how it works, but when I test in the sim, the first temporal event seems to happen immediately, even though the duration is at least 5 minutes. I think I've seen the same behaviour testing on the device, too. And I think I've seen similar behaviour with CIQ watchfaces, although ofc most of them don't publish their source. So I actually assume B)

    So let's assume A) and apply it to these requirements:

    - default value for weather update 5*60

    - after the user selects the update time, it will be updated at user-set intervals

    - if Bluetooth is turned off, the weather update is 5*60

    - if Bluetooth is turned on, the next weather update frequency will be according to the user-set I don't want anything else and I understand the consequences.

    And let's assume the user interval is 60 minutes, just for the sake of this exercise.

    While the network is connected, update requests happen every 60 minutes.

    If the user turns off bluetooth, update requests will happen every 5 minutes. (But bluetooth is disconnected, so these requests have no effect.)

    Now when the user turns on bluetooth, update requests happen every 60 minutes. According to A), the next request after turning on bluetooth happens in 60 minutes (not immediately), which doesn't really accomplish what you want.

    Now let's say it works like B) instead. Then the next request after turning on bluetooth happens as soon as possible, which is what you want.

    Regardless of whether A or B is true, it does not help to request updates every 5 minutes while the network is disabled. You may as well just disable updates during this time, or even more simply, leave updates unchanged. Actually, if you disable updates while the network is disabled, you gain the small advantage that the first update that happens after the network is enabled has a greater change of going out *immediately* (as opposed to having to wait up to 5 minutes).

    And if A is true, then the logic / code has to be changed so that when the network changes from disabled to enabled:

    - you have to schedule a one time temporal event for (last event time +  5 minutes). (If this is in the past, it will happen immediately)

    - when this event fires, you need to reschedule a repeating temporal event for the user duration

    As this makes your code more complex, I think it would be important to figure out whether A or B is true.