Nearby EV Rapid Chargers

With android auto now an option and an open API on openchargemap I decided it would be really useful to have a dashboard that constantly displays my nearest 3 rapid car chargers with useful info (cost, operator, service condition, distance).

How it works
Tracker in the car updates it’s Lat Long co-ordinates on a regular basis
Lat Long is fed to the API which returns a JSON with all the data required (API is set to nearest 3 CCS chargers within 30 miles)
JSON is processed onto Markdown cards and displayed to user - Icon colour shows status of the charging point
The user can click and that will open google maps with the destination loaded for navigation
or
They can select more info to get a detailed view of the charging point with the option of click to call the charge point operator.

Development
I would like to get more details out of the API (photos etc and include them) and harvest and present the data much more efficiently.
2 way communication - ie 1 click check in or add photos back to openchargemap
Seems to me like a good project to become a standalone integration.

DISCLAIMER
I’m very new to homeassistant and completely new to JSON and APIs - I know this is a messy/hacky way of doing it - so be gentle, I mostly did this as a learning exercise, and figured it might be useful to other people.

My config.yaml just includes rest.yaml

rest.yaml

  resource_template: "https://api.openchargemap.io/v3/poi?key=**INSERT YOU OWN API KEY**&latitude={{ state_attr('device_tracker.car', 'latitude') }}&longitude={{ state_attr('device_tracker.car', 'longitude') }}&maxresults=3&connectiontypeid=33&distanceunit=Miles&distance=30" **Adjust API key to you use**
  method: GET
  scan_interval: 600 
  sensor:
    - name: "evcharger1"
      json_attributes_path: "$[0].UsageType]"
      value_template: '{{ value_json[0]["UsageType"]}}'
      json_attributes:
        - IsPayAtLocation
        - IsMembershipRequired
        - IsAccessKeyRequired
        - Title

    - name: "evcharger1 title"
      json_attributes_path: "$[0].OperatorInfo]"
      value_template: '{{ value_json[0].OperatorInfo.Title }}'

    - name: "evcharger1 latitude"
      json_attributes_path: "$[0].AddressInfo]"
      value_template: '{{ value_json[0].AddressInfo.Latitude }}'

    - name: "evcharger1 longitude"
      json_attributes_path: "$[0].AddressInfo]"
      value_template: '{{ value_json[0].AddressInfo.Longitude }}'

    - name: "evcharger1 status"
      json_attributes_path: "$[0].StatusType]"
      value_template: '{{ value_json[0].StatusType.IsOperational }}'

    - name: "evcharger1 cost"
      json_attributes_path: "$[0].UsageCost]"
      value_template: '{{ value_json[0].UsageCost }}'

    - name: "evcharger1 distance"
      unit_of_measurement: 'Miles'
      json_attributes_path: "$[0].AddressInfo]"
      value_template: '{{ value_json[0].AddressInfo.Distance }}'

    - name: "evcharger1 address"
      json_attributes_path: "$[0].AddressInfo]"
      value_template: '{{ value_json[0].AddressInfo.Title }}, {{ value_json[0].AddressInfo.AddressLine1 }}, {{ value_json[0].AddressInfo.AddressLine2 }}, {{ value_json[0].AddressInfo.Town }}, {{ value_json[0].AddressInfo.StateOrProvince }}, {{ value_json[0].AddressInfo.Postcode }}'

    - name: "evcharger2 title"
      json_attributes_path: "$[1].OperatorInfo]"
      value_template: '{{ value_json[1].OperatorInfo.Title }}'

    - name: "evcharger2 latitude"
      json_attributes_path: "$[1].AddressInfo]"
      value_template: '{{ value_json[1].AddressInfo.Latitude }}'

    - name: "evcharger2 longitude"
      json_attributes_path: "$[1].AddressInfo]"
      value_template: '{{ value_json[1].AddressInfo.Longitude }}'

    - name: "evcharger2 status"
      json_attributes_path: "$[1].StatusType]"
      value_template: '{{ value_json[1].StatusType.IsOperational }}'

    - name: "evcharger2 cost"
      json_attributes_path: "$[1].UsageCost]"
      value_template: '{{ value_json[1].UsageCost }}'

    - name: "evcharger2 distance"
      unit_of_measurement: 'Miles'
      json_attributes_path: "$[1].AddressInfo]"
      value_template: '{{ value_json[1].AddressInfo.Distance }}'

    - name: "evcharger2 address"
      json_attributes_path: "$[1].AddressInfo]"
      value_template: '{{ value_json[1].AddressInfo.Title }}, {{ value_json[1].AddressInfo.AddressLine1 }}, {{ value_json[1].AddressInfo.AddressLine2 }}, {{ value_json[1].AddressInfo.Town }}, {{ value_json[1].AddressInfo.StateOrProvince }}, {{ value_json[1].AddressInfo.Postcode }}'

    - name: "evcharger3 title"
      json_attributes_path: "$[2].OperatorInfo]"
      value_template: '{{ value_json[2].OperatorInfo.Title }}'

    - name: "evcharger3 latitude"
      json_attributes_path: "$[2].AddressInfo]"
      value_template: '{{ value_json[2].AddressInfo.Latitude }}'

    - name: "evcharger3 longitude"
      json_attributes_path: "$[2].AddressInfo]"
      value_template: '{{ value_json[2].AddressInfo.Longitude }}'

    - name: "evcharger3 status"
      json_attributes_path: "$[2].StatusType]"
      value_template: '{{ value_json[2].StatusType.IsOperational }}'

    - name: "evcharger3 cost"
      json_attributes_path: "$[2].UsageCost]"
      value_template: '{{ value_json[2].UsageCost }}'

    - name: "evcharger3 distance"
      unit_of_measurement: 'Miles'
      json_attributes_path: "$[2].AddressInfo]"
      value_template: '{{ value_json[2].AddressInfo.Distance }}'

    - name: "evcharger3 address"
      json_attributes_path: "$[2].AddressInfo]"
      value_template: '{{ value_json[2].AddressInfo.Title }}, {{ value_json[2].AddressInfo.AddressLine1 }}, {{ value_json[2].AddressInfo.AddressLine2 }}, {{ value_json[2].AddressInfo.Town }}, {{ value_json[2].AddressInfo.StateOrProvince }}, {{ value_json[2].AddressInfo.Postcode }}'


    - name: "evcharger1 phone"
      json_attributes_path: "$[0].OperatorInfo]"
      value_template: '{{ value_json[0].OperatorInfo.PhonePrimaryContact }}'

    - name: "evcharger1 access"
      json_attributes_path: "$[0].UsageType]"
      value_template: '{{ value_json[0].UsageType.Title }}'

    - name: "evcharger1 operational"
      json_attributes_path: "$[0].StatusType]"
      value_template: '{{ value_json[0].StatusType.Title }}'

    - name: "evcharger1 points"
      json_attributes_path: "$[0].NumberOfPoints]"
      value_template: '{{ value_json[0].NumberOfPoints }}'

    - name: "evcharger1 updated"
      json_attributes_path: "$[0].DateLastStatusUpdate]"
      value_template: '{{ value_json[0].DateLastStatusUpdate }}'

    - name: "evcharger1 connections"
      json_attributes_path: "$[0].Connections]"
      value_template: >
        {%- for i in range(value_json[0].NumberOfPoints-1) or [] %}
          {{ value_json[0].Connections[i].PowerKW }}
        {% endfor %}

    - name: "evcharger1 comments"
      json_attributes_path: "$[0].UserComments]"
      value_template: >
        {%- for x in value_json[0].UserComments or [] %}
          {{ value_json[0].UserComments[x].Comment }}
        {% endfor %}

    - name: "evcharger2 phone"
      json_attributes_path: "$[1].OperatorInfo]"
      value_template: '{{ value_json[1].OperatorInfo.PhonePrimaryContact }}'

    - name: "evcharger2 access"
      json_attributes_path: "$[1].UsageType]"
      value_template: '{{ value_json[1].UsageType.Title }}'

    - name: "evcharger2 operational"
      json_attributes_path: "$[1].StatusType]"
      value_template: '{{ value_json[1].StatusType.Title }}'

    - name: "evcharger2 points"
      json_attributes_path: "$[1].NumberOfPoints]"
      value_template: '{{ value_json[1].NumberOfPoints }}'

    - name: "evcharger2 updated"
      json_attributes_path: "$[1].DateLastStatusUpdate]"
      value_template: '{{ value_json[1].DateLastStatusUpdate }}'

    - name: "evcharger2 connections"
      json_attributes_path: "$[1].Connections]"
      value_template: >
        {%- for i in range(value_json[1].NumberOfPoints-1) or [] %}
          {{ value_json[1].Connections[i].PowerKW }}
        {% endfor %}

    - name: "evcharger2 comments"
      json_attributes_path: "$[1].UserComments]"
      value_template: >
        {%- for x in value_json[1].UserComments or [] %}
          {{ value_json[1].UserComments[x].Comment }}
        {% endfor %}

    - name: "evcharger3 phone"
      json_attributes_path: "$[2].OperatorInfo]"
      value_template: '{{ value_json[2].OperatorInfo.PhonePrimaryContact }}'

    - name: "evcharger3 access"
      json_attributes_path: "$[2].UsageType]"
      value_template: '{{ value_json[2].UsageType.Title }}'

    - name: "evcharger3 operational"
      json_attributes_path: "$[2].StatusType]"
      value_template: '{{ value_json[2].StatusType.Title }}'

    - name: "evcharger3 points"
      json_attributes_path: "$[2].NumberOfPoints]"
      value_template: '{{ value_json[2].NumberOfPoints }}'

    - name: "evcharger3 updated"
      json_attributes_path: "$[2].DateLastStatusUpdate]"
      value_template: '{{ value_json[2].DateLastStatusUpdate }}'

    - name: "evcharger3 connections"
      json_attributes_path: "$[2].Connections]"
      value_template: >
        {%- for i in range(value_json[2].NumberOfPoints-1) or [] %}
          {{ value_json[2].Connections[i].PowerKW }}
        {% endfor %}

    - name: "evcharger3 comments"
      json_attributes_path: "$[2].UserComments]"
      value_template: >
        {%- for x in value_json[2].UserComments or [] %}
          {{ value_json[2].UserComments[x].Comment }}
        {% endfor %}

