i wanted to use the docker version but didnt manage to get it work on the webpage card. so i use the add on. when installed searh for https://YOUR_IP:9000/
Hi, thank you for this write-up! Been really handy. I think it may be outdated now as when I try to copy the code for the week menu I get this error: Invalid config for 'rest' from integration 'sensor' at configuration.yaml, line 167: 'sensor' is an invalid option for 'sensor.rest', check: sensor
I canāt seem to resolve it.
Hi @Jakesa, I double checked the code and itās correct. I run HA version 2024.3.0
Do you have defined it in configuration.yaml under the root or under/in a sensor.yaml file?
Sorry, my bad. Iām running 2024.3.1 I had it defined under the root. Are yours in a sensor.yaml file?
EDIT: Scrap that. I got it sorted. My config was a bit messed up.
Hey all. Not sure if this is useful for anyone, but I thought Iād share it anyway.
We use and love Mealie in my house, but when we are planning out our grocery list for the week, it usually involves looking up some recipes in Mealie, and manually adding their ingredients to our shopping list in Todoist, either via the Todoist app or by asking Alexa to add them.
I decided to write an automation to improve this a bit. Essentially now I can add a Mealie recipe to a Mealie shopping list, all in the Mealie web app. Home Assistant will then read those ingredients which were added, and one by one transfer them to my Todoist groceries list, deleting them from Mealie after it has done each one. This saves me manually typing or announcing each ingredient to Alexa.
UPDATED SOLUTION AUGUST 2024:
Home Assistant 2024.7 introduced an official Mealie integration, so Iād recommend using that to get the data into Home Assistant rather than my custom rest sensor based solution below. Original solution kept below for posterity.
ORIGINAL SOLUTION FROM MARCH 2024:
If youād like to use it yourself, you just need to do the following two things:
-
Add two new secrets to your
secrets.yaml
file and replace the values as appropriatemealie_shopping_items_api_endpoint: https://[my-mealie-url]/api/groups/shopping/items
being sure to repace my-mealie-url with your mealie host name or IP addressmealie_api_token: Bearer xxxxxxxxxx
being sure to replace xxxxxxxxxx with your Mealie API token (see this page for details).
-
Change the two variables commented with
#CHANGEME
target_shopping_list
can be any list available in Home Assistant, doesnāt have to be a Todoist listnotify_service
is what I use to send me a notification to my phone if it fails to delete an item from Mealie for whatever reason, just in case
Hereās the YAML:
sensor:
#Sensor to view items which are on any Mealie shopping list
- platform: rest
name: Mealie Shopping List Items
resource_template: !secret mealie_shopping_items_api_endpoint
headers:
Authorization: !secret mealie_api_token
params:
perPage: 1
queryFilter: checked=false
orderBy: food.name
orderDirection: asc
#As long as the request contains "total", the API was successfully reached
availability: >
{{ value_json['total'] }}
#Extract the ingredient data in the following format: "food - quantity unit" eg. "apples - 1.5 kilogram", or "Empty List" if no items are left in the list
value_template: >
{# If no items in list, return "Empty List" #}
{% if value_json['total'] == 0 %}
Empty List
{# If distinct food is not defined use display name instead #}
{% elif value_json['items'][0]['food'] == none %}
{{ value_json['items'][0]['display'] }}
{# If quantity is available, include it in the output #}
{% elif value_json['items'][0]['quantity'] > 0 %}
{{ value_json['items'][0]['food']['name'] }} - {{ (value_json['items'][0]['quantity'] | round(3) | string).rstrip('0').rstrip('.') }} {{ value_json['items'][0]['unit']['name'] }}
{# Otherwise, print just the food name #}
{% else %}
{{ value_json['items'][0]['food']['name'] }}
{% endif %}
#Extract the ingredient's ID. Required to delete through the API later on.
json_attributes_path: "$.items.0"
json_attributes:
- id
rest_command:
#Command to delete a Mealing shopping list item
mealie_delete_from_shopping_list:
url: >
{{ url }}/{{ state_attr('sensor.mealie_shopping_list_items', 'id') }}
method: delete
headers:
Authorization: !secret mealie_api_token
automation:
#Automation to regularly refresh the "Mealie Shopping List Items" sensor
- id: mealie_update_rest_sensors
alias: "Mealie - Update Rest Sensors"
initial_state: "on"
trigger:
- platform: time_pattern
seconds: "/10" #How often do you want to check for updates in Mealie?
action:
- service: homeassistant.update_entity
data:
entity_id:
- sensor.mealie_shopping_list_items
#Automation to transfer items from the Mealie shopping list to another list of your choice
- id: mealie_transfer_shopping_list
alias: "Mealie - Transfer Shopping List"
description: "When shopping list items are added to the Mealie shopping list, transfer them to an alternative list."
mode: queued
max: 10
initial_state: "on"
variables:
target_shopping_list: todo.groceries_list #CHANGEME: entity ID of your shopping list
notify_service: notify.mobile_app_michael_s_galaxy_s10 #CHANGEME: where to be notified if items fail to delete from Mealie shopping list
trigger:
- id: "regular_trigger"
platform: state
entity_id: sensor.mealie_shopping_list_items
- id: "fallback_trigger"
platform: time_pattern
minutes: "/10"
condition:
- condition: not
conditions:
- condition: state
entity_id: sensor.mealie_shopping_list_items
state: "Empty List"
action:
- alias: "Ensure shopping list item isn't now 'Empty List'"
condition: not
conditions:
- condition: state
entity_id: sensor.mealie_shopping_list_items
state: "Empty List"
- alias: "Add shopping list item to target list"
service: todo.add_item
target:
entity_id: "{{ target_shopping_list }}"
data:
item: "{{ states('sensor.mealie_shopping_list_items') }}"
description: Imported From Mealie
- alias: "Delete shopping list item from Mealie"
service: rest_command.mealie_delete_from_shopping_list
data:
url: !secret mealie_shopping_items_api_endpoint
response_variable: mealie_delete_response
- alias: "Notify if item failed to delete from Mealie"
if: "{{ mealie_delete_response['status'] != 200 }}"
then:
- service: "{{ notify_service }}"
data:
title: "Failed to delete item from Mealie list"
message: "{{ mealie_delete_response['content'] }}"
data:
notification_icon: "mdi:food-off"
- alias: "Refresh Mealie shopping list items sensor, in case more items need processing"
service: homeassistant.update_entity
data:
entity_id:
- sensor.mealie_shopping_list_items
And hereās what to add to your secret.yaml
:
mealie_shopping_items_api_endpoint: https://[my-mealie-url]/api/groups/shopping/items
mealie_api_token: Bearer xxxxxxxxxx
If I get the time one day I might look at trying to turn this into a blueprint or a HACS integration, but hopefully this is useful for some people in the mean time!
Edit: Updated the template sensor to handle recipes where the ingredients are added as just text and not linked to specific foods.
I am trying to copy the markdown card. I have all the entities exposed needed for it:
But using this Markdown code:
type: markdown
content: |-
<table>
{% for i in range(7) %}
{% set index = i|string %}
{% set meal_date = states("sensor.mealie_day" + index + "_date") %}
{% set meal_name = states("sensor.mealie_day" + index + "_name") %}
{% if meal_date != 'unknown' %}
<tr>
<td>
{{ ['ma','di','wo','do','vr','za','zo'][strptime(meal_date, "%Y-%m-%d").weekday()] }}
</td>
<td> </td>
<td>{{ meal_name }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
title: Week Menu
Is blank for some reason:
Any ideas where I am going wrong please?
Great work. However how do you stop it adding staples like salt and olive oil to the shopping list. I only want to add those if I have actually run out.
Probably your sensor name is a bit different.
Go to Developers tools and check the States tab and filter on mealie
Or the meal_date
sensor value is unknown
.
Then you can also remove the if condition in the markdown template.
{% if meal_date != 'unknown' %}
...
{% endif %}
it worked out to be an issue with my config. Thank you.
@nickrout When you add the recipe to a shopping list in Mealie, you can uncheck any ingredients you donāt need to add to your list.
Well thatās easy!
Iām loving the things people are doing with this! But I was wondering, would it be easily possible to gather a list of recipes with a certain category (for example pastaās) and display them with things needed, picture and description in Home Assistant?
All that data can be gathered calling multiple mealie apiās. Not really easy but itās possible.
Why do you want so much information at ones on your dashboard? All ingredients, all steps and all photos.
not the steps to do, just the description and things needed with a picture and name to make it easily to scroll through in HA when you want to make dinner plans for the next week, and do it from HA instead of the website, but then again, I just noticed there is an unofficial Android app made, which makes it easierā¦
The main idea was to have the same feeling as you would have when you used to go over your cook books page by page looking for something to make and writing down the ingredients needed
Just stopping by to say thanks, @my.spider.died! I set this up this morning and looks to be working great. This is really handy.
HA did throw a couple errors, not liking the description fields on data items (ie, description: Imported From Mealie
) but that was easy to fix. Iām running 2024.4.2
Thank you for posting this solution, this would be really handy to work in HAā¦ I am having some trouble getting this to work though. I was able to get the sensor in HA, but it seems to only pick up the last item in a list. Also with the automation it will repeat that item infinitely until i shut the automation off.
Lastly, I am not able to get the delete step to work, HA seems to not like the line " url: !secret mealie_shopping_items_api_endpoint"
What am i missing or doing wrong?
Current Items in Mealie:
Here is my api call
- platform: rest
resource: "https://mymealie/api/groups/shopping/items"
method: GET
name: Mealie Shopping List Items
headers:
Authorization: !secret mealie_api_token
force_update: true
scan_interval: 30
params:
perPage: 1
queryFilter: checked=false
orderBy: food.name
orderDirection: asc
#As long as the request contains "total", the API was successfully reached
availability: >
{{ value_json['total'] }}
#Extract the ingredient data in the following format: "food - quantity unit" eg. "apples - 1.5 kilogram", or "Empty List" if no items are left in the list
value_template: >
{# If no items in list, return "Empty List" #}
{% if value_json['total'] == 0 %}
Empty List
{# If distinct food is not defined use display name instead #}
{% elif value_json['items'][0]['food'] == none %}
{{ value_json['items'][0]['display'] }}
{# If quantity is available, include it in the output #}
{% elif value_json['items'][0]['quantity'] > 0 %}
{{ value_json['items'][0]['food']['name'] }} - {{ (value_json['items'][0]['quantity'] | round(3) | string).rstrip('0').rstrip('.') }} {{ value_json['items'][0]['unit']['name'] }}
{# Otherwise, print just the food name #}
{% else %}
{{ value_json['items'][0]['food']['name'] }}
{% endif %}
#Extract the ingredient's ID. Required to delete through the API later on.
json_attributes_path: "$.items.0"
json_attributes:
- id
Entity showing in HA, but only showing the last item (not sure if this is expected, but seems off to me)
rest_command:
#Command to delete a Mealing shopping list item
mealie_delete_from_shopping_list:
url: >
{{ url }}/{{ state_attr('sensor.mealie_shopping_list_items', 'id') }}
method: delete
headers:
Authorization: !secret mealie_api_token
Rest command not working in the automation
Result at this point is infinatly repeating the last item in HA todo list
Update I was able to eventually get something workable for importing using the call below to import all items of a specific shopping list, then making a template sensor to put items into a listā¦this works extremely wellā¦ the thing is, I would now need to be able to delete or remove items once marked as completed on the list otherwise they will sink again ā¦i have not yet figured out how to do that.
- platform: rest
name: Mealie Shopping List Items
method: GET
resource_template: "https://my_domain/api/groups/shopping/lists/[myshoppinglistid]"
headers:
Authorization: !secret my_token
value_template: "OK"
json_attributes:
- listname
- listItems
Hey @shredder_guitarist. The sensor should only show the last item; essentially it reads the list, pulls the last item into that sensor, and then automation.mealie_transfer_shopping_list
should delete it from Mealie after it has saved it to Todoist. Once deleted from mealie, the rest sensor will be reading a different value for the last item on the list from mealie (ie. no longer the deleted one), which triggers the automation to occur again. This repeats until there are no items on the Mealie list any more, giving the sensor the value āEmpty Listā, which stops the automation from running further.
For the issue youāre seeing, are there any errors logged under System > Logs which might hint as to why the rest_command.mealie_delete_from_shopping_list
isnāt working for you?
One thing I can think of which could cause it is if your mealie api endpoint url in your secrets.yaml
contains a trailing slash? The value should be something like:
https://my-mealie-url.com/api/groups/shopping/items
But if it has a trailing slash, then the rest_command yaml wonāt work, resulting in it trying to call the API endpoint with a double slash, like:
https://my-mealie-url.com/api/groups/shopping/items//9c1f9552-36e2-4a45-a989-dd55e160f807
Iām glad itās working well for you @ih8gates!
Perhaps the description field is only available for certain todo list integrations. I use Todoist as my target todo list, which supports description, but perhaps your one doesnāt.
This has worked fantastically for me, and hugely helps with meal planning and shopping lists! So a huge thanks. It has caused a persistent warning in my logs though - āJSON result was not a dictionary or list with 0th element a dictionaryā.
Any ideas on a fix? Iām transferring mealieās shopping list into HAās local to-do list.
Ok, After starting over again from scratch i was able to get it working after a lot of swearing, cursing, and a good cry in a cold shower.
This will be a really handy addition to automating shopping lists.
There are still some loose ends thoughā¦
-
The notification message doesnāt work in the way that itās written in your example. Iām not sure if those are literal quotes and brackets or placeholders; there are quite a few places in your example where I canāt quite tell if the brackets are supposed to be there or notā¦like ā{# If distinct food is not defined use display name instead #}ā for exampleā¦it seems like this is a comment, but also a piece of code. I removed these occurrences and it still seems to work fine. One thing Iām sure of is that the message: ā{{ mealie_delete_response[ācontentā] }}ā is not liked in my instance for some reason, as a workaround, I just created a āFailed to delete itemā message and left it at that.
-
Also, Iāll share that there is a slight modification to the existing code that can be done to obtain items from a specific shopping list
note the query filter and name notes
- platform: rest
name: Mealie Shopping List Items #insert preferred shopping list name
resource_template: !secret mealie_shopping_items_api_endpoint
headers:
Authorization: !secret mealie_api_token
params:
perPage: 1
queryFilter: checked=false AND shoppingListId= XXXX-XXXX-XXXXXXXXX #Obtain shopping list id from the end of browser url while navigating to the shopping list in mealie
orderBy: food.name
orderDirection: asc
#As long as the request contains "total", the API was successfully reached
availability: >
{{ value_json['total'] }}
#Extract the ingredient data in the following format: "food - quantity unit" eg. "apples - 1.5 kilogram", or "Empty List" if no items are left in the list
value_template: >
{% if value_json['total'] == 0 %}
Empty List
{% elif value_json['items'][0]['food'] == none %}
{{ value_json['items'][0]['display'] }}
{% elif value_json['items'][0]['quantity'] > 0 %}
{{ value_json['items'][0]['food']['name'] }} - {{ (value_json['items'][0]['quantity'] | round(3) | string).rstrip('0').rstrip('.') }} {{ value_json['items'][0]['unit']['name'] }}
{% else %}
{{ value_json['items'][0]['food']['name'] }}
{% endif %}
#Extract the ingredient's ID. Required to delete through the API later on.
json_attributes_path: "$.items.0"
json_attributes:
- id
and a modification to the delete command, note the URL includes the specific shopping list id
rest_command:
#Command to delete a Mealing shopping list item
mealie_delete_from_shopping_list:
url: >
https://###mealieurl###/api/groups/shopping/items/{{ state_attr('sensor.mealie_shopping_list_items', 'id') }}?group_id=XXX-XXXXX-XXXXXX #group id is the preferred shopping list ID
method: delete
headers:
Authorization: !secret mealie_api_token