RESTful API - json attributes for weather API

Hoping to get some help integrating with a weather API.

I have looked at a number of examples and docs - sadly couldn’t find anything that was similar enough to get me on the right track.

The API I am trying to integrate with metocenapi API (Swagger UI) for a weather service. This provides json response with time stamps within dimensions, and then the temperature/humidity/windspeed as variables. Example below:

{
    "dimensions": {
        "point": {
            "type": "point",
            "units": "unknown",
            "data": [
                {
                    "lon": xx
                    "lat": xxx
                }
            ]
        },
        "time": {
            "type": "time",
            "units": "unknown",
            "data": [
                "2023-11-18T23:45:36.47Z",
                "2023-11-19T00:45:36.47Z",
                "2023-11-19T01:45:36.47Z",
                "2023-11-19T02:45:36.47Z",
                "2023-11-19T03:45:36.47Z",
                "2023-11-19T04:45:36.47Z",
                "2023-11-19T05:45:36.47Z",
                "2023-11-19T06:45:36.47Z",
                "2023-11-19T07:45:36.47Z",
                "2023-11-19T08:45:36.47Z",
                "2023-11-19T09:45:36.47Z",
                "2023-11-19T10:45:36.47Z",
                "2023-11-19T11:45:36.47Z",
                "2023-11-19T12:45:36.47Z",
                "2023-11-19T13:45:36.47Z",
                "2023-11-19T14:45:36.47Z",
                "2023-11-19T15:45:36.47Z",
                "2023-11-19T16:45:36.47Z",
                "2023-11-19T17:45:36.47Z",
                "2023-11-19T18:45:36.47Z",
                "2023-11-19T19:45:36.47Z",
                "2023-11-19T20:45:36.47Z",
                "2023-11-19T21:45:36.47Z",
                "2023-11-19T22:45:36.47Z",
                "2023-11-19T23:45:36.47Z"
            ]
        }
    },
    "noDataReasons": {
        "ERROR_INTERNAL": 4,
        "FILL": 1,
        "GAP": 5,
        "GOOD": 0,
        "INVALID_HIGH": 3,
        "INVALID_LOW": 2
    },
    "variables": {
        "air.temperature.at-2m": {
            "standardName": "air_temperature_at_2m_above_ground_level",
            "units": "degreeK",
            "siUnits": "K",
            "dimensions": [
                "time",
                "point"
            ],
            "data": [
                290.90552,
                290.93613,
                290.94275,
                290.9494,
                290.95602,
                290.96268,
                290.96927,
                290.90356,
                290.81494,
                290.72635,
                290.63776,
                290.54913,
                290.4605,
                290.37283,
                290.2854,
                290.198,
                290.1106,
                290.02316,
                289.93576,
                289.92242,
                289.9325,
                289.94257,
                289.95264,
                289.9627,
                289.97278
            ],
            "noData": [
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ]
        }
    }
}

I am struggling to work out how to create sensors that will provide the correct data as attributes, and work out how that can link back to the time dimension.

Example above I have only air temperature, but I plan to pull back several. The other variables are set up the same as "air.temperature.at-2m, all linking back to the time dimension.

I was going down the past of a RESTful (RESTful - Home Assistant) rest sensor, using json_attributes from what I could work out from various examples/documentation.

I tried to look through the forums for similar examples - couldn’t find anything similar.

If someone could help point me in the right direction, I will really appreciate it!

Please provide an exampe of what you want to have in the end
Do you want one sensor on air temp containing attributes being a list of TIME and TEMP? What would be the end-use…graph?

1 Like

Thanks for the reply!

Basically - I would like to replace the functionality of the OpenWeatherMap forecast. I have found that the weather integrations to be not as good as our local metservice in NZ. I have just found they have an API, but there are no integrations yet.

My main issue is I don’t really know what is best. It would be nice to have a forecast sensor to give me weather forecast similar to OpenWeatherMap, and use this in TTS notifications for morning updates, etc.

