Automating your shopping list with Home Assistant and Grocy

Today I'm going to show you some of the ways I'm using Home Assistant and Grocy to automate our shopping list. Using Home Assistant with Grocy allows our smart home to tell us when we need to purchase something, as opposed to adding things to a shopping list when it's already too late.
Automating your shopping list with Home Assistant and Grocy

What is Grocy?

If you're running HASS IO, you may have seen an add-on from Franck called Grocy. This little gem is a stock management system for the home. Grocy allows you to know how much of a product you have at home, and to track when items are due to expire. For example how many litres of milk you have at home, and when it will expire.

The recipes feature of Grocy is where it all comes together. Once you put in the ingredients required for a meal, Grocy can tell you what ingredients you have on hand to make that meal, or allow you to add missing items to the shopping list. When you cook a recipe, by the click of a button, Grocy will reduce the stock levels of those products and keep track of your remaining stock.

For those times when you don't use a fixed recipe, there is also the ability to "consume" items in Grocy. This is where you can tell Grocy you just drank a can of Fosters, so it knows how much you have left in stock.

For the most part this is great, but if you want to take full advantage of Grocy it does require you to login and track your usage of items regularly. This can get quite annoying if you need to open your phone each time you use an egg from the fridge or wake up in the night for a glass of milk. This is where we can leverage our smart home controller, in my case Home Assistant, to automate the consumption of items in Grocy.

CTA Image

Together with Rohan Karamandi, hear me break down the latest Home Assistant release and talk with other users of Home Assistant across the open-source community.

Listen Now

Setting up Home Assistant

One of the things I love about Home Assistant is its flexibility to integrate with other systems and software. There's a whole bunch of ways to integrate things, from HTTP with REST sensors and switches, to MQTT.

To make things easier, I'm going to use a Shell Command, which will make a cURL request to the Grocy REST API to consume an item. I want to be able to re-use as much code as possible, so I'm going to use template data to dynamically send data to this cURL request. This will come in handy later.

To begin, lets start with our shell command, and I'll explain what this is doing.

shell_command: 
    grocy_consume_item: "curl -X POST http://{{server_ip}}:9283/api/stock/products/{{product_id}}/consume -H 'Accept: application/json' -H 'Content-Type: application/json' -H 'GROCY-API-KEY: {{grocy_key}}' -H 'cache-control: no-cache' -d '{ \"amount\": {{amount}},  \"transaction_type\": \"consume\",  \"spoiled\": false }'"

In this command, I've got some parameters wrapped in {{brackets}}. These will allow us to use the same shell command in our scripts and automations moving forward. Let's break down these parameters.

We'll use this shell command throughout the next few scenarios.

{{server_ip}} The IP address of the server where Grocy is running. If running on the same machine as Home Assistant, this could be 127.0.0.1
{{PRODUCT_ID}} The Grocy ID of the product to be consumed. You can get this from the URL of the edit product page inside Grocy.
{{grocy_key}} The API key for your Grocy install. Get this from your Grocy settings page
{{AMOUNT}} The amount you wish to consume. This depends on the product.

Dishwashing Tablets

If you've previously read my blog on making dishwashers and washing machines smart, you'll know that my smart home knows the state of my dishwasher. This means that my home also knows when we start the dishwasher.

With this information, we can get Home Assistant to tell Grocy when we have used a dishwashing tablet.

Making ‘dumb’ Dishwashers and Washing Machines Smart: Alerts When the Dishes and Clothes Are Cleaned
I love the idea of everything in my home being able to communicate with each other. Thanks to Home Assistant I already have a lot of things talking to each other. This is going to solve a massive first world problem. Or maybe it won’t. I’ll let you decide. The

Setting up Grocy

First we need to create a product in Grocy for dishwashing tablets. For this I've created a new Quantity Unit called tablet. Once I've created a product in Grocy, I then use the inventory to record how many dishwashing tablets I have in the house.

There's a couple of things going on in this screenshot, so let me explain.

The minimum stock amount is defined when you create your item in Grocy. Once I have less than 60 dishwashing tablets in stock, Grocy will mark the item as low in stock and prompt me to add this to my shopping list.

Next up is the QU Purchase or Quantity Purchase. Here you'll notice I've created a Quantity Unit in Grocy called 80pk Box. This is because you don't go to the supermarket and ask for 1 dishwashing tablet. You buy them in packs. For me, the brand I like to use always comes in an 80pk box. For this reason, the QU Factor is set to 80. This means when I purchase 1 box of dishwashing tablets, Grocy will automatically add 80 tablets in stock.

Finally the Product Group is handy for the shopping list feature. Items will be grouped together nicely, so when you're in the supermarket you can have your shopping list arranged into the aisles.

Once we've created the product we can use the Inventory feature of Grocy to tell Grocy how many tablets we have in stock already. Once Grocy knows how many dishwashing tablets are in the house, its time to tell Home Assistant to consume (remove 1 tablet from stock) each time the dishwasher starts.

Home Assistant

To start off simple, each time my dishwasher goes into the Running state, I want Home Assistant to remove 1 tablet from Grocy. To do that, I'll use the following automation.

