Nissan Leaf Component(s)/Platform

Got this done now:

Only things missing are:

  • The “start charging” script combined with the charging status as an button-icon in the left bottom corner. (mdi:ev-station?)
  • The “update status” script as an button-icon in the bottom middle (mdi:update?)

I dunno how to do these…

Once fixed I’ll share my changes.

Nice work.

I have tried but I can’t even get the battery icon to change :slight_smile: I’m not much of a programmer, I get confused easily, making this took me most of a days work.

Please post your updated when happy with the results.

Don’t worry, I have the same problem :wink:

If anyone knows how to get these scripts integrated properly, I could finish and share this.

Took me a little while to figure it out yesterday evening, but I’m ready to share :slight_smile:

Based on Roadkill’s fine work!

configuration:

nissan_leaf:
  username: !secret nissan_leaf_username
  password: !secret nissan_leaf_password
  region: "NE"
  update_interval:
    minutes: 30
  update_interval_charging:
    minutes: 15
  update_interval_climate:
    minutes: 5
  force_miles: false

sensor: 
  - platform: template
    sensors:
      leaf_state:
        value_template: "Laden: {{ states('binary_sensor.leaf1mich_charging_status') }}"
      leaf_range_ac: 
        value_template: "A/C actieradius: {{ states('sensor.leaf1mich_range_ac') }}"
      leaf_range: 
        value_template: "Actieradius: {{ states('sensor.leaf1mich_range') }}"
      leaf_battery:
        unit_of_measurement: '%'
        value_template: "{{ states('sensor.leaf1mich_charge') }}"
        icon_template: "{%- if states.sensor.leaf1mich_charge.state >= '95' %}mdi:battery{%- elif states.sensor.leaf1mich_charge.state == '100' %}mdi:battery{%- elif states.sensor.leaf1mich_charge.state <= '15' %}mdi:battery-outline{% else %}mdi:battery-{{(states.sensor.leaf1mich_charge.state|float / 10)|round*10}}{%- endif %}"

Lovelace:

elements:
  - entity: binary_sensor.leaf1mich_charging_status
    icon: 'mdi:ev-station'
    style:
      left: 0
      bottom: 0
      pointer-events: none
      font-size: 16px
      line-height: 50px
      color: white
      background-color: 'rgba(0, 0, 0, 0.3)'
      width: 100%
      transform: initial
      padding: 0 8px
    tap_action:
      action: call-service
      service: nissan_leaf.start_charge
      confirmation: false
    type: state-icon
  - entity: sensor.leaf1mich_charge
    icon: 'mdi:reload'
    style:
      '--paper-item-icon-color': 'rgb(25,25,25)'
      bottom: 0
      color: white
      left: 45%
      line-height: 32px
      margin: 0px 0px -3px 0px
      padding: 8px
      transform: initial
    tap_action:
      action: call-service
      service: nissan_leaf.update
      confirmation: false
    type: state-icon
  - entity: switch.leaf1mich_climate_control
    icon: 'mdi:fan'
    style:
      '--paper-item-icon-color': 'rgb(25,25,25)'
      bottom: 0
      color: white
      line-height: 32px
      margin: 5px 0px -3px 0px
      padding: 8px
      right: 0
      transform: initial
    tap_action:
      action: toggle
      confirmation: true
    type: state-icon
  - entity: binary_sensor.leaf1mich_plug_status
    style:
      '--paper-item-icon-color': 'rgb(25,25,25)'
      left: 0
      margin: 25px 25px
      top: 0
    type: state-icon
  - entity: sensor.leaf_range_ac
    style:
      color: 'rgba(25,25,25,1)'
      font-size: 12px
      line-height: 32px
      margin: 1px 35px
      pointer-events: none
      right: 0
      text-shadow: 'rgba(0, 0, 0, 0.2) 0px 0px 2px'
      top: 0
      transform: initial
    type: state-label
  - icon: 'mdi:speedometer'
    style:
      color: 'rgba(25,25,25,1)'
      line-height: 32px
      margin: 8px 13px 0 0
      pointer-events: none
      right: 0
      top: 0
      transform: scale(0.8)
    type: icon
  - entity: sensor.leaf_range
    style:
      color: 'rgba(25,25,25,1)'
      font-size: 12px
      line-height: 32px
      margin: 30px 35px
      pointer-events: none
      right: 0
      text-shadow: 'rgba(0, 0, 0, 0.2) 0px 0px 2px'
      top: 0
      transform: initial
    type: state-label
  - icon: 'mdi:speedometer'
    style:
      color: 'rgba(25,25,25,1)'
      line-height: 32px
      margin: 36px 13px
      pointer-events: none
      right: 0
      top: 0
      transform: scale(0.8)
    type: icon
  - entity: sensor.leaf1mich_charge
    style:
      color: 'rgba(25,25,25,1)'
      font-size: 12px
      line-height: 32px
      margin: 58px 34px
      pointer-events: none
      right: 0
      text-shadow: 'rgba(0, 0, 0, 0.2) 0px 0px 2px'
      top: 0
      transform: initial
    type: state-label
  - entity: sensor.leaf_battery
    style:
      '--paper-item-icon-color': 'rgb(25,25,25)'
      margin: 60px 5px
      right: 0
      top: 0
      transform: initial
    type: state-icon
