Baby's first Homeassistant Rest Calls

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.

social