Displaying Birdnet-go detections

No fighting with other important issues at the moment (shitty iotawatt integration), but something has to be done. I replaced the microphone and now the birdnet list of detections is 100s of lines long each day.

Yes, me too - for now, I reverse sort them by time, and show the top 10…

1 Like

That’s a good idea. Care to share your config for this?

Just a small addition to your markdown card:

  - type: markdown
    title: "BirdNET Events"
    content: |-
      Time|CommonName|Confidence
      :---|:---|:---
      {%- set t = now() %}
      {%- set bird_list = [] %}
      {%- for bird in (state_attr('sensor.birdnet_intake','bird_events')| sort(attribute='time', reverse=true))[0:10] or []  %}
      {{bird.time}} | {{bird.name}} | {{bird.confidence }}
      {%- endfor %}

My next attempt will be to show just the most recent ‘sighting’ of each bird…

2 Likes

I’ve also used the new webpage dashboard to put the full BirdNET dashboard in the side menu but it only works when I’m at home and using http access.

This code presents the most recent sighting of each unique bird in your events:

  - type: markdown
    title: "BirdNET Events"
    content: |-
      Time|Common Name|Day Count|Max Confidence
      :---|:---|:---:|:---:
      {%- set t = now() %}
      {%- set bird_list = state_attr('sensor.birdnet_intake','bird_events') | sort(attribute='time', reverse=true) | map(attribute='name') | unique | list %}
      {%- set bird_objects = state_attr('sensor.birdnet_intake','bird_events') | sort(attribute='time', reverse=true) %}
      {%- for thisbird in bird_list or [] %}
      {%- set ubird = ((bird_objects | selectattr("name", "equalto", thisbird)) | list)[0] %}
      {%- set ubird_count = ((bird_objects | selectattr("name", "equalto", thisbird)) | list) | length %}
      {%- set ubird_max_confidence = ((bird_objects | selectattr("name", "equalto", thisbird)) | map(attribute='confidence') | max) %}
      {{ubird.time}} | {{ubird.name}} | {{ubird_count}} | {{ubird_max_confidence }}
      {%- endfor %}

(edited to show most recent version)

3 Likes

That’s awesome. Thank you for sharing. The only addition I made was a couple of   spaces in front of the name and confidence for legibility:

Screenshot 2024-04-17 at 11-22-44 Mobile View – Home Assistant

Time|  Common Name|Day Count|  Max Confidence
:---|:---|:---:|:---:
{%- set t = now() %}
{%- set bird_list = state_attr('sensor.birdnet_go_events','bird_events') | sort(attribute='time', reverse=true) | map(attribute='name') | unique | list %}
{%- set bird_objects = state_attr('sensor.birdnet_go_events','bird_events') | sort(attribute='time', reverse=true) %}
{%- for thisbird in bird_list or [] %}
{%- set ubird = ((bird_objects | selectattr("name", "equalto", thisbird)) | list)[0] %}
{%- set ubird_count = ((bird_objects | selectattr("name", "equalto", thisbird)) | list) | length %}
{%- set ubird_max_confidence = ((bird_objects | selectattr("name", "equalto", thisbird)) | map(attribute='confidence') | max) %}
{{ubird.time}} |  {{ubird.name}} | {{ubird_count}} |  {{ubird_max_confidence }}
{%- endfor %}

So I got a new microphone. In the nighttime recordings (after traffic noise has died down) I can hear the waves crashing on the beach 1.3Km away and 100m below.
Lots more bird detections. Too many in-fact:

Logger: homeassistant.components.recorder.db_schema
Source: components/recorder/db_schema.py:598
integration: Recorder (documentation, issues)
First occurred: 15:26:57 (14 occurrences)
Last logged: 15:53:00

State attributes for sensor.birdnet_go_events exceed maximum size of 16384 bytes. This can cause database performance issues; Attributes will not be stored

1 Like

Create multiple sensors and filter based on time?
So 1 for the hours 00:00 - 06:00
the 2nd none for 06:00 - 12:00 etc

Hello, can you share configuration of mqtt sensor for birdnet-go? I’m trying to get the data from birdnet

mqtt:
  sensor:
    - name: "BirdNet"
      state_topic: "birdnet"
      unique_id: bird

I don’t use an mqtt sensor. I use a triggered template sensor as shown above Displaying Birdnet-go detections - #6 by tom_l

And this post: Displaying Birdnet-go detections - #7 by tom_l

1 Like

thanks Tom, it’s works for me, maybe you can tell me how to add a link to the wiki about each bird like this https://community.home-assistant.io/t/birdnet-pi/444654/10

fixed :wink:

https://en.wikipedia.org/wiki/{{bird_name | replace(' ', '_')}}

Thanks a lot for sharing this! It is awesome, and works very well.

I fine-tuned a bit the card to provide a link to the BirdNet-Go UI, filter the results (confidence above 70), embed the Wikipedia links and add a nice icon.