The full JSON response with the other variables I have pasted below, as it is likely easier to have a sensor with multiple attributes per hour block. The API call is an hourly interval with 24 repeats to give me an hourly 24hr forecast. If I can get this one going, I can work on multiple days, etc.

I presume a single sensor could have a list of time and the various variables (temp, wind speed, etc) but given I can’t work it out I am not sure! :slight_smile:

{
    "dimensions": {
        "point": {
            "type": "point",
            "units": "unknown",
            "data": [
                {
                    "lon": x,
                    "lat": x
                }
            ]
        },
        "time": {
            "type": "time",
            "units": "unknown",
            "data": [
                "2023-11-18T23:45:36.47Z",
                "2023-11-19T00:45:36.47Z",
                "2023-11-19T01:45:36.47Z",
                "2023-11-19T02:45:36.47Z",
                "2023-11-19T03:45:36.47Z",
                "2023-11-19T04:45:36.47Z",
                "2023-11-19T05:45:36.47Z",
                "2023-11-19T06:45:36.47Z",
                "2023-11-19T07:45:36.47Z",
                "2023-11-19T08:45:36.47Z",
                "2023-11-19T09:45:36.47Z",
                "2023-11-19T10:45:36.47Z",
                "2023-11-19T11:45:36.47Z",
                "2023-11-19T12:45:36.47Z",
                "2023-11-19T13:45:36.47Z",
                "2023-11-19T14:45:36.47Z",
                "2023-11-19T15:45:36.47Z",
                "2023-11-19T16:45:36.47Z",
                "2023-11-19T17:45:36.47Z",
                "2023-11-19T18:45:36.47Z",
                "2023-11-19T19:45:36.47Z",
                "2023-11-19T20:45:36.47Z",
                "2023-11-19T21:45:36.47Z",
                "2023-11-19T22:45:36.47Z",
                "2023-11-19T23:45:36.47Z"
            ]
        }
    },
    "noDataReasons": {
        "ERROR_INTERNAL": 3,
        "FILL": 4,
        "GAP": 1,
        "GOOD": 0,
        "INVALID_HIGH": 2,
        "INVALID_LOW": 5
    },
    "variables": {
        "air.temperature.at-2m": {
            "standardName": "air_temperature_at_2m_above_ground_level",
            "units": "degreeK",
            "siUnits": "K",
            "dimensions": [
                "time",
                "point"
            ],
            "data": [
                null,
                291.32413,
                291.30685,
                291.2896,
                291.27237,
                291.2551,
                291.23785,
                291.14282,
                291.0232,
                290.90363,
                290.784,
                290.66443,
                290.54483,
                290.44113,
                290.34244,
                290.24377,
                290.14508,
                290.04642,
                289.94772,
                289.94534,
                289.97336,
                290.0014,
                290.02942,
                290.05743,
                290.08545
            ],
            "noData": [
                1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ]
        },
        "cloud.cover": {
            "standardName": "cloud_area_fraction",
            "units": "percent",
            "dimensions": [
                "time",
                "point"
            ],
            "data": [
                null,
                53.44242,
                62.237858,
                71.0333,
                79.828735,
                88.624176,
                97.41961,
                98.966354,
                98.22404,
                97.48173,
                96.7394,
                95.99709,
                95.25477,
                95.70024,
                96.5208,
                97.34137,
                98.16194,
                98.9825,
                99.80306,
                94.16576,
                86.48911,
                78.812485,
                71.13585,
                63.459206,
                55.78257
            ],
            "noData": [
                1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ]
        },
        "precipitation.rate": {
            "standardName": "lwe_precipitation_rate",
            "units": "millimeterPerHour",
            "siUnits": "mm.hr^{-1}",
            "dimensions": [
                "time",
                "point"
            ],
            "data": [
                null,
                null,
                null,
                null,
                null,
                null,
                null,
                2.2356915,
                2.0887985,
                1.9419055,
                1.7950122,
                1.6481192,
                1.501226,
                1.307142,
                1.0981557,
                0.88916945,
                0.6801831,
                0.47119677,
                0.26221043,
                0.18835331,
                0.15716854,
                0.12598379,
                0.09479902,
                0.06361426,
                0.032429494
            ],
            "noData": [
                1,
                4,
                4,
                4,
                4,
                4,
                4,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ]
        },
        "wind.direction.at-10m": {
            "standardName": "wind_from_direction_at_10m_above_ground_level",
            "units": "degree",
            "siUnits": "degree",
            "dimensions": [
                "time",
                "point"
            ],
            "data": [
                null,
                74.55406,
                81.385796,
                88.94301,
                97.04878,
                105.41702,
                113.701385,
                118.05928,
                121.49573,
                125.23002,
                129.26666,
                133.59897,
                138.20589,
                144.11246,
                150.57718,
                157.11966,
                163.57204,
                169.77972,
                175.62161,
                179.29318,
                182.31535,
                185.26903,
                188.14142,
                190.92204,
                193.6028
            ],
            "noData": [
                1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ]
        },
        "wind.speed.at-10m": {
            "standardName": "wind_speed_at_10m_above_ground_level",
            "units": "meterPerSecond",
            "siUnits": "m.s^{-1}",
            "dimensions": [
                "time",
                "point"
            ],
            "data": [
                null,
                8.201182,
                7.7481675,
                7.4178143,
                7.226962,
                7.1867337,
                7.299621,
                7.1077657,
                6.8113346,
                6.541573,
                6.301906,
                6.0958858,
                5.9270205,
                5.7902055,
                5.7188983,
                5.721671,
                5.7984157,
                5.9462705,
                6.160116,
                6.25725,
                6.3211226,
                6.402203,
                6.499847,
                6.6133213,
                6.7418265
            ],
            "noData": [
                1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ]
        },
        "wind.speed.gust.at-10m": {
            "standardName": "wind_speed_of_gust_at_10m_above_ground_level",
            "units": "meterPerSecond",
            "siUnits": "m.s^{-1}",
            "dimensions": [
                "time",
                "point"
            ],
            "data": [
                null,
                null,
                null,
                null,
                null,
                null,
                null,
                11.623706,
                11.256136,
                10.888567,
                10.520996,
                10.153427,
                9.785856,
                9.667354,
                9.627503,
                9.587652,
                9.547802,
                9.507952,
                9.4681,
                9.4050865,
                9.334758,
                9.264429,
                9.1941,
                9.123773,
                9.053444
            ],
            "noData": [
                1,
                4,
                4,
                4,
                4,
                4,
                4,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ]
        }
    }
}

Any help greatly appreciated.

Creating the same attribute setup as OWM in a single sensor is possible but a lot of work and will become technically unreadable , from moy pov you’d need jq (jquery)
The pro is that you can reuse existing weather cards
My ‘simple’ solution would be to create a sensor per topic, i.e. wind, precipitation, cloud_area… and then use Apexcharts to get the data in a graph.
The single sensor woulc contain an attribute with all timings and another for the values.
… happy to help if you need … but before I spend time, need to know if this is OK enough?

I was slightly bored… so check this

command_line:   
  - sensor: 
        name: testjson3
        unique_id: testjson3
        scan_interval: 30000
        command: > 
            curl "http://192.168.1.20:8124/local/test3.json" | jq '{"time": .dimensions.time.data, "air_temperature": .variables."air.temperature.at-2m".data, "cloud_cover": .variables."cloud.cover".data}'
        value_template: >    
        json_attributes:
            - time
            - air_temperature
            - cloud_cover

this assumes the source to be a file in www folder

type: custom:apexcharts-card
header:
  title: Test
  show: true
graph_span: 2d
series:
  - entity: sensor.testjson3
    name: temp_K
    color: orange
    data_generator: |
      return entity.attributes.time.map((time, index) =>
            {     
          return [new Date(time).getTime(), entity.attributes.air_temperature[index]];
            });

sensor.testjson3 has this in its attributes…you can add the rest yourselves in the jq above

time:
  - "2023-11-18T23:45:36.47Z"
  - "2023-11-19T00:45:36.47Z"
  - "2023-11-19T01:45:36.47Z"
  - "2023-11-19T02:45:36.47Z"
  - "2023-11-19T03:45:36.47Z"
  - "2023-11-19T04:45:36.47Z"
  - "2023-11-19T05:45:36.47Z"
  - "2023-11-19T06:45:36.47Z"
  - "2023-11-19T07:45:36.47Z"
  - "2023-11-19T08:45:36.47Z"
  - "2023-11-19T09:45:36.47Z"
  - "2023-11-19T10:45:36.47Z"
  - "2023-11-19T11:45:36.47Z"
  - "2023-11-19T12:45:36.47Z"
  - "2023-11-19T13:45:36.47Z"
  - "2023-11-19T14:45:36.47Z"
  - "2023-11-19T15:45:36.47Z"
  - "2023-11-19T16:45:36.47Z"
  - "2023-11-19T17:45:36.47Z"
  - "2023-11-19T18:45:36.47Z"
  - "2023-11-19T19:45:36.47Z"
  - "2023-11-19T20:45:36.47Z"
  - "2023-11-19T21:45:36.47Z"
  - "2023-11-19T22:45:36.47Z"
  - "2023-11-19T23:45:36.47Z"
air_temperature:
  - null
  - 291.32413
  - 291.30685
  - 291.2896
  - 291.27237
  - 291.2551
  - 291.23785
  - 291.14282
  - 291.0232
  - 290.90363
  - 290.784
  - 290.66443
  - 290.54483
  - 290.44113
  - 290.34244
  - 290.24377
  - 290.14508
  - 290.04642
  - 289.94772
  - 289.94534
  - 289.97336
  - 290.0014
  - 290.02942
  - 290.05743
  - 290.08545
cloud_cover:
  - null
  - 53.44242
  - 62.237858
  - 71.0333
  - 79.828735
  - 88.624176
  - 97.41961
  - 98.966354
  - 98.22404
  - 97.48173
  - 96.7394
  - 95.99709
  - 95.25477
  - 95.70024
  - 96.5208
  - 97.34137
  - 98.16194
  - 98.9825
  - 99.80306
  - 94.16576
  - 86.48911
  - 78.812485
  - 71.13585
  - 63.459206
  - 55.78257
friendly_name: testjson3

With jinja/templating you can use it for other things as automations…

Oh awesome thank-you so much! I will have a play with this. Will report back - really appreciate the time you have given this.

As you noticed I still had to use jq to bring all sub-level attributes into one. Theoretically one could make this more complex (as mentioned) by iterating in JQ and putting the variables each under their respective date (same as OWM forecast attrib)

Did you ever get this all up and working @Damaar ? I’m super interested in this, given that most weather services for New Zealand are rubbish.

Not just there… living in south of France it s*cks too. I use 3 services atm to make sure that I am timely made aware of either rain or sun, they update independently, infrequently and their temp values are off too.

Hey @timwelch - from the good help of @vingerha I have got it going, but I haven’t managed to sort it out properly. I have can pull the data out of the API, but I have not had the time to sit down and work it through from there. I was hoping my wife would get involved and sort it out as I have been struggling with it but she has been focused on studies. I am keen to look at how the OpenWeatherMap integration works and take a similar approach. That would be the ideal.

1 Like

I’d love to help out but I’m really not a programmer; rather a “scripter” at best.

I wonder if we ask for help within the NZ https://community.home-assistant.io/t/home-assistant-new-zealand/ that someone with more API experience might be able to jump in. :thinking:

Unless there is a read-made integration, this is the only one available and I already gave the options on how to do it…yes, it needs some jq stuff and all …that I cannot prevent, but the example above can be used as a basis to create a similar ‘forecast’ section alike ‘proper’ integrations…i.e. grouping datetime wirh other attribs related to that datetime.

EDIT: I am returning on this … I already analyzed it and creating a OWM-alike attribute is too much work
But, the one created above works and can be used for apexcharts