Google Maps/Places popular times component

Nice use-case. I’ve looked into using the Google popular times data as well, but Google blocks the data after a while. Maybe you all could try as alternative data-source https://BestTime.app . They provide foot-traffic data that comes closes to Google but with an easier software API. You can start with a free test account, but unfortunately it is paid for higher usage. Anyway this works for me to track the popularity for several places every hour.

I have been using the popular times component without problem but on 9/15 it appears to have stopped updating. I don’t see any error messages related to populartimes in the Logs. Anyone having similar problems or suggestions on how to troubleshoot?

I’m seeing the same thing. However, the cause seems to be that google maps has stopped reporting live busyness data for some places. I have 2 sensors, both report 0 busyness right now. But last week only one did. Google maps reported exactly the same though, so I cant fix that.

Hi,
Can you describe this step by step? I’m not sure where to add this :frowning:

I have now updated the component with these changes:

  • Added fallback to historical Maps data, for when live popularity is not reported for a place.
  • Added a new attribute to indicate whether current state is from historical or live data.

If you update (via HACS) to version 0.25 you should see historical data reflect in the sensor’s value :slight_smile:

Fantastic change - looks really good. Thanks!

To show if the current info with and indication if it is live data or not, I made the following. It also retrieves the historical data for the current day of the week and current hour.

{% set array = state_attr('sensor.peakhours', 'popularity_' ~ now().strftime('%A').lower()) %}
{% set popular_now = states('sensor.peakhours') | int %}
Popularity: {{ popular_now }}%
{% if state_attr('sensor.peakhours', 'popularity_is_live') == true %}This is live data.
{% else %}This is not live data.
{% endif %}
{% set historical_now = array[now().hour - 1] %}
Historical info on this day & hour: {{ historical_now }}%
Next 3 hours: {{ array[now().hour]}}%, {{ array[now().hour + 1]}}%, {{ array[now().hour + 2]}}%
{% if popular_now < historical_now %}Less busy than normal.
{% elif popular_now == historical_now %}Normal.
{% elif popular_now > historical_now %}Busier than normal.
{% endif %}
1 Like

Any suggestions on how to show the popular times sensor data on a map card? Is it possible?

Is this still functional? I installed successfully but it errored out when adding a component. Going to probably start looking into the api for BestTime.app instead.

It’s still functional on my side.

Still working good. No issues.

Just found out about this sensor, very handy!

Works on first attempt and status updates, however I do see this error in HA UI:

We have generated statistics for ‘Sportiv’ (sensor.sportiv) in the past, but it no longer has a state class, therefore, we cannot track long term statistics for it anymore.

Does anyone know if I have to configure a state class (and if yes, which one should it be?)?

Thank you!

That is strange, I do not have this log line in my own log.
I did create a new release which specifies state_class as measurement. Maybe you can update to version 0.27 and see if the issue in your log is now fixed?

Thanks for your reply.

I updated to the latest version. And I see the state-class is present.

In the meantime I also discovered that I still had a very old sensor active with the same entity_id. So that probably caused the confusion and change of the sensor attributes.

Sorry for the confusion.

No worries, glad you resolved it :wink:

1 Like

I love this component.

Thanks to this I was able to build a heatmap for my local gym:

Minor issue I’m facing now is that the component seems to update not frequently enough to differentiate the 30 mins slots.

Is there any way to increase the update frequency?

Are you willing to share the .ymal of you’re top setup? I would like to integrated it into my dash.

Sure, here you go:

type: vertical-stack
cards:
  - type: horizontal-stack
    cards:
      - type: gauge
        entity: sensor.healthclub_sportiv
        max: 100
        severity:
          green: 0
          yellow: 50
          red: 75
        needle: true
        name: Currently busy at Sportiv?
      - type: markdown
        content: >
          {% set array = state_attr('sensor.healthclub_sportiv', 'popularity_' ~
          now().strftime('%A').lower()) %} {% set popular_now =
          states('sensor.healthclub_sportiv') | int(default=0) %}

          {% if array and array is iterable and array | count > now().hour %}
            {% set array_copy = array[:]|list %}
            {% set historical_now = array_copy[now().hour - 1] if now().hour > 0 else array_copy[0] %}
            {% set deviation = ((popular_now - historical_now) / historical_now * 100) | abs if historical_now > 0 else 0 %}
          {% else %}
            {% set historical_now = 0 %}
            {% set deviation = 0 %}
          {% endif %}

          {% if state_attr('sensor.healthclub_sportiv', 'popularity_is_live') ==
          true %} **This is live data**,  

          {% else %} **This is NOT live data**,  

          {% endif %} Currently it's  

          {% if deviation < 5 %}
            <font size="5"><font color="#2ea1cc">Normal.</font></font>
          {% elif popular_now < historical_now %}
            <font size="5"><font color="#59b82c">Less busy than normal.</font></font>
          {% else %}
            <font size="5"><font color="#ff5733">Busier than normal.</font></font>
          {% endif %} <br> <font size="2"><font color="#ffffff">Expectation next
          3 hours:</font></font>

          {% if array and now().hour + 2 < array | count %}
            <font size="5">{{ array_copy[now().hour] }}%, {{ array_copy[now().hour + 1] }}%, {{ array_copy[now().hour + 2] }}%</font>
          {% else %}
            <font size="5">Data unavailable for future hours.</font>
          {% endif %}
    card_mod:
      style: |
        ha-card {
        border-radius: 15px;
        box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2);
        padding: 12px;
        }
visibility:
  - condition: state
    entity: sensor.healthclub_sportiv
    state_not: "0"
grid_options:
  columns: 12
  rows: 5

2 Likes