Markdown card to display the basic info of evcharger_1 (I just replicated it for 2 and 3)

<a href="/ev-charging/0"><center><font color="steelblue"><ha-icon icon="mdi:ev-station"></ha-icon></font> {{ states.sensor.evcharger1_title.state }} {% if is_state('sensor.evcharger1_status', 'True') %} <font color="green"> {% else %} <font color="red"> {% endif %}<ha-icon icon="mdi:ev-plug-ccs2"></ha-icon></font><br></a></center>
<font color="steelblue"><ha-icon icon="mdi:map-marker-radius"></ha-icon></font>
{{ states.sensor.evcharger3_address.state | regex_replace(find='None,', replace='', ignorecase=False) }}<br>

<font color="steelblue"><ha-icon icon="mdi:cash-multiple"></ha-icon></font> Cost: {{ states.sensor.evcharger1_cost.state }}
<font color="steelblue"><ha-icon icon="mdi:gauge"></ha-icon></font> Distance: {{ states.sensor.evcharger1_distance.state | round(1) }} mile
<center><font color="steelblue"><ha-icon icon="mdi:map"></ha-icon></font> <a href="http://maps.google.com/?q={{ states.sensor.evcharger1_latitude.state }},{{ states.sensor.evcharger1_longitude.state }}">Navigate</a></center>

