Is there any way to detect when someone modify Shopping list?

Target:
I want to use HA Shopping sincronized with Amazon Alexa shopping list.

I already had “Alexa Actions for HA” and node-red so I can simply call an intent in a skill for do the stuff. In the skill I can read shopping list from HA and from Alexa but the problem is what is the “main” list in the merge process? I don’t think that is possible update HA list when I add something to alexa so my idea is 2 merge process at the same time:

  • every x minutes I merge alexa list into HA list, Alexa is the main
  • when I edited HA list I merge HA list in Alexa list, HA is the main

so the problem is: how can I detect a change on home assistant shopping list? Is there a event?

Alternately: is there any way to trig something when i add something to alexa shopping list?

I’m not aware of an ootb event or way to detect change but the entire shopping list is in the /config/.shopping_list.json file. So you could make a command line sensor out of it with something like this:

sensor:
- platform: command_line
  name: Shopping list
  command: >-
    jq  '{"list": .}' /config/.shopping_list.json
  value_template: '{{ value_json.list | count }}'
  json_attributes: ['list']
  unit_of_measurement: items

Then you can watch that sensor like normal and trigger off changes. It’ll poll every 60 seconds by default, can customize that with scan_interval.

Remember to exclude it from recorder though. Its state will probably be way too big so you’ll get errors about inserting text too big for the column otherwise.

1 Like

Thank you, it’s not an elegant solution but it’s probably the only available.

can you also help me to define a second sensor with only active (or completed) items?

this is my config:

sensor:
  - platform: command_line
    unique_id: shopping_list_total_items
    name: shopping list total items
    command: >-
      jq  '{"list": .}' /config/.shopping_list.json
    value_template: '{{ value_json.list | count }}'
    unit_of_measurement: items
  - platform: command_line
    unique_id: shopping_list_active_items
    name: shopping list active items
    command: >-
      jq  '{"list": .}' /config/.shopping_list.json
    value_template: "{{ value_json | selectattr('complete', 'eq', false) | list | count }}"
    unit_of_measurement: items
  - platform: command_line
    unique_id: shopping_list_complete_items
    name: shopping list complete items
    command: >-
      jq  '{"list": .}' /config/.shopping_list.json
    value_template: "{{ value_json | selectattr('complete', 'eq', true) | list | count }}"
    unit_of_measurement: items

The problem is probably on the template {{ value_json | selectattr('complete', 'eq', false) | list | count }}. I try to read the docs and make a lot of try but the sensors always show 0.

So if you look at the file you’ll see this:

[
  { ...item1... },
  { ...item2...},
  ...
]

I used jq to turn that into this

{
  "list": [
    { ...item1... },
    { ...item2...},
    ...
  ]
}

Because the json_attributes option only works when the response is a JSON object, you list fields to capture. If the response is a JSON array then you can’t capture the shopping list in attributes.

For your other sensors you don’t care about that, you aren’t using json_attributes. So just change the command to cat /config/.shopping_list.json and don’t bother with jq.

Although actually it’s probably better to just make those template sensors like this:

template:
- sensor:
  - name: shopping list active items
    unique_id: shopping_list_active_items
    state: >-
      {{ state_attr('sensor.shopping_list_total_items', 'list')
        | selectattr('complete', 'eq', false) | list | count }}
    unit_of_measurement: items
  ...(I assume you can take it from here)

Since command line sensors are polling it’s better to just have one polling sensor that pulls in the list. Then have other sensors simply look at that one and react to it’s changes rather then polling the same file separately.