#dishwasher.yaml
- alias: Dishwasher consume tablet running
    trigger:
      - platform: state
        entity_id: sensor.dishwasher_status
        to: 'Running'
    action:
      - service: shell_command.grocy_consume_item
        data:
          server_ip: 127.0.0.1
          grocy_key: GROCY123APIKEY
          product_id: 59
          amount: 1

Pretty basic, right? Using those template variables in the shell command, we can also use Home Assistant secrets as variables. This way if your product ID for dishwashing tablets changes in the future, you've just got one place to update.

Although now I have a problem. Let's take a look at the diagram from my Dishwasher state automation.

In this diagram, we can see that the state can go back to Running in the middle of a cycle. This means each time the power drops and comes back up, Home Assistant will remove a dishwashing tablet from my stock, even though I haven't put another tablet in the dishwasher.

I need to stop this from happening. So let's go ahead and make a small change to our automation above.

#dishwasher.yaml
- alias: Dishwasher consume tablet running
    trigger:
      - platform: state
        entity_id: sensor.dishwasher_status
        to: 'Running'
    action:
      - service: shell_command.grocy_consume_item
        data:
          server_ip: 127.0.0.1
          grocy_key: GROCY
          product_id: 59
          amount: 1
      - service: homeassistant.turn_off
        entity_id: automation.dishwasher_consume_tablet_running

This will turn the automation off once it has been run. Now we need another automation to turn this back on once the dishwasher door has been opened.

#dishwasher.yaml
- alias: Dishwasher consume tablet enable
    trigger:
      - platform: state
        entity_id: sensor.dishwasher_status
        to: Dirty
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: sensor.dishwasher_status
          state: Dirty
        - condition: state
          entity_id: automation.dishwasher_consume_tablet_running
          state: 'off'
    action:
      - service: homeassistant.turn_on
        entity_id: automation.dishwasher_consume_tablet_running

Now Home Assistant will automatically remove a dishwashing tablet from my stock levels when the dishwasher is run. Grocy will prompt me to buy tablets when stock levels get below my set threshold.

Washing Machine

So the dishwasher was pretty simple. But what about something a tiny bit more complicated? The washing machine needs to manage two items. Washing Powder and Fabric Softener. However unlike the dIshwasher, these are different amounts. Washing powder is measured in weight, whilst the Fabric Softener is measured in litres.

This makes things slightly tricky. For my washing powder, I can easily use a kitchen scale to weigh how much a scoop of powder consumes. Luckily for the liquid, it mentions there are 25 washes in the bottle. Using this, we can do some maths to work out how much Home Assistant should subtract each time the washing machine is turned on.

2000ml / 25 washes = 80ml per wash

From there, we can then plug these into our Home Assistant automations.

#washing.yaml
- alias: Washing Machine Powder Consume
    trigger:
      - platform: state
        entity_id: sensor.washing_machine_status
        to: 'Running'
    action:
      # Consume washing detergent / fabric softener
      - service: shell_command.grocy_consume_item
        data:
          server_ip: 127.0.0.1
          grocy_key: GROCYKEY
          product_id: 24
          amount: 80
      # Consume washing powder
      - service: shell_command.grocy_consume_item
        data:
          server_ip: 127.0.0.1
          grocy_key: GROCYKEY
          product_id: 23
          amount: 45
      - service: homeassistant.turn_off
        entity_id: automation.washing_machine_powder_consume
 

In Grocy I've set these items up with the right purchase and consumption units like the dishwashing tablets.

Regular Consumables

So far we've automated things where Home Assistant can "see" them being consumed. But what about other things that Home Assistant can't see via sensors?

For daily things, we can setup timed automations to execute at a certain time. For example every day at 9am, remove a breakfast bar from stock, but only if it is a workday.

#grocy.yaml
- alias: Consume breakfast bar on Work Day
    trigger:
      - platform: time
        at: '08:00:00'
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: binary_sensor.workday_sensor
          state: 'on'
    action:
      - service: shell_command.grocy_consume_item
        data_template:
          server_ip: 127.0.0.1
          grocy_key: GROCYKEY
          product_id: 32
          amount: 1

For items consumed on an ad-hoc basis, we can use the Home Assistant interface. This would be particularly helpful for a tablet like an Amazon Fire Tablet mounted to a wall in the kitchen.

We can easily create scripts, which can be used to tell Grocy to consume items when called. Here's a script which will remove 100ml of Milk from stock when executed.

#grocy.yaml
script:
  grocy_consume_milk:
    alias: Consume Glass of Milk
    sequence:
      - service: shell_command.grocy_consume_single_item
        data:
          server_ip: 127.0.0.1
          grocy_key: GROCYKEY
          product_id: 4
          amount: 0.1 #Grocy tracks Milk in litres, so mark 0.1 litres as consumed
 

Which can appear in Lovelace with an entity card like:

Alerting when item below threshold

Grocy has the ability to mark items in its interface when they are below a threshold. However this requires you to open the Grocy interface. It would be better if Home Assistant could send you a notification when your stock levels have reached a certain point.

We can easily do this with a REST Sensor, and some automations. We'll need to use a full URL to the Grocy API for this.