A markdown with a more detailed view of evcharger1 again I just replicated it for 2 and 3

<a href="/ev-charging/0"><center><font color="steelblue"><ha-icon icon="mdi:ev-station"></ha-icon></font> {{ states.sensor.evcharger1_title.state }} {% if is_state('sensor.evcharger1_status', 'True') %} <font color="green"> {% else %} <font color="red"> {% endif %}<ha-icon icon="mdi:ev-plug-ccs2"></ha-icon></font><br></a><font color="steelblue"><ha-icon icon="mdi:phone"></ha-icon></font><a href="tel:{{ states.sensor.evcharger1_phone.state }}">{{ states.sensor.evcharger1_phone.state }}</a></center>

Last Updated: 
{{ as_timestamp(states.sensor.evcharger1_updated.state) | timestamp_custom('%A %d %b %Y, %H:%M %p') }}
<br>
<font color="steelblue"><ha-icon icon="mdi:map-marker-radius"></ha-icon></font>
{{ states.sensor.evcharger3_address.state | regex_replace(find='None,', replace='', ignorecase=False) }}<br>{{ states.sensor.evcharger1_access.state }}

<font color="steelblue"><ha-icon icon="mdi:image-broken"></ha-icon></font>Operational: {{ states.sensor.evcharger1_operational.state }}
<font color="steelblue"><ha-icon icon="mdi:ev-plug-type2"></ha-icon></font>Number of Sockets: {{ states.sensor.evcharger1_points.state }}
<font color="steelblue"><ha-icon icon="mdi:power-plug"></ha-icon></font>Power: {{ states.sensor.evcharger1_connections.state }} kw
<font color="steelblue"><ha-icon icon="mdi:cash-multiple"></ha-icon></font> Cost: {{ states.sensor.evcharger1_cost.state }}
<font color="steelblue"><ha-icon icon="mdi:gauge"></ha-icon></font> Distance: {{ states.sensor.evcharger1_distance.state | round(1) }} miles
<font color="steelblue"><ha-icon icon="mdi:chat"></ha-icon></font> Comments:
{{ states.sensor.evcharger1_comments.state }}
<center><font color="steelblue"><ha-icon icon="mdi:map"></ha-icon></font> <a href="http://maps.google.com/?q={{ states.sensor.evcharger1_latitude.state }},{{ states.sensor.evcharger1_longitude.state }}">Navigate</a></center>

