Weekly Dinner menu choices, auto-rotating, with random selection

Weekly Dinner menu choices, auto-rotating, with random selection

I got extremely tired of the mental load of picking menu options for my family’s dinners, creating a grocery list, and then repeating this for every evening until I perish. I decided to use technology to make my life easier and help bring some efficiency to managing our household.

a quick note: I use separate files for my configuration.yaml to reference each of template, input_text, input_select, etc.

this means that my references will be in separate files entirely, rather than in my config.yaml. the entries in my config.yaml are:

input_select: !include input_selects.yaml
input_text: !include input_texts.yaml
script: !include scripts.yaml
sensor: !include sensors.yaml
template: !include templates.yaml
  1. Create the following input_select entries for each recipe you need:
##recipe input selects##
	recipe_menu_name:
		name: This is The Menu Item Name
		options:
		- "ingredient 1"
		- "ingredient 2"
		- "ingredient 3"

example:

Summary
	recipe_tuna_salad:
		name: Tuna salad
		options:
			- "2 cans tuna"
			- "6 eggs"
			- "mayonnaise"
			- "yellow mustard"
			- "sweet relish"
			- "onion powder"
			- "garlic powder"
			- "smoked paprika"
			- "black pepper"
	recipe_shepherds_pie:
		name: Shepherds pie
		options:
			- "2 lbs ground beef"
			- "1 bag frozen mixed vegetables"
			- "mushroom broth"
			- "cascade mushroom mix"
			- "6 russet potatoes"
			- "4 tbsp butter"
  1. Create a separate input_select to collate each recipe name, as a list to reference in all our next steps:
menu_options:
    name: Weekly Dinner Menu Items
    icon: mdi:silverware
    options:
        - "Initial"
  1. Create the following input_texts:
Summary
monday_menu:
  name: Monday Menu
tuesday_menu:
  name: Tuesday Menu
wednesday_menu:
  name: Wednesday Menu
thursday_menu:
  name: Thursday Menu
friday_menu:
  name: Friday Menu
previous_monday_menu:
  name: Previous Monday Menu
previous_tuesday_menu:
  name: Previous Tuesday Menu
previous_wednesday_menu:
  name: Previous Wednesday Menu
previous_thursday_menu:
  name: Previous Thursday Menu
previous_friday_menu:
  name: Previous Friday Menu
  1. Now that the baselines are created, we need scripts and automations to handle the updates. Create the following script entries, to allow both menu_options updates, as well as create a new menu each week:
Summary
update_menu_options:
  sequence:
    - service: input_select.set_options
      target:
        entity_id: input_select.menu_options
      data:
        options: >
          {% set entities = states.input_select | selectattr('entity_id', 'search', 'input_select.recipe_') | list %}
          {% set friendly_names = entities | map(attribute='attributes.friendly_name') | list %}
          {{ friendly_names }}
assign_weekly_menu:
    sequence:
      # Update previous menu values
      - service: input_text.set_value
        target:
          entity_id: input_text.previous_monday_menu
        data:
          value: '{{ states(''input_text.monday_menu'') }}'
      - service: input_text.set_value
        target:
          entity_id: input_text.previous_tuesday_menu
        data:
          value: '{{ states(''input_text.tuesday_menu'') }}'
      - service: input_text.set_value
        target:
          entity_id: input_text.previous_wednesday_menu
        data:
          value: '{{ states(''input_text.wednesday_menu'') }}'
      - service: input_text.set_value
        target:
          entity_id: input_text.previous_thursday_menu
        data:
          value: '{{ states(''input_text.thursday_menu'') }}'
      - service: input_text.set_value
        target:
          entity_id: input_text.previous_friday_menu
        data:
          value: '{{ states(''input_text.friday_menu'') }}'
    
      # Assign new unique menu options
      - variables:
          options: '{{ state_attr(''input_select.menu_options'', ''options'') | list }}'
          used_options: []
      - service: input_text.set_value
        target:
          entity_id: input_text.monday_menu
        data:
          value: >-
            {% set options = options | reject('equalto', states('input_text.previous_monday_menu')) | list %}
            {% set monday_menu = options | random %}
            {% set used_options = used_options + [monday_menu] %}
            {{ monday_menu }}
      - service: input_text.set_value
        target:
          entity_id: input_text.tuesday_menu
        data:
          value: >-
            {% set options = options | reject('equalto', states('input_text.previous_tuesday_menu')) | reject('in', used_options) | list %}
            {% set tuesday_menu = options | random %}
            {% set used_options = used_options + [tuesday_menu] %}
            {{ tuesday_menu }}
      - service: input_text.set_value
        target:
          entity_id: input_text.wednesday_menu
        data:
          value: >-
            {% set options = options | reject('equalto', states('input_text.previous_wednesday_menu')) | reject('in', used_options) | list %}
            {% set wednesday_menu = options | random %}
            {% set used_options = used_options + [wednesday_menu] %}
            {{ wednesday_menu }}
      - service: input_text.set_value
        target:
          entity_id: input_text.thursday_menu
        data:
          value: >-
            {% set options = options | reject('equalto', states('input_text.previous_thursday_menu')) | reject('in', used_options) | list %}
            {% set thursday_menu = options | random %}
            {% set used_options = used_options + [thursday_menu] %}
            {{ thursday_menu }}
      - service: input_text.set_value
        target:
          entity_id: input_text.friday_menu
        data:
          value: >-
            {% set options = options | reject('equalto', states('input_text.previous_friday_menu')) | reject('in', used_options) | list %}
            {% set friday_menu = options | random %}
            {{ friday_menu }}

  1. Next up, 2 entries in template.yaml:
