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 am using Home Assistant’s capabilities for a to-do list to create a grocery list, as well as menu for each week.

I chose to create 4 dinners here, but you can certainly add more.

I have yet to figure out how to create a list to avoid weekly repeats, but will update when I’ve solved that portion.
Here is a list of the steps I performed, with examples below of each step:

  1. Create input_select sensors for each recipe I’ll use in the menu options list.
  2. Create a menu list from each of the recipe input_select sensors.
  3. Create a menu selection from random picks of the menu list.
  4. Create a schedule for the menu selection to update.
  5. Create a script to clear previous ingredient lists from the prior week, and create new entries based off the new menu selections after they’ve been updated.
  6. Create an entry into your configuration.yaml, as well as a custom folder for the python script to properly function.
  7. Create an automation based off the schedule trigger in step 4, that uses the script in step 5 targeting the grocery list entity.

  1. Create the following input_select entries:

in input_select.yaml:

##recipe input selects##
	recipe_menu_name:
		name: This is The Menu Item Name
		options:
		- "ingredient 1"
		- "ingredient 2"
		- "ingredient 3"

example:

	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. Once all recipes are added into unique input select items, create a new input select sensor with the following options:
	##menu options for dinners##
	menu_options:
		name: Weekly Dinner Menu Items
		icon: mdi:silverware
		options:
			- "Name exactly as the friendly name is displayed for each input_select"

example:

	##menu options for dinners##
	menu_options:
		name: Weekly Dinner Menu Items
		icon: mdi:silverware
		options:
			- "Tuna salad"
			- "Shepherd's pie"
			- "Chicken pot pie"
  1. Then, create a sensor under template.yaml to randomly select the menu options from your initially created input_selects:
	##Dinner Menu Items
		- name: updated_dinner_menu
		  unique_id: updated_dinner_menu
		  state: "OK"
		  attributes:
			Monday: >
			  {% set menu = state_attr('input_select.menu_options','options')|list |random %}
			  {{menu}}
			Tuesday: >
			  {% set menu2 = state_attr('input_select.menu_options','options')|list |random %}
			  {% for menu2 in 'attributes.sensor.updated_dinner_menu' |rejectattr(menu) %}
			  {%endfor%}
			  {{menu2}}
			Wednesday: >
			  {% set menu3 = state_attr('input_select.menu_options','options')|list |random %}
			  {% for menu3 in 'attributes.sensor.updated_dinner_menu' |rejectattr(menu) |rejectattr(menu2) %}
			  {%endfor%}
			  {{menu3}}
			Thursday: >
			  {% set menu4 = state_attr('input_select.menu_options','options')|list |random %}
			  {% for menu4 in 'attributes.sensor.updated_dinner_menu' |rejectattr(menu) | rejectattr(menu2) | rejectattr(menu3) %}
			  {%endfor%}
			  {{menu4}}
  1. Navigate to Settings>Devices & Services>Helpers, and create a Schedule Helper:
    Name: Dinner Menu Update
    Entity ID: schedule.dinner_menu_update
    Event is set to reset every Saturday at 12:00AM. You can customize this portion to refresh whenever you need.

  2. Create an entry in scripts.yaml with the below details. You’ll need to customize days and entities to add your specific entries:
    Example:

	add_to_shopping_list:
	  alias: Shopping List additions
	  sequence:
		- variables:
			days: ['add your day options here from your updated menu selection options','each entry will be a unique single quotation']
			item_counts: {}
		- repeat:
			count: "{{ days | length }}"
			sequence:
			  - variables:
				  day: "{{ days[repeat.index - 1] }}"
				  menu: "{{ state_attr('sensor.updated_dinner_menu', day) }}"
				  entity_id: >
					{% set entities = 'comma separated values for each recipe input_select entity' %}
					{% set entityList = entities.split(",") %}
					{% set querymatch = entityList | map('state_attr', 'friendly_name') | list %}
					{% set matchers = querymatch | select('search', menu) | list %}
					{% if matchers %}
					  {{ entityList[querymatch.index(matchers[0])] }}
					{% else %}
					  none
					{% endif %}
				  options: >
					{% if entity_id != 'none' %}
					  {{ state_attr(entity_id, 'options') }}
					{% 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 %}