Here is the full card snippet in case you are interested:

It is in German, but easy to translate. You would have to replace “IP_OF_YOUR_BIRDNETGO_UI” by the IP of your HA instance or wherever your BirdNET-Go is running.

  - type: markdown
    title: Vogelbeobachtungen
    content: >-
      Uhr|  Vogelname|Anzahl Heute|    Max
      [Confidence](http://IP_OF_YOUR_BIRDNETGO_UI:8080/)

      :---|:---|:---:|:---:

      {%- set t = now() %}

      {%- set bird_list = state_attr('sensor.birdnet_go_events','bird_events') |
      sort(attribute='time', reverse=true) | map(attribute='name') | unique |
      list %}

      {%- set bird_objects =
      state_attr('sensor.birdnet_go_events','bird_events') |
      sort(attribute='time', reverse=true) %}

      {%- for thisbird in bird_list or [] %}

      {%- set ubird = ((bird_objects | selectattr("name", "equalto", thisbird))
      | list)[0] %}

      {%- set ubird_count = ((bird_objects | selectattr("name", "equalto",
      thisbird)) | list) | length %}

      {%- set ubird_max_confidence = ((bird_objects | selectattr("name",
      "equalto", thisbird)) | map(attribute='confidence') | map('replace', '%',
      '') | map('float') | max | round(0)) %}

      {%- if ubird_max_confidence > 70 %}

      {{ubird.time}}
      |  [{{ubird.name}}](https://de.wikipedia.org/wiki/{{ubird.name |
      replace(' ', '_')}}) | {{ubird_count}} | {{ ubird_max_confidence }} %

      {%- endif %}

      {%- endfor %}
    card_mod:
      style:
        $: |
          .card-header {
            display: flex !important;
            align-items: center;
          }
          .card-header:before {
            content: url("data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMDYuODcgMTE2LjY2Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2Y0ZTUwNTt9LmNscy0ye2ZpbGw6I2UzMWUyNjt9LmNscy0ze2ZpbGw6I2ZmZjt9PC9zdHlsZT48L2RlZnM+PHBhdGggZD0iTTIwNi4zNywxNi42OHMtMTYuNDQtNC4zNC0yMi43Ni00LjljMCwwLTI1LDEzLjUtMzIsMThhMTkuMTYsMTkuMTYsMCwwLDAtOC42NywxMy44OWwzNS43MS0yNi4zMmgyOEMyMDcuMzEsMTcuMzksMjA2LjM3LDE2LjY4LDIwNi4zNywxNi42OFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgMC42MykiLz48cGF0aCBkPSJNMTQ4LjU1LDI3LjMzYzcuMzItNC45LDMyLjYyLTE4LjczLDMyLjYyLTE4LjczbDAsMEEzMC42OSwzMC42OSwwLDAsMCwxNTktLjYzYTQ0LjIzLDQ0LjIzLDAsMCwwLTIwLjcxLDVIMGMwLDMuNzEsNS42LDYuNTYsMTIuMTQsNi41Nkg1Mi4zNkw4Ni42MiwzNS4xMlY3MS4zN2MwLDE1LjczLDguMjYsMjkuNDQsMjEuNzgsMzcuMzVTMTI4LjY4LDExNiwxMzguNjMsMTE2VjQ2Ljg3QzEzOC42Myw0MC43OCwxNDAuNDcsMzIuNzMsMTQ4LjU1LDI3LjMzWk0xNjcuODcsOGEyLjUxLDIuNTEsMCwxLDEtMi41MSwyLjUxQTIuNTEsMi41MSwwLDAsMSwxNjcuODcsOFptLTI5LjEzLDEzLDE1LjY5LTguNjgsNi44OS41N0wxMzguNzQsMjUuMzZaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDAuNjMpIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNTIuMzYsMTAuOTFIMTEwYy0xMi44OSwwLTIzLjQsMTAuMzUtMjMuNCwyNC4yMVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgMC42MykiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNzgsMTAuMzNBMzEuNzEsMzEuNzEsMCwwLDAsMTU3Ljc4LDIuOVYtLjYxbDEuMjUsMEEzMC42MywzMC42MywwLDAsMSwxODEuMTcsOC42WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAwLjYzKSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTE3OC42MywxNy4zOWwtMjUsMTguNDNzLS4yOS0yLjcsMy40Ny01Ljc0LDI2LjUtMTguMywyNi41LTE4LjNaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDAuNjMpIi8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMTI4LjE0LDY0LjQ3VjUyLjE1YzAtNS4xOC0yLjExLTguNzctNi45My0xMi4xOEwxMDAuNzksMjUuNTRhMTQuMzIsMTQuMzIsMCwwLDAsMiwyMVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgMC42MykiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMjguMTQsNjQuNDdWNTIuMTVjMC01LjE4LTIuMTEtOC43Ny02LjkzLTEyLjE4TDEwMC43OSwyNS41NGExNC4zMiwxNC4zMiwwLDAsMCwyLDIxWiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAwLjYzKSIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTE1MS41OSwyOS44MmM3LTQuNTQsMzItMTgsMzItMThhMTYuMjQsMTYuMjQsMCwwLDAtMi40MS0zLjE1bDAsMHMtMjUuMywxMy44My0zMi42MiwxOC43My05LjU3LDEyLjE3LTkuODcsMThsLS4wNSwxLjUxLDQuMjktMy4xNkExOS4xNiwxOS4xNiwwLDAsMSwxNTEuNTksMjkuODJaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDAuNjMpIi8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMTY3Ljg3LDhhMi41MSwyLjUxLDAsMSwxLTIuNTEsMi41MUEyLjUxLDIuNTEsMCwwLDEsMTY3Ljg3LDhaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDAuNjMpIi8+PHBvbHlnb24gY2xhc3M9ImNscy0zIiBwb2ludHM9IjEzOC43NCAyMS41NyAxNTQuNDMgMTIuODkgMTYxLjMyIDEzLjQ1IDEzOC43NCAyNS45OCAxMzguNzQgMjEuNTciLz48L3N2Zz4=");
            height: 20px;
            width: 60px;
            margin-top: -10px;
            padding-left: 8px;
            padding-right: 18px;
          }