Summary
  - name: "Rotating Dinner Menu"
    unique_id: updated_dinner_menu
    state: "OK"
    attributes:
      Monday: >-
        {% set mon = states('input_text.monday_menu') %}
        {% set selection = states('input_select.monday_menu_manual') %}
        {{ mon if selection == 'Placeholder' else selection }}
      Tuesday: >-
        {% set tue = states('input_text.tuesday_menu') %}
        {% set selection = states('input_select.tuesday_menu_manual') %}
        {{ tue if selection == 'Placeholder' else selection }}
      Wednesday: >-
        {% set wed = states('input_text.wednesday_menu') %}
        {% set selection = states('input_select.wednesday_menu_manual') %}
        {{ wed if selection == 'Placeholder' else selection }}
      Thursday: >-
        {% set thur = states('input_text.thursday_menu') %}
        {% set selection = states('input_select.thursday_menu_manual') %}
        {{ thur if selection == 'Placeholder' else selection }}
      Friday: >-
        {% set fri = states('input_text.friday_menu') %}
        {% set selection = states('input_select.friday_menu_manual') %}
        {{ fri if selection == 'Placeholder' else selection }}
  - name: "Last Week's Dinner Menu"
    unique_id: last_week_menu
    state: "OK"
    attributes:
      Monday: "{{states('input_text.previous_monday_menu')}}"
      Tuesday: "{{states('input_text.previous_tuesday_menu')}}"
      Wednesday: "{{states('input_text.previous_wednesday_menu')}}"
      Thursday: "{{states('input_text.previous_thursday_menu')}}"
      Friday: "{{states('input_text.previous_friday_menu')}}"
  1. Finally, create an automation to update the menu items each week, as well as reflect the week change each iteration.

With all these configurations, you are able to work with an auto-update menu.

Next section to tackle: the grocery list based off each menu item.

scripts.yaml entry:

Summary
add_to_shopping_list:
  alias: Shopping List additions
  sequence:
    - variables:
        days: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
        item_counts: {}
    - repeat:
        count: "{{ days | length }}"
        sequence:
          - variables:
              day: "{{ days[repeat.index - 1] }}"
              menu: "{{ state_attr('sensor.rotating_dinner_menu', day) }}"
              entity_id: >
                {% set entities = states.input_select | selectattr('entity_id', 'search', 'input_select.recipe_') | list %}
                {% set entity = entities | selectattr('attributes.friendly_name', 'equalto', menu) | first %}
                {{ entity.entity_id if entity else 'none' }}
              options: >
                {% if entity_id != 'none' %}
                  {{ state_attr(entity_id, 'options') | list }}
                {% else %}
                  []
                {% endif %}
          - repeat:
              count: "{{ options | length }}"
              sequence:
                - variables:
                    item: "{{ options[repeat.index - 1] }}"
                    count: "{{ item_counts[item] | default(0) + 1 }}"
                - service: python_script.update_item_counts
                  data:
                    item: "{{ item }}"
                    count: "{{ count }}"
                - service: shopping_list.add_item
                  data:
                    name: >
                      {% if count > 1 %}
                        {{ count }}x {{ item }}
                      {% else %}
                        {{ item }}
                      {% endif %}

Modify your automation to perform the script action after the menu is updated each weekly iteration.

I’m currently working out the learning curve on creation of a blueprint. More to come!

3 Likes

This deserves more credit! Love these kind of solutions. Hope it works well! I’ll think about integrating this sometime in the future

1 Like

Nice work! :smiley:

Can you make a blueprint?

I’m going to learn how to do this :smiley: will send a quick update when available!

I was able to research the request you provided. I feel as though it’d be a bit moot, considering all the building blocks have to be manually created, prior to the automation creation of the blueprint version of this project. If I’m incorrect, please feel free to provide me with whatever I’m missing, and I’ll happily oblige :slight_smile: