PineTime weather

Spent some time trying to figure out how to get weather details to my PineTime watch using only the official Home Assistant app vs having to have another weather app running as well.

There are still things to work out and this isn’t perfect but its probably a good starting point for some.

Below is the service call to tell Gadget Bridge via an Intent what temperature to pass over. This is also passing the humidity and some other info but there are only two things being displayed by the watch using the PineTime watch face ATM temperature and the currentConditionCode.

Things to note. The temperature must be sent in Kelvin. The temperature on the watch is always displayed in Celsius (PineTime bug I think?) the condition code is used to show sun/sun + clouds/just clouds but I don’t have a good way to get that info yet so its just hard coded 803 (partly cloudy for now) the data sent is JSON but it has to be url encoded.

I’m running this automation every 15 minutes and things seems to be working. There is a PineTime bug that can cause the watch to run out of memory and crash if too much weather data is sent so keep that in mind.

  - service: notify.mobile_app
    data:
      message: command_broadcast_intent
      data:
        intent_package_name: nodomain.freeyourgadget.gadgetbridge
        intent_extras: WeatherJson:%7B%27timestamp%27%3A{{as_timestamp(now()) | int}}%2C%27location%27%3A%27Home%27%2C%27currentTemp%27%3A{{((((states.sensor.outside_temperature.state
          | float) - 32) * 5/9) + 273.15) | int}}%2C%27todayMinTemp%27%3A0%2C%27todayMaxTemp%27%3A0%2C%27currentCondition%27%3A%27%27%2C%27currentConditionCode%27%3A803%2C%27currentHumidity%27%3A{{states.sensor.outside_humidity.state
          | int}}%2C%27windSpeed%27%3A0%2C%27windDirection%27%3A0%2C%27forecasts%27%3A%5B%5D%7D:String.urlencoded
        intent_action: nodomain.freeyourgadget.gadgetbridge.ACTION_GENERIC_WEATHER

Building upon w1ll1am23’s foundation for PineTime weather integration, I made the followng enhancements to create a more comprehensive weather display:

  1. Added support for dynamic min/max temperature tracking using HA Statistics sensors
  2. Implemented weather condition mapping to display appropriate weather icons, converting states to OpenWeatherMap condition codes.
  3. Integrated real wind speed and direction data from the weather forecast
  4. Added 5-day weather forecast support using the weather.get_forecasts action.

Note:

  • the solution below assumes Celsius temperatures reported from your sensors and converts them to Kelvin.
  • the mapping from a condition string to a code has been created by an LLM and hasnt been fully tested.

Get Forecast Action

action: weather.get_forecasts
metadata: {}
data:
  type: daily
response_variable: weather_forecast
target:
  entity_id: weather.forecast_home

Send Weather intent to Gadgetbridge

action: notify.mobile_app_oneplus_a6003
metadata: {}
data:
  message: command_broadcast_intent
  data:
    intent_package_name: nodomain.freeyourgadget.gadgetbridge
    intent_extras: >-
      WeatherJson:%7B%27timestamp%27%3A{{as_timestamp(now()) |
      int}}%2C%27location%27%3A%27Home%27%2C%27currentTemp%27%3A{{(states.sensor.balkon_wetterstation_indoor_temperature.state
      | float + 273.15) |
      int}}%2C%27todayMinTemp%27%3A{{(states.sensor.balkon_daily_min_temperature.state
      | float + 273.15) |
      int}}%2C%27todayMaxTemp%27%3A{{(states.sensor.balkon_daily_max_temperature.state
      | float + 273.15) |
      int}}%2C%27currentCondition%27%3A%27{{states.weather.forecast_home.state}}%27%2C%27currentConditionCode%27%3A{%
      if states.weather.forecast_home.state == 'clear-night' %}801{% elif
      states.weather.forecast_home.state == 'cloudy' %}804{% elif
      states.weather.forecast_home.state == 'fog' %}741{% elif
      states.weather.forecast_home.state == 'hail' %}906{% elif
      states.weather.forecast_home.state == 'lightning' %}210{% elif
      states.weather.forecast_home.state == 'lightning-rainy' %}211{% elif
      states.weather.forecast_home.state == 'partlycloudy' %}802{% elif
      states.weather.forecast_home.state == 'pouring' %}502{% elif
      states.weather.forecast_home.state == 'rainy' %}500{% elif
      states.weather.forecast_home.state == 'snowy' %}600{% elif
      states.weather.forecast_home.state == 'snowy-rainy' %}615{% elif
      states.weather.forecast_home.state == 'sunny' %}800{% elif
      states.weather.forecast_home.state == 'windy' %}781{% elif
      states.weather.forecast_home.state == 'windy-variant' %}781{% elif
      states.weather.forecast_home.state == 'exceptional' %}900{% else %}803{%
      endif
      %}%2C%27currentHumidity%27%3A{{states.sensor.balkon_wetterstation_indoor_humidity.state
      |
      int}}%2C%27windSpeed%27%3A{{states.weather.forecast_home.attributes.wind_speed
      |
      int}}%2C%27windDirection%27%3A{{states.weather.forecast_home.attributes.wind_bearing
      | int}}%2C%27forecasts%27%3A[
        {% for day in weather_forecast['weather.forecast_home'].forecast[:5] %}
          {
            %27datetime%27%3A{{as_timestamp(day.datetime) | int}}%2C
            %27minTemp%27%3A{{(day.templow | float + 273.15) | int}}%2C
            %27maxTemp%27%3A{{(day.temperature | float + 273.15) | int}}%2C
            %27condition%27%3A%27{{day.condition}}%27%2C
            %27conditionCode%27%3A{% if day.condition == 'clear-night' %}801{% elif day.condition == 'cloudy' %}804{% elif day.condition == 'fog' %}741{% elif day.condition == 'hail' %}906{% elif day.condition == 'lightning' %}210{% elif day.condition == 'lightning-rainy' %}211{% elif day.condition == 'partlycloudy' %}802{% elif day.condition == 'pouring' %}502{% elif day.condition == 'rainy' %}500{% elif day.condition == 'snowy' %}600{% elif day.condition == 'snowy-rainy' %}615{% elif day.condition == 'sunny' %}800{% elif day.condition == 'windy' %}781{% elif day.condition == 'windy-variant' %}781{% elif day.condition == 'exceptional' %}900{% else %}803{% endif %}
          }{% if not loop.last %}%2C{% endif %}
        {% endfor %}
      ]%7D:String.urlencoded
    intent_action: nodomain.freeyourgadget.gadgetbridge.ACTION_GENERIC_WEATHER

I am rather new to HA, if anyone can tell me how I can outsource the mapping of condition to code into a reusable block, please let me know.

1 Like