image: /local/images/car/leaf.jpg
type: picture-elements

Make sure to replace “leaf1mich” with your leafs name

If you improve this any further, please share!

Well, I’ve been busy too, the battery icon fix was the same as yours :slight_smile: however mine was sensor.leaf_charge but now I’ve changed it to match your better suggestion.

I’ve also sorted out the other items you wanted doing, so here it is :slight_smile:

leaf

  
  - platform: template
    sensors:
      leaf_state:
        value_template: "Charging: {{ states('binary_sensor.MYNISSANLEAF_charging_status') }}"
      leaf_range_ac: 
        value_template: "A/C Milage: {{ states('sensor.MYNISSANLEAF_range_ac') }}"
      leaf_range: 
        value_template: "Milage: {{ states('sensor.MYNISSANLEAF_range') }}"
      leaf_battery:
        value_template: "{{ states('sensor.MYNISSANLEAF_charge') }}"
        icon_template: "{%- if states.sensor.MYNISSANLEAF_charge.state >= '95' %}mdi:battery{%- elif states.sensor.MYNISSANLEAF_charge.state == '100' %}mdi:battery{%- elif states.sensor.MYNISSANLEAF_charge.state <= '15' %}mdi:battery-outline{% else %}mdi:battery-{{(states.sensor.MYNISSANLEAF_charge.state|float / 10)|round*10}}{%- endif %}"
        unit_of_measurement: '%'
  - type: picture-elements
    image: /local/pics/leaf.png
    elements:
      # Title and Program
      - type: state-label
        entity: sensor.leaf_state
        style:
          left: 0
          bottom: 0
          pointer-events: none
          font-size: 16px
          line-height: 32px
          color: white
          background-color: rgba(0, 0, 0, 0.3)
          width: 100%
          transform: initial
          padding: 0 8px
      # A/C Control
      - type: state-icon
        entity: switch.MYNISSANLEAF_climate_control
        tap_action:
          action: toggle
          confirmation:
            text: Are you sure you want to Start the car?
        style:
          bottom: 0
          right: 0
          transform: initial
          color: white
          line-height: 32px
          padding: 8px
          margin: 0 0px 0 0
          # Change color of state-icon off
          --paper-item-icon-color: rgb(25,25,25)
      # Plug Status
      - type: state-icon
        entity: binary_sensor.MYNISSANLEAF_plug_status
        style:
          top: 0
          left: 0
          transform: scale(0.8)
          color: rgba(255,25,25,1)
          line-height: 32px
          padding: 8px
          margin: 0px 0px
          # Change color of state-icon off
          --paper-item-icon-color: rgb(25,25,25)
      # Start Charge
      - type: state-icon
        entity: binary_sensor.MYNISSANLEAF_charging_status
        tap_action:
          action: call-service
          service: script.leaf_charge # <== YOUR CHARGE SCRIPT HERE
          confirmation:
            text: Are you sure you want to Start Charging?
        style:
          top: 0
          left: 0
          transform: scale(0.8)
          color: rgba(255,25,25,1)
          line-height: 32px
          padding: 8px
          margin: 30px 0px
          # Change color of state-icon off
          --paper-item-icon-color: rgb(25,25,25)
      # Check Status
      - type: icon
        icon: mdi:car-info
        tap_action:
          action: call-service
          service: script.car_info # <== YOUR CAR INFO SCRIPT HERE
        style:
          top: 0
          left: 0
          transform: scale(0.8)
          color: rgba(25,25,25,1)
          line-height: 32px
          padding: 8px
          margin: 60px 10px
      # Range
      - type: state-label
        entity: sensor.leaf_range_ac
        style:
          top: 0
          right: 0
          pointer-events: none
          transform: initial
          font-size: 12px
          color: rgba(25,25,25,1)
          text-shadow: rgba(0, 0, 0, 0.2) 0px 0px 2px
          line-height: 32px
          margin: 1px 35px 0 0
      - type: icon
        icon: mdi:speedometer
        style:
          top: 0
          right: 0
          pointer-events: none
          transform: scale(0.8)
          color: rgba(25,25,25,1)
          line-height: 32px
          margin: 6px 13px 0 0
      - type: state-label
        entity: sensor.leaf_range
        style:
          top: 0
          right: 0
          pointer-events: none
          transform: initial
          font-size: 12px
          color: rgba(25,25,25,1)
          text-shadow: rgba(0, 0, 0, 0.2) 0px 0px 2px
          line-height: 32px
          margin: 30px 35px
      - type: icon
        icon: mdi:speedometer
        style:
          top: 0
          right: 0
          pointer-events: none
          transform: scale(0.8)
          color: rgba(25,25,25,1)
          line-height: 32px
          margin: 35px 13px
      - type: state-label
        # Charge
        entity: sensor.MYNISSANLEAF_charge
        style:
          top: 0
          right: 0
          pointer-events: none
          transform: initial
          font-size: 12px
          color: rgba(25,25,25,1)
          text-shadow: rgba(0, 0, 0, 0.2) 0px 0px 2px
          line-height: 32px
          margin: 59px 35px
      - type: state-icon
        entity: sensor.leaf_battery
        style:
          top: 0
          right: 0
          pointer-events: none
          transform: scale(0.8)
          color: rgba(25,25,25,1)
          line-height: 32px
          margin: 60px 4px 0 0

