Memory usage

I'm developing an app (watch face for FR645) and having a few problems with memory usage. It seems that when an HTTP GET returns with too large a JSON, the app crashes ("Encountered an app crash") - no stack trace, no exception, nothing. As someone with a C++ background, I'm quite surprised at this behavior. Now, I know people make apps that display a lot of weather data, which is only accessible through large JSONs. It appears that a number of the open source projects use an independent website to forward the HTTP request to the weather website, parse it down to a manageable size, and return it. At best, this only reduces the size by about 50%, which doesn't seem all that substantial. My questions are:

1. Is it standard to use an independent website for HTTP requests?

2. Is there a better way to handle the memory usage so it doesn't go over?

3. Is there a way to check how much memory is left available?

I'd appreciate your thoughts.

  • 1) No.  but I use both OpenWeatherMaps and Weather Underground and have for a long time.

    2) with both of those, and parameters in the request, I can handle both in background processes. 

    On some, a background can max at 32k.  But out of that 32k, your AppBase gets loaded, globals for your app, your code with the background annotation, and the data that's used. And when it comes to makeWebRequests(), the data is received in JSON format, and it needs to be converted to a dictionary, which can really increase the size depending on the complexity (consider at least double while the conversion is taking place).  It's not just "the response is only 2k long".  Also, you are limited to about 8k in what can be returned to the main app by way of Background.exit().  And if a watch face has a max of say 92k, your background code counts towards that, so if the background is 15k, that takes away from the memory for your watch face, cutting that way down.

    3)Sys.getSystemStats().usedMemory; (or availableMemory)

    With 3.2 devices, you can skip this whole thing and just use the new Weather Module in CIQ, and just use the Garmin weather data already on the watch.

  • 1) and 2) Interesting, I was working with OpenWeather and Accuweather and haven't been able to get the parameters to filter it down. I had no idea the memory restrictions, that makes a lot of sense. Maybe I can parse the JSON before exiting the background thread.

    With 3.2 devices, you can skip this whole thing and just use the new Weather Module in CIQ, and just use the Garmin weather data already on the watch.

    Apparently I'm an idiot, not sure how I missed this. Thank you very much, good sir.

  • I was thinking of darksky with the parameters to reduce data.  I don't need to do that with OWM or WU.

    Here's a watch face of mine that uses garmin weather if you want to see how it works - It's also got on device settings:

    apps.garmin.com/.../c051f37a-8fad-4907-b124-0112fe010c91.

  • Looks like Dark Sky is no longer available: https://blog.darksky.net/. So I can't test their API to see what size a response they provide.

    OWM is the one I'm using. Maybe I missed something, but while there is an API for current conditions that returns a reasonable size, I haven't found one like that yet for future conditions.

    Not sure if you intended it that way or not, but I can't see the source code for that app. So I can see the results, but not how you did it.

  • Yes, darksky is pretty much gone.  Any time you're trying to get a forecast (hourly, daily), you're talking a large amount of data, and doing it in a background services will be very difficult.

    Here's a small bit of code where I display the hourly forcase using what's in 3.2.  It's really pretty simple.

    hasWeather I declare at the class level, and in initialize() I set it with 

    hasWeather=(Toybox has :Weather);

    makeTime and makeTemp are just helper functions to display the time and temp is a friendly format.  Code blocks don't seem to be working today..  Sorry.

    if(hasWeather) {

    var hf=Weather.getHourlyForecast();
    if(hf==null) {
    dc.drawText(centerW,y,largeFont,"No 1hr forecast",Gfx.TEXT_JUSTIFY_CENTER);
    } else {
    var sz=hf.size();
    dc.drawText(centerW,y,smallFont,"1hr forecast ok, sz="+sz,Gfx.TEXT_JUSTIFY_CENTER);
    y+=smallHeight;

    var i=0;
    while(i<sz) {
    dc.drawText(width*.33,y,smallFont,makeTime(hf[i].forecastTime)+" "+makeTemp(hf[i].temperature)+degree,Gfx.TEXT_JUSTIFY_CENTER);
    i++;
    if(i<sz) {
    dc.drawText(width*.66,y,smallFont,makeTime(hf[i].forecastTime)+" "+makeTemp(hf[i].temperature)+degree,Gfx.TEXT_JUSTIFY_CENTER);
    i++;
    }
    y+=smallHeight;
    }

    }
    } else {
    dc.drawText(centerW,y,largeFont,"Weather NA",Gfx.TEXT_JUSTIFY_CENTER);
    }

  • Dark sky is gone.  An alternative you may look into is AerisWeather.  Their API gives many options to filter and request specific data, however their API is not free.

    www.aerisweather.com

  • So, I looked into the weather options for 3.2 - and I understand you had some influence there, and honestly it looks like it will be really nice someday.

    Unfortunately, a lot of devices are not at 3.2 yet, and it is still missing quite a few pieces of information one might want about the weather. Hopefully it will get there in the future.

  • The info in 3.2 appears to be only what's needed for Garmin's weather widget.  What the watch already had is just being exposed in CIQ.  

    I really doubt the memory available for a background service will change, so you got that limit as to what you can do.

  • same problem for me, the hourly seem to return too much data sometimes and haven't find a way to limit the hour range

  • Former Member
    0 Former Member over 4 years ago in reply to Scott

    Dark sky might be coming back. But it is not the same as it used to be. You can try Climacell API. They have various plans that you can choose from according to your needs.