How to get a value from this object?

I have the following data returned by my Ecowitt weather station:

{time=>1723724790, data=>{rainfall=>{yearly=>{unit=>mm, time=>1723724776, value=>0.0}, daily=>{unit=>mm, time=>1723724776, value=>0.0}, rain_rate=>{unit=>mm/hr, time=>1723724776, value=>0.0}, weekly=>{unit=>mm, time=>1723724776, value=>0.0}, hourly=>{unit=>mm, time=>1723724776, value=>0.0}, event=>{unit=>mm, time=>1723724776, value=>0.0}, monthly=>{unit=>mm, time=>1723724776, value=>0.0}}, battery=>{sensor_array=>{unit=>, time=>1723724776, value=>0}}, outdoor=>{humidity=>{unit=>%, time=>1723724776, value=>51}, app_temp=>{unit=>℃, time=>1723724776, value=>31.2}, dew_point=>{unit=>℃, time=>1723724776, value=>18.3}, feels_like=>{unit=>℃, time=>1723724776, value=>30.4}, temperature=>{unit=>℃, time=>1723724776, value=>29.5}}, indoor=>{humidity=>{unit=>%, time=>1723724776, value=>59}, temperature=>{unit=>℃, time=>1723724776, value=>26.8}}, pressure=>{relative=>{unit=>inHg, time=>1723724776, value=>27.99}, absolute=>{unit=>inHg, time=>1723724776, value=>27.99}}, solar_and_uvi=>{solar=>{unit=>W/m², time=>1723724776, value=>202.5}, uvi=>{unit=>, time=>1723724776, value=>1}}, wind=>{wind_gust=>{unit=>km/h, time=>1723724776, value=>9.4}, wind_direction=>{unit=>º, time=>1723724776, value=>149}, wind_speed=>{unit=>km/h, time=>1723724776, value=>6.5}}}, msg=>success, code=>0}

How can I get the value of the outdoor temperature (data.outdoor.temperature.value)?

I tried the following and got a crash:

var temp = data["data"]["outdoor"]["temperature"]["value"];
var unit = data["data"]["outdoor"]["temperature"]["unit"];

Thanks in advance

Best regards