#grocy.yaml
sensor:
  - platform: rest
    resource: http://127.0.0.1:9283/api/stock/products/52
    headers:
      GROCY-API-KEY: GROCYKEY
    name: Dishwashing Tablets
    value_template: '{{ value_json.stock_amount }}'
    scan_interval: 3600
    json_attributes:
      - last_purchased

Now we'll setup an automation to send a notification at 9:30pm if there are less than 10 dIshwashing tablets in stock.

#grocy.yaml
automation:
  - alias: Alert when Dishwashing tablets below threshold
    trigger:
      - platform: time
        at: '21:30:00'
    condition:
      condition: and
      conditions:
        - condition: numeric_state
          entity_id: sensor.dishwashing_tablets
          below: 10
        - condition: time
          before: '23:00:00'
          after: '20:00:00'
    action:
      - service: notify.phil
        data:
          message: Oh no you need to buy Dishwashing tablets!
          title: Dishwashing Tablets

Maybe instead of bugging me at 9:30pm when the grocery store is closed, Home Assistant could just add the item to my shopping list once. There are several different systems Home Assistant can integrate with for this. For example you may choose to send an email to Todoist. For the sake of simplicity, I'm going to use the Home Assistant shopping list for this example.

#dishwashing.yaml
 
automation:
  - alias: Dishwashing tablets shopping list add
    trigger:
      - platform: state
        entity_id: sensor.dishwashing_tablets
        state: 10
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: sensor.dishwashing_tablets
          state: 10
    action:
      - service: shopping_list.add_item
        data:
          name: Dishwashing Tablets

You can also automate marking the items as done once the stock amount returns to a normal threshold

#dishwashing.yaml
automation:
  - alias: Dishwashing tablets shopping list complete
    trigger:
      - platform: numeric_state
        entity_id: sensor.dishwashing_tablets
        above: 40
    condition:
      condition: and
      conditions:
        - condition: numeric_state
          entity_id: sensor.dishwashing_tablets
          above: 40
    action:
      - service: shopping_list.complete_item
        data:
          name: Dishwashing Tablets

The only problem with marking things off the Home Assistant shopping list automatically is that there is no way to check if an item exists in the Shopping List. This means each time you use a dishwashing tablet, and it goes down from 50 -> 49, 49 -> 48 this automation will get called and may throw some errors.

We can simply turn the automation off so that once the Dishwashing tablets have been marked as complete, we won't try again.

#dishwashing.yaml
automation:
  - alias: Dishwashing tablets shopping list complete
    trigger:
      - platform: numeric_state
        entity_id: sensor.dishwashing_tablets
        above: 40
    condition:
      condition: and
      conditions:
        - condition: numeric_state
          entity_id: sensor.dishwashing_tablets
          above: 40
    action:
      - service: shopping_list.complete_item
        data:
          name: Dishwashing Tablets
      - service: automation.turn_off
        data:
          entity_id: automation.dishwashing_tablets_shopping_list_complete
 

For good measure we should also turn that automation back on, once we have added the item to the shopping list.

#dishwashing.yaml
automation:
  - alias: Dishwashing tablets shopping list add
    trigger:
      - platform: state
        entity_id: sensor.dishwashing_tablets
        state: 10
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: sensor.dishwashing_tablets
          state: 10
    action:
      - service: shopping_list.add_item
        data:
          name: Dishwashing Tablets
      - service: automation.turn_on
        data:
          entity_id: automation.dishwashing_tablets_shopping_list_complete

Making it simple with the Grocy custom component

ℹ️
As of May 2025 the Grocy custom component has been marked as no longer being maintained, and has been removed from HACS.

The examples I've given so far will work for any Home Assistant installation, because they're using core components to talk directly with the Grocy API.

There is also a custom component for Home Assistant from Sebastian Rutofski. Using the custom component, you could instead use service calls and sensors instead of relying on shell commands and REST sensors. If you're interested, you can check out that component on GitHub.

The Grocy custom component is also available for one-click install via the Home Assistant Community Store (HACS).

Going Further

So far we've got the the shopping list automated based on time, and when devices change state. However there's some other cool use cases you could use with Home Assistant. Here's some ideas...

  • Use a Xiaomi Wireless button as a "consume button". Stick these near your fridge or pantry, and label the button. Each time you press the button, Home Assistant will remove the applicable item (for example 200ml of Milk, or a can of soda) from your stock levels.
  • Automatically update the stock levels of the popcorn when a movie starts playing on Plex late at night.
  • Remove a portion of soap or shampoo from your inventory each time someone has a shower, by taking action when a water leak sensor in your shower is activated.
  • Use an ESP8266 device with a weight sensor to automatically report the stock levels of jarred items like flour or sugar directly into Grocy.
  • If your device tracker GPS enters a radius near the grocery store, have Home Assistant email you any items that are below the threshold set in Home Assistant.

See the products I use in my smart home

Check out my Kit

Subscribe to stay updated.

Don't miss anything. Get all the latest posts delivered straight to your inbox. It's free!
Great! Check your inbox and click the link to confirm your subscription.
Error! Please enter a valid email address!