Automation Looping Service Call - Syntax Error

I’m trying to simplify an automation I’m using to create a weather display using the open epaper service. I’ve already got an automation going that updates the weather forecast every 20 minutes and it has been working fine. In that automation I hard coded all of the calls for the weekday, temps hi/low, icon and precipitation for all 6 days on the screen. I just change the day number for the forecast array and move the “x” position 50 px for each day. I am now trying to refactor it to be scalable using a for loop to loop through each day rather than copy/paste the same values for each day.

Below is just a sample of how I’m iterating through the weekday value and placing it on the screen by modifying the “x” position based on the iteration. This runs just fine in the developer tools → template. I can even copy the template output directly into Services and run it with no errors. However, If I try to run it in the services with the for loop in the services panel I get a very nondescript, “Service YAML contains syntax errors, please fix the syntax”.

If I comment out the for and endfor lines and replace the day variable with 0 and the x at 12 it works fine, so I think it can’t handle the loop. However I’ve see other people use loops successfully so before I just give up I wanted to check to see if anyone sees an obvious mistake.

service: open_epaper_link.drawcustom
data:
  background: white
  rotate: 0
  payload:
    {% for day in range(0,6) %}
    - type: text
      value: >-
        {{ as_timestamp((state_attr('weather.home', 'forecast')[day].datetime)) |
        timestamp_custom('%a') }}
      font: ppb.ttf
      x: {{12 + (50*day)}}
      y: 30
      size: 10
      color: red
    {% endfor %}
target:
  entity_id: >-
    open_epaper_link.0000027fff8b3b10

Since your templating is using a for loop without using namespace() the output is more of a list-shaped string than an actual list of dictionaries.

Also, be aware that the forecast attribute is being deprecated , so you will want to use the weather.get_forecast service.

- service: weather.get_forecast
  data:
    type: daily
  target:
    entity_id: weather.home
  response_variable: daily
- service: open_epaper_link.drawcustom
  data:
    background: white
    rotate: 0
    payload: |
      {% set ns = namespace( text_list = [] ) %}
      {% for day in range(0,6) %}
      {% set ns.text_list = ns.text_list +  
      [{ "type": "text",  
        "value": (daily.forecast[day].datetime|as_datetime).strftime('%a'), 
        "font": "ppb.ttf",
        "x": 12 + (50*day),
        "y": 30, "size": 10,
        "color": "red"} ] %}
      {% endfor %}
      {{ ns.text_list }}

Thanks Drew!
That was a ton of help. I still can’t get the call to weather.get_forecast to work with the epaper drawcustom. I don’t think I’m accessing daily.forecast quite right. But I was able to use your namespace sample to work for passing the day correctly in the automation.

If anyone else is interested here is my automation.

service: open_epaper_link.drawcustom
data:
  background: white
  rotate: 0
  payload: |
    {% set ns = namespace( text_list = [] ) %}
    {% for day in range(0,6) %}
    {% set mapper =
          {'clear-day': 'sunny',
           'clear-night': 'night',
           'sunny': 'sunny',
           'rain': 'rainy',
           'snow': 'snowy',
           'snowy': 'snowy',
           'wind': 'windy',
           'fog': 'fog',
           'cloudy': 'cloudy',
           'partlycloudy': 'partly-cloudy',
           'partly-cloudy-day': 'partly-cloudy',
           'partly-cloudy-night': 'night-partly-cloudy',
           'hail': 'hail',
           'rainy': 'rainy',
           'snowy-rainy': 'snowy-rainy',
           'thunderstorm': 'lightning',
           'tornado': 'hurricane'} %}
          {% set state = state_attr('weather.home', 'forecast')[day].condition %}
          {% set weather = mapper[state] if state in mapper else 'sunny-alert' %}
          {% set weather_icon = 'weather-' + weather %}
    {% set ns.text_list = ns.text_list +  
    [{ "type": "text",  
      "value": as_timestamp((state_attr('weather.home', 'forecast')[day].datetime)) |
        timestamp_custom('%a'), 
      "font": "ppb.ttf",
      "x": 12 + (50*day),
      "y": 30, "size": 12,
      "color": "red"} ] +
    [{ "type": "text",  
      "value": state_attr('weather.home', 'forecast')[day].temperature, 
      "font": "ppb.ttf",
      "x": 12 + (50*day),
      "y": 50, "size": 14,
      "color": "black"} ] +
    [{ "type": "icon",  
      "value": weather_icon, 
      "font": "ppb.ttf",
      "x": 12 + (50*day),
      "y": 65, "size": 25,
      "color": "red"} ] +
    [{ "type": "text",  
      "value": state_attr('weather.home', 'forecast')[day].precipitation * 100, 
      "font": "ppb.ttf",
      "x": 12 + (50*day),
      "y": 90, "size": 12,
      "color": "black"} ]  +
    [{ "type": "text",  
      "value": state_attr('weather.home', 'forecast')[day].templow, 
      "font": "ppb.ttf",
      "x": 12 + (50*day),
      "y": 110, "size": 14,
      "color": "black"} ] +
    [{"type": "line",
      "x_start": 45 + (50*day),
      "x_end": 45 + (50*day),
      "y_start": 40,
      "y_end": 128,
      "width": 1,
      "fill": "red"
      }]
      %} 
    {% endfor %}  
    {% set ns.text_list = ns.text_list +  
    [{ "type": "line",
      "x_start": 0,
      "x_end": 296,
      "y_start": 20,
      "y_end": 20,
      "y_padding": 5,
      "width": 2,
      "fill": "red"},
      {"type": "text",
        "value": "Temp: " ~ states('sensor.kcobroom119_temp') | round(1) ~ "°"
        ~ " Humid: " ~ states('sensor.kcobroom119_humidity') | round(0) ~ 
        " Wind: " ~ states('sensor.average_10_min_wind_speed') ~ " mph",
        "font": "ppb.ttf",
        "x": 3,
        "y": 5,
        "size": 12,
        "color": "black"
      }
      ]
      %}
    {{ ns.text_list }}
target:
  entity_id: >-
    open_epaper_link.[YOUR MAC HERE]

Next: figure out what I’m doing wrong with get forecast