Aaron

  • What's the crash?  You may want to split things up a bit, like this (this is in my ecowitt app) "curdata"is what you call "data"

            if(curData!=null) {
                var data=curData["data"];          
                var outdoor=data["outdoor"];
                var indoor=data["indoor"];
                var time=curData["time"].toNumber();
                var oTemp=(outdoor!=null) ? ""+outdoor["temperature"]["value"]+degree : "--.-"+degree;
                var oHumid=(outdoor!=null) ? ""+outdoor["humidity"]["value"]+"%" : "--%";
                var iTemp=(indoor!=null) ? ""+indoor["temperature"]["value"]+degree : "--.-"+degree;
                var iHumid=(indoor!=null) ? ""+indoor["humidity"]["value"]+"%"
    ... }

    Also, you may want to try this on a real devices as soon as you can.  My app works in the sim, but fails on a real watch.  I didn't dig into it too much, as I just get the data by way of Weather Underground. 

    If you send your data to WU, you can get an APIKey to access data, and that can be your ecowitt or the nearest PWS to where you might be.  Here's my widget for that:

    https://apps.garmin.com/apps/f509fc4e-7f1f-48a5-b337-ed86668c5f6c

    The widget publishes complications, and if your Garmin supports them, you can display the data on your own watch face

  • So I implemented your code into my app and it gave me a crash on this:

    var outdoor = dataObj["outdoor"];

    The crash message:

    Error: Unhandled Exception
    Exception: UnexpectedTypeException: Expected Number, given String
    Stack: 
      - onReceive() at C:\Users\aaron\GarminDev\garmin-wetterstation\source\garmin-wetterstationView.mc:38 0x10000159 

  • Is dataObj exactly what you get back from the makeWebRequest callback?

    What do you see if you do a

    System.println(dataObj);

  • dataObj gets set in my split-up version of the code, which is this:

    var dataObj = data["data"];
    System.println(dataObj);
    var outdoor = dataObj["outdoor"];
    var indoor = dataObj["indoor"];
    var oTemp = outdoor["temperature"]["value"] + degree;
    var oHumid = outdoor["humidity"]["value"] + "%";
    var iTemp = indoor["temperature"]["value"] + degree;
    var iHumid = indoor["humidity"]["value"] + degree;

    When printing out dataObj, I get the following output:

    {rainfall=>{yearly=>{unit=>mm, time=>1723728803, value=>0.0}, daily=>{unit=>mm, time=>1723728803, value=>0.0}, rain_rate=>{unit=>mm/hr, time=>1723728803, value=>0.0}, weekly=>{unit=>mm, time=>1723728803, value=>0.0}, hourly=>{unit=>mm, time=>1723728803, value=>0.0}, event=>{unit=>mm, time=>1723728803, value=>0.0}, monthly=>{unit=>mm, time=>1723728803, value=>0.0}}, battery=>{sensor_array=>{unit=>, time=>1723728803, value=>0}}, outdoor=>{humidity=>{unit=>%, time=>1723728803, value=>49}, app_temp=>{unit=>℃, time=>1723728803, value=>31.7}, dew_point=>{unit=>℃, time=>1723728803, value=>17.6}, feels_like=>{unit=>℃, time=>1723728803, value=>30.1}, temperature=>{unit=>℃, time=>1723728803, value=>29.4}}, indoor=>{humidity=>{unit=>%, time=>1723728803, value=>58}, temperature=>{unit=>℃, time=>1723728803, value=>27.2}}, pressure=>{relative=>{unit=>inHg, time=>1723728803, value=>27.98}, absolute=>{unit=>inHg, time=>1723728803, value=>27.98}}, solar_and_uvi=>{solar=>{unit=>W/m², time=>1723728803, value=>710.4}, uvi=>{unit=>, time=>1723728803, value=>6}}, wind=>{wind_gust=>{unit=>km/h, time=>1723728803, value=>5.4}, wind_direction=>{unit=>º, time=>1723728803, value=>137}, wind_speed=>{unit=>km/h, time=>1723728803, value=>1.4}}}

  • if you look at the whole result of your println, do you see "outdoor"?

    Something like

    outdoor=>{humidity=>{unit=>%, time=>1723729386, value=>44}.......

    What are you using for an outdoor sensor?

    Here's the parameters I use in my makeWebRequest (I removed things like my keys and mac address

    var param={
    	    	"application_key" => "hidden",
    	    	"api_key"=>"hidden",
    			"mac" => "hidden",
    			"callback" => "all"	

  • My parameters look like this:

       var params = {
          // set the parameters
          "application_key" => Application.Properties.getValue("appkey"),
          "api_key" => Application.Properties.getValue("apikey"),
          "mac" => Application.Properties.getValue("stationMAC"),
          "call_back" => "all",
          "temp_unitid" => 1,
          "wind_speed_unitid" => 7,
          "rainfall_unitid" => 12,
        };

    The Properties are reading correctly, I verified it using System.println()...

  • Notice i have the

    "callback" => "all"

    It's been a while, but I seem to remember that impacts what data gets sent back  Looks like you have an extra comma after the 12.  

    Do you see outdoor in the data as I showed?

  • I see the outdoor data (as shown when I posted the printed data) and even without the extra comma after the 12 and with or without the "call_back", I get the same crash as before but I think I now know why...

    I think that the Ecowitt API has some sort of rate limit and I ran into it, leading to an error message and thus data that isn't what the program expected...

  • I haven't run into a limit but it wouldn't surprise me.  Right now I have a home automation server that gets the data every 2 minutes and it runs fine.

    in the callback for the makeWebRequest, do you see something other than 200 for a responseCode?

    Something like

        function receiveData(responseCode, data) {
            if(responseCode==200) {
                curData=data;
            }
         }
    could help avoid the crash...
  • I have now found a way to not run into rate limits (just poll every 4 seconds instead of every watch onUpdate() run, as the limit is once per second.

    I remember however that the code was still 200, there was just a different response (data wasn't there)...