Edited to correct the placement of the icons on the left hand side.

Had to go back to scripts. The service call would not accept the vin.

Some more color fixes:

Right hand botom icon shows Climate control status and starts the climate control ‘on click’
Botom middle icon requests new data from the car.
Left hand botom icon shows charging status and will start charging ‘on click’

Configuration:

nissan_leaf:
  username: !secret nissan_leaf_username
  password: !secret nissan_leaf_password
  region: "NE"
  update_interval:
    minutes: 30
  update_interval_charging:
    minutes: 15
  update_interval_climate:
    minutes: 5
  force_miles: false

sensor: 
  - platform: template
    sensors:
      leaf_state:
        value_template: "Laden: {{ states('binary_sensor.leaf1mich_charging_status') }}"
      leaf_range_ac: 
        value_template: "A/C actieradius: {{ states('sensor.leaf1mich_range_ac') }}"
      leaf_range: 
        value_template: "Actieradius: {{ states('sensor.leaf1mich_range') }}"
      leaf_battery:
        friendly_name: "Accu"
        unit_of_measurement: '%'
        value_template: "{{ states('sensor.leaf1mich_charge') }}"
        icon_template: "{%- if states.sensor.leaf1mich_charge.state >= '95' %}mdi:battery{%- elif states.sensor.leaf1mich_charge.state == '100' %}mdi:battery{%- elif states.sensor.leaf1mich_charge.state <= '15' %}mdi:battery-outline{% else %}mdi:battery-{{(states.sensor.leaf1mich_charge.state|float / 10)|round*10}}{%- endif %}"

script:
  leaf_charge:
    alias: Laden starten
    sequence:
      - service: nissan_leaf.start_charge
        data:
          vin: !secret nissan_leaf_vin
  leaf_update:
    alias: Update status
    sequence:          
      - service: nissan_leaf.update
        data:
          vin: !secret nissan_leaf_vin

Lovelace:

elements:
  - entity: binary_sensor.leaf1mich_charging_status
    icon: 'mdi:ev-station'
    style:
      background-color: 'rgba(0, 0, 0, 0.3)'
      bottom: 0
      font-size: 16px
      left: 0
      line-height: 50px
      padding: 0 8px
      transform: initial
      width: 100%
    tap_action:
      action: call-service
      confirmation: false
      service: script.leaf_charge
    type: state-icon
  - entity: sensor.leaf1mich_charge
    icon: 'mdi:reload'
    style:
      bottom: 0
      color: white
      left: 45%
      line-height: 32px
      margin: 0px 0px -3px 0px
      padding: 8px
      transform: initial
    tap_action:
      action: call-service
      confirmation: false
      service: script.leaf_update
    type: state-icon
  - entity: switch.leaf1mich_climate_control
    icon: 'mdi:fan'
    style:
      bottom: 0
      color: white
      line-height: 32px
      margin: 5px 0px -3px 0px
      padding: 8px
      right: 0
      transform: initial
    tap_action:
      action: toggle
      confirmation: false
    type: state-icon
  - entity: binary_sensor.leaf1mich_plug_status
    style:
      '--paper-item-icon-color': 'rgb(25,25,25,1)'
      left: 0
      margin: 25px 25px
      top: 0
    type: state-icon
  - entity: sensor.leaf_range_ac
    style:
      font-size: 12px
      color: 'rgb(25,25,25,1)'
      line-height: 32px
      margin: 1px 35px
      pointer-events: none
      right: 0
      text-shadow: 'rgb(0, 0, 0, 0.2) 0px 0px 2px'
      top: 0
      transform: initial
    type: state-label
  - entity: sensor.leaf_range
    icon: 'mdi:speedometer'
    style:
      '--paper-item-icon-color': 'rgb(25,25,25,1)'
      line-height: 32px
      margin: 5px 5px
      right: 0
      top: 0
      transform: initial
    type: state-icon
  - entity: sensor.leaf_range
    style:
      font-size: 12px
      color: 'rgba(25,25,25,1)'
      line-height: 32px
      margin: 30px 35px
      pointer-events: none
      right: 0
      text-shadow: 'rgb(0, 0, 0, 0.2) 0px 0px 2px'
      top: 0
      transform: initial
    type: state-label
  - entity: sensor.leaf_range
    icon: 'mdi:speedometer'
    style:
      '--paper-item-icon-color': 'rgb(25,25,25)'
      line-height: 32px
      margin: 33px 5px
      right: 0
      top: 0
      transform: initial
    type: state-icon
  - entity: sensor.leaf1mich_charge
    style:
      color: 'rgba(25,25,25,1)'
      font-size: 12px
      line-height: 32px
      margin: 58px 34px
      pointer-events: none
      right: 0
      text-shadow: 'rgb(0, 0, 0, 0.2) 0px 0px 2px'
      top: 0
      transform: initial
    type: state-label
  - entity: sensor.leaf_battery
    style:
      '--paper-item-icon-color': 'rgb(25,25,25,1)'
      margin: 60px 5px
      right: 0
      top: 0
      transform: initial
    type: state-icon
