Skip to content

Commit

Permalink
Update docs for mealie v2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
vdbrink committed Oct 23, 2024
1 parent 4bb44eb commit 6a7f1ae
Showing 1 changed file with 16 additions and 7 deletions.
23 changes: 16 additions & 7 deletions homeassistant/homeassistant_dashboard_mealie.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ image: /homeassistant/images_mealie/mealie1_ha_integration.png

Here you find how I seamlessly integrate the recipe manager **Mealie** into my HA dashboard to organize my **recipes** and show a meal **day-** and **weekplanning**.

This documentation is based on Mealie version `2.0.0`

<img src="images_mealie/mealie1_ha_integration.png" alt="meal planner" width="400px">

> **_UPDATE:_** There is now also a [Mealie integration](https://www.home-assistant.io/integrations/mealie/) in Home Assistant.\
> This page was already created before this exists, here I describe also other functionalities than you get with this integration.
> **_UPDATE 22-10-2024:_** Mealie version `2.0.0` is released and has breaking API changes compare to the previous `1.12.0` version.
> See this PR for the changed paths https://github.com/mealie-recipes/mealie/pull/3970 \
> For example `/groups/mealplans` -> `/households/mealplans`
---
## Table of Contents
<!-- TOC -->
Expand Down Expand Up @@ -91,7 +97,8 @@ services:

mealie-recipes:
container_name: mealie-recipes
image: ghcr.io/mealie-recipes/mealie:latest
# This documetation is based on version 2.0.0 (october 2024)
image: ghcr.io/mealie-recipes/mealie:latest
restart: always
volumes:
- ./volumes/mealie-recipes:/app/data/
Expand Down Expand Up @@ -129,9 +136,11 @@ Smart Home Junkie created a step-by-step video about the installation in HA.
---
## Add recipes

When you access your local Mealie website, you're in read-only modus. Click in the right top corner to login with the default credentials [email protected] / MyPassword
When you access your local Mealie website, you're in read-only modus.
Click in the right top corner to login with the default credentials [email protected] / MyPassword

Click in the left menu on the plus button to add meals manually or import them from a website. Not all recipe websites provide their data in a correct way so Mealie can import the complete online recipe in the Mealie template style, then you need to copy-paste it yourself.
Click on the left menu on the plus button to add meals manually or import them from a website.
Not all recipe websites provide their data in a correct way so Mealie can import the complete online recipe in the Mealie template style, then you need to copy-paste it yourself.

---
## Dashboard integration
Expand Down Expand Up @@ -218,7 +227,7 @@ If you don't want to use the `secrets.yaml` method, you can also place the token
# configuration.yaml
rest:
- scan_interval: 3600
resource: "http://< mealie-url >:9925/api/groups/mealplans/today"
resource: "http://< mealie-url >:9925/api/households/mealplans/today"
headers:
Authorization: !secret mealie_bearer
sensor:
Expand Down Expand Up @@ -304,7 +313,7 @@ The update interval is set here to one hour, if you reorder the meals in Mealie
# configuration.yaml
rest:
- scan_interval: 3600
resource: "http://< ip-address >:9925/api/groups/mealplans?orderBy=date&orderDirection=asc"
resource: "http://< ip-address >:9925/api/households/mealplans?orderBy=date&orderDirection=asc"
headers:
Authorization: !secret mealie_bearer
params:
Expand Down Expand Up @@ -466,14 +475,14 @@ Only ingredients with the text `[freezer]` are used in the notification.

```yaml
{% raw %}
[{"id":"bd0839aee9138ce9","type":"tab","label":"Mealie test","disabled":false,"info":"","env":[]},{"id":"74e61f540d6cfdff","type":"inject","z":"bd0839aee9138ce9","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 22 * * *","once":false,"onceDelay":0.1,"topic":"","x":110,"y":100,"wires":[["d0a80ee27f0fa9ac"]]},{"id":"403b6a3cd68b67c4","type":"http request","z":"bd0839aee9138ce9","name":"get mealplans after now","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://mealie-recipes:9000/api/groups/mealplans?orderBy=date&orderDirection=asc&perPage=1&start_date={{{start_date}}}","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"bearer","senderr":false,"headers":[],"x":550,"y":100,"wires":[["1d7bcc9aea364223"]]},{"id":"d0a80ee27f0fa9ac","type":"function","z":"bd0839aee9138ce9","name":"tomorrow as YYYY-MM-DD","func":"let currentDate = new Date();\ncurrentDate.setDate(currentDate.getDate() + 1);\n\n// Format the date to YYYY-MM-DD\nlet year = currentDate.getFullYear();\nlet month = ('0' + (currentDate.getMonth() + 1)).slice(-2); // Adding 1 because months are zero-based\nlet day = ('0' + currentDate.getDate()).slice(-2);\nlet formattedDate = year + '-' + month + '-' + day;\n\nmsg.start_date = formattedDate;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":100,"wires":[["403b6a3cd68b67c4"]]},{"id":"dc16d1889207dc1c","type":"http request","z":"bd0839aee9138ce9","name":"get recipe for tomorrow","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://mealie-recipes:9000/api/recipes/{{{recipeId}}}","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"bearer","senderr":false,"headers":[],"x":310,"y":260,"wires":[["d2048ea8d9e3ba36"]]},{"id":"f95f8b3686b07a9b","type":"function","z":"bd0839aee9138ce9","name":"get recipeId","func":"if (msg.payload.items.length>0) {\n msg.recipeId = msg.payload.items[0].recipeId;\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":391,"y":180,"wires":[["c30cf32f3fb9dcb0"]]},{"id":"1d7bcc9aea364223","type":"json","z":"bd0839aee9138ce9","name":"","property":"payload","action":"","pretty":false,"x":250,"y":180,"wires":[["f95f8b3686b07a9b"]]},{"id":"d2048ea8d9e3ba36","type":"json","z":"bd0839aee9138ce9","name":"","property":"payload","action":"","pretty":false,"x":490,"y":260,"wires":[["18553b8d68008d00"]]},{"id":"18553b8d68008d00","type":"function","z":"bd0839aee9138ce9","name":"find tag from ingredients","func":"var recipe = msg.payload;\n\nmsg.payload = {};\nmsg.payload.recipe_name = recipe.name;\nmsg.payload.fridge = null;\n\nvar keyword = \"freezer\";\nvar tag = \"[\" + keyword +\"]\";\nvar freezerIngredients = Array();\nfor (let i = 0; i < recipe.recipeIngredient.length; i++) {\n var ingredient = recipe.recipeIngredient[i];\n if (ingredient.display.includes(tag)) {\n // remove tag and add to the array\n freezerIngredients.push(ingredient.display.replace(' '+ tag, ''));\n }\n}\nif (freezerIngredients.length > 0) {\n msg.payload.fridge = freezerIngredients.join(\" and \");\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":340,"wires":[["6600274d3fc3c995"]]},{"id":"ab1563c57ccf9d26","type":"template","z":"bd0839aee9138ce9","name":"from fridge","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"For tomorrow {{payload.fridge}} must get out of the freezer for {{payload.recipe_name}}","output":"str","x":770,"y":320,"wires":[["dd9bfa2ced5eb6ff"]]},{"id":"6600274d3fc3c995","type":"switch","z":"bd0839aee9138ce9","name":"!= null","property":"payload.fridge","propertyType":"msg","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":510,"y":340,"wires":[["ab1563c57ccf9d26"],["cb9246ee0de6055b"]]},{"id":"2c49779e764870f5","type":"link out","z":"bd0839aee9138ce9","name":"send message","mode":"link","links":[],"x":1125,"y":320,"wires":[]},{"id":"cb9246ee0de6055b","type":"template","z":"bd0839aee9138ce9","name":"nothing out of the freezer","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"For tomorrow nothing need out of the freezer for {{payload.recipe_name}}","output":"str","x":810,"y":360,"wires":[["dd9bfa2ced5eb6ff"]]},{"id":"c30cf32f3fb9dcb0","type":"switch","z":"bd0839aee9138ce9","name":"recipeId != null","property":"recipeId","propertyType":"msg","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":560,"y":180,"wires":[["dc16d1889207dc1c"],["6b12146002663662"]]},{"id":"6b12146002663662","type":"template","z":"bd0839aee9138ce9","name":"no recipe for tomorrow","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"For tomorrow no recipe found","output":"str","x":800,"y":280,"wires":[["dd9bfa2ced5eb6ff"]]},{"id":"9f7205ae535d4aea","type":"comment","z":"bd0839aee9138ce9","name":"Get meat out of fridge (vdbrink.github.io)","info":"","x":200,"y":40,"wires":[]},{"id":"dd9bfa2ced5eb6ff","type":"rbe","z":"bd0839aee9138ce9","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":1030,"y":320,"wires":[["2c49779e764870f5"]]}]
[{"id":"bd0839aee9138ce9","type":"tab","label":"Mealie test","disabled":false,"info":"","env":[]},{"id":"74e61f540d6cfdff","type":"inject","z":"bd0839aee9138ce9","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 22 * * *","once":false,"onceDelay":0.1,"topic":"","x":110,"y":100,"wires":[["d0a80ee27f0fa9ac"]]},{"id":"403b6a3cd68b67c4","type":"http request","z":"bd0839aee9138ce9","name":"get mealplans after now","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://mealie-recipes:9000/api/households/mealplans?orderBy=date&orderDirection=asc&perPage=1&start_date={{{start_date}}}","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"bearer","senderr":false,"headers":[],"x":550,"y":100,"wires":[["1d7bcc9aea364223"]]},{"id":"d0a80ee27f0fa9ac","type":"function","z":"bd0839aee9138ce9","name":"tomorrow as YYYY-MM-DD","func":"let currentDate = new Date();\ncurrentDate.setDate(currentDate.getDate() + 1);\n\n// Format the date to YYYY-MM-DD\nlet year = currentDate.getFullYear();\nlet month = ('0' + (currentDate.getMonth() + 1)).slice(-2); // Adding 1 because months are zero-based\nlet day = ('0' + currentDate.getDate()).slice(-2);\nlet formattedDate = year + '-' + month + '-' + day;\n\nmsg.start_date = formattedDate;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":100,"wires":[["403b6a3cd68b67c4"]]},{"id":"dc16d1889207dc1c","type":"http request","z":"bd0839aee9138ce9","name":"get recipe for tomorrow","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://mealie-recipes:9000/api/recipes/{{{recipeId}}}","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"bearer","senderr":false,"headers":[],"x":310,"y":260,"wires":[["d2048ea8d9e3ba36"]]},{"id":"f95f8b3686b07a9b","type":"function","z":"bd0839aee9138ce9","name":"get recipeId","func":"if (msg.payload.items.length>0) {\n msg.recipeId = msg.payload.items[0].recipeId;\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":391,"y":180,"wires":[["c30cf32f3fb9dcb0"]]},{"id":"1d7bcc9aea364223","type":"json","z":"bd0839aee9138ce9","name":"","property":"payload","action":"","pretty":false,"x":250,"y":180,"wires":[["f95f8b3686b07a9b"]]},{"id":"d2048ea8d9e3ba36","type":"json","z":"bd0839aee9138ce9","name":"","property":"payload","action":"","pretty":false,"x":490,"y":260,"wires":[["18553b8d68008d00"]]},{"id":"18553b8d68008d00","type":"function","z":"bd0839aee9138ce9","name":"find tag from ingredients","func":"var recipe = msg.payload;\n\nmsg.payload = {};\nmsg.payload.recipe_name = recipe.name;\nmsg.payload.fridge = null;\n\nvar keyword = \"freezer\";\nvar tag = \"[\" + keyword +\"]\";\nvar freezerIngredients = Array();\nfor (let i = 0; i < recipe.recipeIngredient.length; i++) {\n var ingredient = recipe.recipeIngredient[i];\n if (ingredient.display.includes(tag)) {\n // remove tag and add to the array\n freezerIngredients.push(ingredient.display.replace(' '+ tag, ''));\n }\n}\nif (freezerIngredients.length > 0) {\n msg.payload.fridge = freezerIngredients.join(\" and \");\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":310,"y":340,"wires":[["6600274d3fc3c995"]]},{"id":"ab1563c57ccf9d26","type":"template","z":"bd0839aee9138ce9","name":"from fridge","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"For tomorrow {{payload.fridge}} must get out of the freezer for {{payload.recipe_name}}","output":"str","x":770,"y":320,"wires":[["dd9bfa2ced5eb6ff"]]},{"id":"6600274d3fc3c995","type":"switch","z":"bd0839aee9138ce9","name":"!= null","property":"payload.fridge","propertyType":"msg","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":510,"y":340,"wires":[["ab1563c57ccf9d26"],["cb9246ee0de6055b"]]},{"id":"2c49779e764870f5","type":"link out","z":"bd0839aee9138ce9","name":"send message","mode":"link","links":[],"x":1125,"y":320,"wires":[]},{"id":"cb9246ee0de6055b","type":"template","z":"bd0839aee9138ce9","name":"nothing out of the freezer","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"For tomorrow nothing need out of the freezer for {{payload.recipe_name}}","output":"str","x":810,"y":360,"wires":[["dd9bfa2ced5eb6ff"]]},{"id":"c30cf32f3fb9dcb0","type":"switch","z":"bd0839aee9138ce9","name":"recipeId != null","property":"recipeId","propertyType":"msg","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":560,"y":180,"wires":[["dc16d1889207dc1c"],["6b12146002663662"]]},{"id":"6b12146002663662","type":"template","z":"bd0839aee9138ce9","name":"no recipe for tomorrow","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"For tomorrow no recipe found","output":"str","x":800,"y":280,"wires":[["dd9bfa2ced5eb6ff"]]},{"id":"9f7205ae535d4aea","type":"comment","z":"bd0839aee9138ce9","name":"Get meat out of fridge (vdbrink.github.io)","info":"","x":200,"y":40,"wires":[]},{"id":"dd9bfa2ced5eb6ff","type":"rbe","z":"bd0839aee9138ce9","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":1030,"y":320,"wires":[["2c49779e764870f5"]]}]
{% endraw %}
```
> **_NOTE:_** If have/can convert it into a Home Assistant automation let me know, then I can add it here also.
#### The flow explanation
* Call the Mealie API to get all the recipes after today
* Endpoint `http://mealie-recipes:9000/api/groups/mealplans?orderBy=date&orderDirection=asc&perPage=1&start_date={{{start_date}}}`
* Endpoint `http://mealie-recipes:9000/api/households/mealplans?orderBy=date&orderDirection=asc&perPage=1&start_date={{{start_date}}}`
* Get the first recipe ID
* If there is no recipe found:
* Send a message `For tomorrow no recipe found`
Expand Down

0 comments on commit 6a7f1ae

Please sign in to comment.