Hope someone finds it helpful - and maybe someone wants to develop it properly?

Finished (ish) result looks like this:
Quick view cards

Detailed Card
2

2 Likes

Very cool, pity the coverage of openchargemap is so poor in NZ.

Yeah I was hoping to use zap-map or plugshare but both of their APIs are closed down.

Have somebody moved forward with this project into hacs? That would be great.

1 Like

Is there scope to include whether or not the charger is available?

Hi, I’m the developer of Open Charge Map. Our data comes from community editors submitting data or from Open Data data imports. We are the single largest Open Data set for charging location in the world. You can encourage networks to share data with us (and we will promote their network for free) using this form: https://openchargemap.org/site/about/datasharing

If your local networks will not share data with us we unfortunately can’t just take it anyway and publish it, instead you can manually supply data using https://map.openchargemap.io and clicking the blue marker to add a POI at that location (or use Add from the menu). If you don’t add it, you can assume it might never get added by someone else either.

Unlike many other popular charging apps our data is openly shared with other apps and services, such as A Better Route Planner (ABRP), or this home assistant project :slight_smile:

@HugosDad we unfortunately don’t commonly have access to live status information from networks as most of our data is supplied by the community. PlugShare is also a great resource for community reviews (although it’s not Open Data, so data fed into that can typically only be accessed through their app/website).