Today I wanted to integrate Grocy into my Home Assistant. Mostly so that when I take out my trash, I can touch my phone to an NFC tag and it would log the chore as done in Grocy and log who took out the trash. Sounds easy enough. It's one button in Grocy after all. First I tried using what looked like a complete solution of a Grocy Integration, but for reasons likely involving my own terrible inadequacy, I couldn't get Home Assistant to find that integration via HACS, which is basically "home brew" for home assistant.
Okay, so I gave up on that, now what? Well, guess we'll have to use the web
API. Oh hey! Speaking of my terrible inadequacy I am not a web dude. Or any
kind of experienced user of Home Assistant, or Grocy. Sure, I can put bits on
wires with the best of them, but I'm more familiar with POSIX's TCP interface
than well, curl. I'm a broken embedded engineer.
Fortunately, Grocy seems ready to hold my hand with it's integrated API
documentation and playground. If you go to the /api#
of your running Grocy
install you get a neat playground of all the API
endpoints.
Okay, so looking at the /chores/{chore_id}/execute
looks like we need a
choreId
and a userId
so we can fill out the required field in the URL and
the done_by
payload field. Cool. We can find what these IDs are in our
instance by running the /users
and /chores
endpoints. You can even do that
within the API explorer. Cool, so the chore I want (Taking out the Trash) is 1
and my user id is 2, my partner's is 3. Cool. So now we just need to tell Home
Assistant all this.
The REST commands don't really have GUI components in Home Assistant to speak of
so I added the line rest_command: !include rest_commands.yaml
to the end of my
Home Assistant configuration.yaml. Then I opened up a blank rest_commands.yaml
and
put in the following.
do_chore:
url: 'http://GROCYURL/api/chores/{{ chore_id }}/execute'
method: POST
headers:
accept: application/json
GROCY-API-KEY: !secret grocy_api
payload: '{"done_by": {{ chore_doer }} }'
content_type: application/json
Oh, also in your secrets.yaml put a grocy_api
key. You can get that from the Grocy
interface under Manage API Keys.
Next I made the NFC tag that I taped to the kitchen trash can. I could scan it
and it showed up as scanned. So now if I hardcoded the chore_doer
it was
easy. All I had to do was create an automation that triggered when the tag was
scanned. Then hit "Add Action" and select my new RESTful Command
'rest_command.do_chore'
. And add to the "Action data" field the following:
chore_id: 1
chore_doer: 2
Cool. That works! For just me... It ignores who scanned the tag. So we're
almost there. Well, that information has to be somewhere right? I went to the
Home Assistant logbook and found where the tag was scanned and the automation
was triggered. In the "changed variables" field I saw a buncha data. One field
that looked super interesting was trigger.event.data.device_id
. Is this what
I'm looking for? Nope. That's the id for the tag itself. Boooo. But the next
field I saw was trigger.context.user_id
. Ooooooooooooh, I'm a user! That's me!
So it looks like I should have access to that. But even if I do, we have another
problem, the user_id
isn't the grocy_id
we need.
It was at this point I decided to commit terrible code sins for the sake of getting
back to drinking Mai Tais. The Home Assistant user interface doesn't seem to make it
easy to put in a lookup table. Or at least not cleanly. So I opened up automations.yaml
and altered what was there to look roughly like the following:
- id: 'SOMEID'
alias: Take out Trash
variables:
device_to_grocy:
abc2145bacacbdea23123123124513aa: 2
1254213809abdcadbcdebacb21312546: 3
description: ''
triggers:
- trigger: tag
tag_id: kitchen_trash
conditions: []
actions:
- variables:
grocy_id: '{{ device_to_grocy.get(trigger.event.context.user_id, 1) }}'
- action: rest_command.do_chore
metadata: {}
data:
chore_id: 1
chore_doer: '{{ grocy_id }}'
mode: single
Yeeeeeeeeeeeeeeeeeeeeah hardcode that lookup table. Oh I'm aware it's terrible.
I don't know how to clean it up yet since I probably want to use both the
do_chore
command and that lookup table again. I'm sure there's some kinda
template or jamming that data into some sort of entity that I can use, but it
works! And until I add a new chore, it's only a moderately shameful solution.