5 Likes

Great topic! I’ve added MQTT to the birdnet-pi addon too with the same MQTT handle so that those cards can mostly be used as such

Given it publishes the SpeciesCode you could also use : https://ebird.org/species/{{SpeciesCode}} or https://ebird.org/species/{{SpeciesCode}}?siteLanguage={{language}} where language can be whatever you want to have it in your own language

Just got Birdnet-go setup (using the add-on). Would there be an easy way to also pull the thumbnail/picture of each identified bird into the card?

At the moment the solution is to open a BirdWeather account to connect your BirdNet to and then use this: Bird detector sensors and dashboard

Tangentially related, I’d like to setup two additional template sensors: The total number of detections and the total number of species identified (both above a defined confidence level and for each day, same as the markup card and main template sensor). Has anyone done this or care to show me how? Interacting with lists of data in the attributes is just a touch beyond my native abilities. Thanks in advance!

Combining a bunch of the suggestions here including @alexbelgium 's ebird links and @brooksben11 's request for totals

In my HA config file I set up the triggered template sensor (note the speciesCode field I added that the previous examples didn’t include):

template:
  - trigger:
      - platform: mqtt
        topic: "birdnet"
      - platform: time
        at: "00:00:00"
        id: reset
    sensor:
      - unique_id: c893533c-3c06-4ebe-a5bb-da833da0a947
        name: BirdNET-Go Events
        state: "{{ today_at(trigger.payload_json.Time) }}"
        attributes:
          bird_events: >
            {% if trigger.id == 'reset' %}
              {{ [] }}
            {% else %}
              {% set time = trigger.payload_json.Time %}
              {% set name = trigger.payload_json.CommonName %}
              {% set speciesCode = trigger.payload_json.SpeciesCode %}
              {% set confidence = trigger.payload_json.Confidence|round(2) * 100 ~ '%' %}
              {% set current = this.attributes.get('bird_events', []) %}
              {% set new = dict(time=time, name=name, speciesCode=speciesCode, confidence=confidence) %}
              {{ current + [new] }}
            {% endif %}                                                                                                 

I then addeed a card to my dashboard with this yaml:

type: markdown
content: >-
  Time|  Common Name|Day Count|  Max Confidence

  :---|:---|:---:|:---:

  {%- set t = now() %}

  {%- set bird_list = state_attr('sensor.birdnet_go_events','bird_events') |
  sort(attribute='time', reverse=true) | map(attribute='name') | unique | list
  %}

  {%- set bird_objects = state_attr('sensor.birdnet_go_events','bird_events') |
  sort(attribute='time', reverse=true) %}

  {%- for thisbird in bird_list or [] %}

  {%- set ubird = ((bird_objects | selectattr("name", "equalto", thisbird)) |
  list)[0] %}

  {%- set ubird_count = ((bird_objects | selectattr("name", "equalto",
  thisbird)) | list) | length %}

  {%- set ubird_max_confidence = ((bird_objects | selectattr("name", "equalto",
  thisbird)) | map(attribute='confidence') | max) %}

  {{ubird.time}} | 
  [{{ubird.name}}](https://ebird.org/species/{{ubird.speciesCode}}) |
  {{ubird_count}} |  {{ubird_max_confidence }}

  {%- endfor %}


  Total Detections: {{bird_objects | count}}

  Total Species Detected: {{bird_list | count}}
title: Birds Seen Today

Which gives me a card that looks like this:

As an aside, my setup runs the mic outside just dumping to RTSP so since I already had the RTSP set up I included that on my dashboard as well (with a live spectrogram :slight_smile: )
image

2 Likes