-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
16 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 --> | ||
|
@@ -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/ | ||
|
@@ -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 | ||
|
@@ -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: | ||
|
@@ -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: | ||
|
@@ -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` | ||
|