`						  

`	##Query to add ingredients from dynamic menu items, to grocery list. automation clears all items and adds refreshed items##
	add_to_shopping_list:
	  alias: Shopping List additions
	  sequence:
		- variables:
			days: ['Monday', 'Tuesday', 'Wednesday', 'Thursday']
			item_counts: {}
		- repeat:
			count: "{{ days | length }}"
			sequence:
			  - variables:
				  day: "{{ days[repeat.index - 1] }}"
				  menu: "{{ state_attr('sensor.updated_dinner_menu', day) }}"
				  entity_id: >
					{% set entities = 'input_select.recipe_tuna_salad,input_select.recipe_shepherds_pie,input_select.recipe_chicken_pot_pie,input_select.recipe_enchilada_casserole,input_select.recipe_spaghetti,input_select.recipe_sausage_and_cabbage,input_select.recipe_breakfast_burrito,input_select.recipe_steak_fingers,input_select.recipe_chicken_nuggets,input_select.recipe_waffles,input_select.recipe_fried_rice,input_select.recipe_pork_chops,input_select.recipe_stroganoff,input_select.recipe_risotto,input_select.recipe_butternut_squash_soup,input_select.recipe_chicken_and_dumplings,input_select.recipe_hamburgers,input_select.recipe_chili,input_select.recipe_taco_salad,input_select.recipe_pot_roast,input_select.recipe_chicken_fried_steak,input_select.recipe_loaded_nachos,input_select.recipe_eggs_biscuits_and_gravy,input_select.recipe_ravioli,input_select.recipe_quesadillas,input_select.recipe_pizza,input_select.recipe_parmesan_chicken,input_select.recipe_salmon_caesar_salad,input_select.recipe_manicotti,input_select.recipe_pan_fried_chicken_thighs,input_select.recipe_meatloaf,input_select.recipe_green_pea_falafel,input_select.recipe_baked_potatoes,input_select.recipe_pulled_pork,input_select.recipe_pork_tenderloin,input_select.recipe_teriyaki_steak' %}
					{% set entityList = entities.split(",") %}
					{% set querymatch = entityList | map('state_attr', 'friendly_name') | list %}
					{% set matchers = querymatch | select('search', menu) | list %}
					{% if matchers %}
					  {{ entityList[querymatch.index(matchers[0])] }}
					{% else %}
					  none
					{% endif %}
				  options: >
					{% if entity_id != 'none' %}
					  {{ state_attr(entity_id, 'options') }}
					{% 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 %}
						  
  1. Create the following entry into your configuration.yaml:
    python_script:

Then, create a folder under HASS’s root config folder, named python_scripts. Add a file named update_item_counts.py with the following contents:

item = data.get('item')
count = data.get('count')
item_counts = hass.states.get('script.add_to_shopping_list').attributes.get('item_counts')
item_counts[item] = count
hass.states.set('script.add_to_shopping_list', 'running', {'item_counts': item_counts})
  1. Finally, create an automation based off all these components with the following config. Navigate to Settings>Automations & Scenes>Automations. Create:
    Event Trigger: Entity: Dinner Menu Update
    Attribute Next Event changes
    Then Do:
    Shopping List"Complete All"
    Shopping List “Clear completed Items”
    Script ‘Shopping list additions’

Save and name your automation.

For my instance, I created a page view in the dashboard to centralize my outputted dinner items, as well as my ingredients added to the list.

Entities Card Congifuration:
entity: sensor.updated_dinner_menu
type: attribute
attribute: Monday
entity: sensor.updated_dinner_menu
type: attribute
attribute: Tuesday
entity: sensor.updated_dinner_menu
type: attribute
attribute: Wednesday
entity: sensor.updated_dinner_menu
type: attribute
attribute: Thursday

To-Do List card configuration:
Entity: Shopping List

And, that’s all! I’ve found a good amount of success here.

Known limitations in this config:

I haven’t yet created a “re-roll” button in case there’s a duplicate of last week’s menu items. More to come, there.
I have not integrated this to any additional automations to add grocery list ingredients to external add-ins. YMMV here.

1 Like