image: /local/images/car/leaf.jpg
type: picture-elements

The image:

3 Likes

They did put it back in the new cars, so my new Leaf do have the location service again. But there is no support in the HA component for the new API yet.

I think that its due to that the trafic goes via Sms and it was a expensive solution, especially when we all requested the location every 15 min or so.

Wait wut, traffic goes via SMS from the car to the Nissan servers? Any source?

Well, how else would it get there? :wink:

It’s either that or 2G.

I don’t have any official sources on this.
But a swedish guy did som tests and the only way to get the Nissan Leaf to report Charging state in somewhat reasonble time line, was to ask every 5 minutes. Then it didn’t go down in sleep.

I have an automation that will poll 30 seconds after polling, using an additional input_boolean. Been running for weeks now without issue.

- action:
  - entity_id: input_boolean.leaf_repeat
    service: input_boolean.turn_on
  - delay: 00:00:30
  - service: nissan_leaf.update
    data:
      vin: 'XXXXXXX123456789'             # replace
  - delay: 00:10:00
  - entity_id: input_boolean.leaf_repeat
    service: input_boolean.turn_off
  alias: Leaf Double Take
  condition:
    - condition: state
      entity_id: input_boolean.leaf_repeat
      state: 'off'
  id: '4896215945484'
  trigger:
  - entity_id: sensor.leaf_updating
    platform: state
    to: 'False'

and the input_boolean

input_boolean:
  leaf_repeat:
    name: Leaf Repeat
    initial: off
    icon: mdi:leaf

EDIT: Here is the sensor missed from the original post.

  - platform: template
    sensors:
      leaf_updating:
        friendly_name: 'Leaf Update Status'
        value_template: "{{ state_attr('sensor.CHANGEME_charge', 'update_in_progress') }}"

I would love to try this, but I am too new to understand this 100%.

How does “sensor.leaf_updating” figure into this? Is that based on a sensor-template, or is that what you set when you manually or by automation check for update?

Thanks in advance!

You’re right, I missed that, it is indeed another sensor, here it is, just change the necessary parts.

  - platform: template
    sensors:
      leaf_updating:
        friendly_name: 'Leaf Update Status'
        value_template: "{{ state_attr('sensor.CHANGEME_charge', 'update_in_progress') }}"
  

Hello all.
I’m owing a 2019 Nissan Leaf and as a noob, I tried to follow all thoses config files but without succes. Are those files ok for my 2019 car ?
I allready put the files in “custom-components/nissan-leaf”, copy the script, include the sensor and nissan_leaf in config yaml but… no success.
Someone could write a step by step how to in order to point my mistake ?

No one to help me ? Really ?

Just doesnt work for any newer than may -19.

Someone has started developing a >May-19 Leaf component, but the development unfortunately stalled.

https://github.com/mitchellrj/kamereon-python

I do have this running as a custom component which ‘works’ however it has an OAUTH timeout issue which I cannot quite figure out as not able to tell if it’s using the built-in HASS OAUTH schema and how to have it automatically renew. My Python skills are far too basic to adapt this, but all the hard work of the extracting data from the API to HASS is done.

2 Likes

This is great, I’ve missed this component since I changed to a newer Leaf, let’s encourage the developer to continue!

@mitsumaui

How did you actually set this up in HA? The installation of the custom component I’m onboard with, but what config are you using to provide user-name and password?