Frigate MQTT sensor

I have (I think) created an MQTT sensor to return the direction of car travel along a driveway:

mqtt:
  sensor:
    - name: driveway_car_direction
      state_topic: "frigate/events"
      value_template: >-
        {% if (states(payload_json["before"]["current_zones"] == "right") AND (states(payload_json["before"]["entered_zones"]) == "middle") %}
          arriving
        {% if (states(payload_json["before"]["current_zones"] == "left") AND (states(payload_json["before"]["entered_zones"]) == "middle") %}
          leaving
        {% else %}
          false
        {% endif %}

Three zones are defined for the camera:

- right
- middle
- left

However, the sensor doesn’t show up in dev tools and I’m stuck as to why. It passes config check OK.

Any ideas?

I should add that I’m a bit of a novice with templating!

So after either restarting Home Assistant or executing Reload Manually Configured MQTT Entities, the entity named sensor.driveway_car_direction isn’t listed in Developer Tools > States?

Which version of Home Assistant are you using?

BTW, you should know that the template contains errors. Use value_json to reference the received JSON payload (not payload _json). Refer to the example in the documentation.

Also, based on your description of what is contained in current_zones, you shouldn’t be using the states() function. That’s for getting an entity’s state value and current_zones doesn’t contain an entity’s entity_id.

Correct.

core-2022.6.6

Thanks for the reply. I appreciate that there may be errors in the template but I hadn’t got that far as it doesn’t show up.

EDIT:

I now have this:

mqtt:
  sensor:
    - name: driveway_car_direction
      state_topic: "frigate/events"
      value_template: >-
        {% if ((value_json["before"]["current_zones"]) == "right") AND ((value_json["before"]["entered_zones"]) == "middle") %}
          arriving
        {% if ((value_json["before"]["current_zones"]) == "left") AND ((value_json["before"]["entered_zones"]) == "middle") %}
          leaving
        {% else %}
          false
        {% endif %}

Still. not showing up and the template doesn’t pass the check in dev tools. I get TemplateSyntaxError: expected token 'end of statement block', got 'AND'

Am I going about this the wrong way?

Let’s set aside the template errors for a moment. The fact that your original version, the one that passed Configuration Check but failed to appear in Developer Tools > States view, means Home Assistant ignored/rejected it. That’s what needs to be fixed first.

Have you confirmed the MQTT integration is installed and working properly?
Is this your first MQTT Sensor or have you configured others in the past?

Thank you for your help with this.

Yes, sorting out the recognition of the sensor needs to come first.

Frigate uses MQTT for all communication and I’ve been monitoring its messages with MQTT Explorer. I can both listen and publish, so MQTT is working fine.

Yes, this is my first MQTT sensor. I have tried it configured in configuration.yaml and in a separate file with a pointer to it from configuration.yaml. Same result either way.

I have tried reloading just the manually configured MQTT entities and also full HA restart.

I’ve also tired the same config on another HA instance, with the same result.

Just two questions to clarify the situation:

Have you installed the MQTT integration?

Are you using Home Assistant version 2022.6.X or an older version?

Yes, MQTT integration is all installed and fine.

I’m running 2022.6.6.

I’ve just stripped out everything to this:

sensor:
  - name: driveway_car_direction
    state_topic: "frigate/events"
    value_template: "{{ value_json.temperature }}"

This is now in a separate mqtt.yaml file and I can now see it in dev tools following a restart.

It seems my poor template is the issue.

So, what do I need to change there?

It works now but it didn’t work before? :thinking:

The template itself wouldn’t determine if the sensor is created or not so what else did you change to make it work?

For the template, try this:

      value_template: >-
        {% set current = value_json.before.current_zones %}
        {% set entered = value_json.before.entered_zones %}
        {% if current == 'right' and entered == 'middle' %}
          arriving
        {% elif current == 'left' and entered == 'middle' %}
          leaving
        {% else %}
          false
        {% endif %}

I really changed nothing else. I just looked at the example from the docs and copied it. I’m at a loss to understand this too.

You template suggestion seems to be just what is needed.

Should this sensor update with each message to the state_topic?

When I set its state in dev tools and then publish to the topic it clears the sensor state.

I’m publishing this, which is what Frigate publishes on detection:

{"before": {"id": "1656607545.592707-rj7g0u", "camera": "driveway", "frame_time": 1656607547.245374, "snapshot_time": 1656607547.245374, "label": "car", "top_score": 0.6171875, "false_positive": false, "start_time": 1656607545.592707, "end_time": null, "score": 0.640625, "box": [289, 152, 336, 178], "area": 1222, "region": [127, 7, 447, 327], "stationary": false, "motionless_count": 1, "position_changes": 1, "current_zones": [], "entered_zones": ["left"], "has_clip": true, "has_snapshot": true}, "after": {"id": "1656607545.592707-rj7g0u", "camera": "driveway", "frame_time": 1656607550.038609, "snapshot_time": 1656607547.245374, "label": "car", "top_score": 0.6171875, "false_positive": false, "start_time": 1656607545.592707, "end_time": null, "score": 0.62890625, "box": [442, 158, 462, 177], "area": 380, "region": [171, 5, 491, 325], "stationary": false, "motionless_count": 0, "position_changes": 1, "current_zones": ["right"], "entered_zones": ["middle", "left"], "has_clip": true, "has_snapshot": true}, "type": "new"}

I just reverted to my original template and the sensor shows up! Clearly, I did, inadvertently, change something else. Sorry! I know how frustrating that can be.

Yes.

The sample payload you posted shows that current_zones contains a list and not merely a string.

The brackets you see here indicate the value is a list (the first list is empty and the second one contains a single item):

"current_zones": [], "entered_zones": ["left"]

Try this version:

      value_template: >-
        {% set current = value_json.before.current_zones %}
        {% set entered = value_json.before.entered_zones %}
        {% if 'right' in current and 'middle' in entered %}
          arriving
        {% elif 'left' in current and 'middle' in entered %}
          leaving
        {% else %}
          false
        {% endif %}

NOTE

Seeing that current_zones might contain an empty list, does that affect the logic you created for reporting arriving/leaving/false?

I don’t know yet.

In theory, every detected car will cause one entry in current_zones and no more than two in entered_zones.

However, it’s possible that either zone could be empty if the AI in frigate failed to detect the car in any zone (though I have to say, it’s pretty good).

At the moment, whatever I set current_zones and entered_zones to before publishing, the state always gets set to false.

Could this be because the list contains “left” (6 characters) for example, but the template is looking for left, if you get what I mean?

Here’s how it appears in a more readable form:

{
  "before": {
    "id": "1656607545.592707-rj7g0u",
    "camera": "driveway",
    "frame_time": 1656607547.245374,
    "snapshot_time": 1656607547.245374,
    "label": "car",
    "top_score": 0.6171875,
    "false_positive": false,
    "start_time": 1656607545.592707,
    "end_time": null,
    "score": 0.640625,
    "box": [
      289,
      152,
      336,
      178
    ],
    "area": 1222,
    "region": [
      127,
      7,
      447,
      327
    ],
    "stationary": false,
    "motionless_count": 1,
    "position_changes": 1,
    "current_zones": [],
    "entered_zones": [
      "left"
    ],
    "has_clip": true,
    "has_snapshot": true
  },
  "after": {
    "id": "1656607545.592707-rj7g0u",
    "camera": "driveway",
    "frame_time": 1656607550.038609,
    "snapshot_time": 1656607547.245374,
    "label": "car",
    "top_score": 0.6171875,
    "false_positive": false,
    "start_time": 1656607545.592707,
    "end_time": null,
    "score": 0.62890625,
    "box": [
      442,
      158,
      462,
      177
    ],
    "area": 380,
    "region": [
      171,
      5,
      491,
      325
    ],
    "stationary": false,
    "motionless_count": 0,
    "position_changes": 1,
    "current_zones": [
      "left"
    ],
    "entered_zones": [
      "middle",
      "left"
    ],
    "has_clip": true,
    "has_snapshot": true
  },
  "type": "new"
}

No difference from what you posted earlier. Both current_zones and entered_zones contain a list value, not a simple string, so you cannot simply use if value_json.before.entered_zones == 'middle'. You have to check if the list contains the desired value (as shown in my revised template).

BTW, if current_zones is an empty list then the template will definitely report “false”.

1 Like

Thank you for all of your help. I appreciate it.

1 Like