Nissan Leaf in Home Assistant

Robert AndresenHome Assistant, Internet of things, Tutorials 2 Comments

I found this: https://github.com/glynhudson/leaf-python-mqtt, and thought it was a simple task… But nooooo. I have very little experience with MQTT, other than the basics, so this took some time 🙂

This article has been re-written 2018.01.22. I have added more details (mostly copy-paste) from glynhudson/leaf-python-mqtt on Github. I will advise you to follow the readme on Github instead, to get the newest update.

My setup

Lenovo with Ubuntu 16.04 and Home Assistant, but this was also testet on my last setup with Rasbian on RaspberryPi.

I installed leaf-python-mqtt in my home-folder:
/home/<user>/leaf-python-mqtt

 

Install Requirements

Requires python 2.7.9 & python pip

Install carwings python lib

# pip install git+https://github.com/jdhorne/pycarwings2.git

See pycarwings2 repo for more info

Install other python libs

# pip install schedule datetime paho-mqtt time

pip may require sudo.

I had to install one at the time, like «pip install schedule» and so on. The «time» component is default (included in python), so that one gave me an error message when trying to install it.

Install Leaf-python-mqtt

Clone this repo:

# git clone https://github.com/glynhudson/leaf-python-mqtt

Create config file using default file as a template, edit config to suit requirements. You will need to enter your CarWings / NissanConnect EV username (not e-mail) and password.

See below for more MQTT broker details.

# cd leaf-python-mqtt
# cp default.config.ini config.ini
# vi config.ini

The default config is setup for Nissan Leaf cars in Europe with region code NE, change the region code to one of the following if you are in a different region:

NNA : USA
NE : Europe
NCI : Canada
NMA : Australia
NML : Japan

Test script by running

# ./leaf-python-mqtt.py

Here is an example of the feedback:

root@homeassistant:/home/user/leaf-python-mqtt# ./leaf-python-mqtt.py
INFO:root:Startup leaf-python-MQTT: 2018-01-22 02:16:00
INFO:root:Loaded config file /home/user/leaf-python-mqtt/config.ini
INFO:root:updating data from API every 15min
INFO:root:Prepare Session
INFO:root:Login...
INFO:root:Start update time: 2018-01-22 02:16:00
INFO:root:Connected to MQTT host cloudmqtt.com with result code 0
INFO:root:Suscribing to leaf control topic: leaf/control
INFO:root:Publishing to leaf status topic: leaf/status
INFO:root:get_latest_battery_status
INFO:root:date jan. 22,2018 01:32
INFO:root:date 2018/01/22 00:32
INFO:root:battery_capacity2 12
INFO:root:battery_capacity 12
INFO:root:charging_status NOT_CHARGING
INFO:root:battery_capacity 12
INFO:root:battery_remaining_amount 12
INFO:root:charging_status NOT_CHARGING
INFO:root:is_charging False
INFO:root:is_quick_charging False
INFO:root:plugin_state CONNECTED
INFO:root:is_connected True
INFO:root:is_connected_to_quick_charger False
INFO:root:time_to_full_trickle None
INFO:root:time_to_full_l2 None
INFO:root:time_to_full_l2_6kw None
INFO:root:leaf_info.battery_percent 100.0
INFO:root:End update time: 2018-01-22 02:16:11
INFO:root:publishing to MQTT base status topic: leaf/status
INFO:root:End update time: 2018-01-22 02:16:15
INFO:root:Schedule API update every 15min
INFO:root:Schedule API update every 15min

Here is the data output from the MQTT stream:

The json from leaf/status/raw is prettified to make it easier to see.

leaf/status Connecting to MQTT host cloudmqtt.com
leaf/status MQTT connected
leaf/status/last_updated 2018/01/22 00:32
leaf/status/battery_percent 100.0
leaf/status/charging_status NOT_CHARGING
leaf/status/raw
{
  "status": 200,
  "BatteryStatusRecords": {
    "BatteryStatus": {
      "BatteryRemainingAmountWH": "",
      "BatteryChargingStatus": "NOT_CHARGING",
      "BatteryRemainingAmount": "12",
      "BatteryCapacity": "12",
      "BatteryRemainingAmountkWH": ""
    },
    "OperationResult": "START",
    "NotificationDateAndTime": "2018\/01\/22 00:32",
    "CruisingRangeAcOff": "111104.0",
    "OperationDateAndTime": "jan. 22,2018 01:32",
    "CruisingRangeAcOn": "98560.0",
    "PluginState": "CONNECTED",
    "TargetDate": "2018\/01\/22 00:32"
  }
}
leaf/status/connected Yes

 

Run script as system service

Create Systemd service

Create systemd service, assuming repo was cloned to /home/pi folder on a RaspberryPi, adjust paths if needed

# sudo ln -s /home/pi/leaf-python-mqtt/leaf-python-mqtt.service /etc/systemd/system/leaf-python-mqtt.service

Set permissions:

sudo chmod 644 /etc/systemd/system/leaf-python-mqtt.service

Reload systemd then enable the service at startup:

# sudo systemctl daemon-reload
# sudo systemctl enable leaf-python-mqtt.service
# sudo systemctl start leaf-python-mqtt.service

Check service status and view log snippet with:

# sudo systemctl status leaf-python-mqtt.service

 

MQTT broker

There is an included MQTT broker in Home Assistant, but I struggled a lot to get this working. You can read the docs here if you want to try: https://home-assistant.io/docs/mqtt/broker/.

One of the problems with the MQTT-broker in HA was understanding what was going on. I tried installing multiple MQTT-clients to monitor the topics. All of them connected just fine, but there was no stream of data. It did worked somehow, as I got the Carwings-data through MQTT to HA. I also tried to push an update for the car, but nothing happened.

I ended up registering an account on CloudMQTT. From there I created a homeassistant user and added the broker URL, username, password and port in /home/<user>/leaf-python-mqtt/config.ini.

MQTT client

Sometimes it can be nice to see if the messages is actually being sent over the MQTT stream. For that you need a client. There is a lot of client, but somehow I have problem with most of them.

Here are some clients you can try: https://www.hivemq.com/blog/seven-best-mqtt-client-tools

HiveMQ is a online service, but this one gives me a socket error. MQTT.fx starts on my computer, but the window doesn’t show. mqtt-spy does not start. MQTT Lens show so big icons and have a GUI bug.

I ended up installing a client on my ubuntu:

# apt install mosquitto-clients
# mosquitto_sub -v -h cloudmqtt.com -u USERNAME-P PASSWORD -p 1883 -t '#'
leaf/control/update 1
leaf/status MQTT connected

 

Troubleshoot

Error: «KeyError: BatteryStatusRecords»

# /usr/bin/python ./get-leaf-info.py Prepare Session 
Login... get_latest_battery_status 
Traceback (most recent call last): 
File "./get-leaf-info.py", line 28, in <module> 
leaf_info = l.get_latest_battery_status() 
File "/usr/local/lib/python2.7/dist-packages/pycarwings2/pycarwings2.py", line 372, 
in get_latest_battery_status return CarwingsLatestBatteryStatusResponse(response) 
File "/usr/local/lib/python2.7/dist-packages/pycarwings2/responses.py", 
line 508, in __init__ CarwingsResponse.__init__(self, status["BatteryStatusRecords"]) 
KeyError: 'BatteryStatusRecords'

Solution: Start the Carwings app on your phone. Log out and in again, and update the car status. After I did this, I got this result in my console:

# ./leaf-python-mqtt.py
INFO:root:Startup leaf-python-MQTT: 2017-08-18 02:54:52
INFO:root:Loaded config file /home/pi/leaf-python-mqtt/config.ini
INFO:root:updating data from API every 15min
INFO:root:Prepare Session
INFO:root:Login...
INFO:root:Start update time: 2017-08-18 02:54:52
INFO:urllib3.connectionpool:Starting new HTTPS connection (1): gdcportalgw.its-mo.com
INFO:urllib3.connectionpool:Starting new HTTPS connection (1): gdcportalgw.its-mo.com
INFO:root:Connected to MQTT host localhost with result code 0
INFO:root:Suscribing to leaf control topic: leaf/control
INFO:root:Publishing to leaf status topic: leaf/status
INFO:root:get_latest_battery_status
INFO:urllib3.connectionpool:Starting new HTTPS connection (1): gdcportalgw.its-mo.com
INFO:root:date aug. 18,2017 01:50
INFO:root:date 2017/08/17 23:50
INFO:root:battery_capacity2 12
INFO:root:battery_capacity 12
INFO:root:charging_status NOT_CHARGING
INFO:root:battery_capacity 12
INFO:root:battery_remaining_amount 11
INFO:root:charging_status NOT_CHARGING
INFO:root:is_charging False
INFO:root:is_quick_charging False
INFO:root:plugin_state NOT_CONNECTED
INFO:root:is_connected False
INFO:root:is_connected_to_quick_charger False
INFO:root:time_to_full_trickle 4:00:00
INFO:root:time_to_full_l2 2:30:00
INFO:root:time_to_full_l2_6kw None
INFO:root:leaf_info.battery_percent 91.6666666667
INFO:root:End update time: 2017-08-18 02:55:03
INFO:root:publishing to MQTT base status topic: leaf/status
INFO:root:End update time: 2017-08-18 02:55:06
INFO:root:Schedule API update every 15min

 

Error: Connection refused

INFO:root:updating data from API every 15min
Traceback (most recent call last):
File "./leaf-python-mqtt.py", line 88, in <module>
client.connect(mqtt_host, mqtt_port, 60)
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 760, in connect
return self.reconnect()
File "/usr/local/lib/python2.7/dist-packages/paho/mqtt/client.py", line 887, in reconnect
sock = socket.create_connection((self._host, self._port), source_address=(self._bind_address, 0))
File "/usr/lib/python2.7/socket.py", line 571, in create_connection
raise err
socket.error: [Errno 111] Connection refused

Solution: Your HA or MQTT component/broker is probably not running correct.

 

Add sensors to HA

Docs: https://home-assistant.io/components/sensor.mqtt/

I have created a separate sensor.yaml file, where I added this:

  - platform: mqtt
    state_topic: "leaf/status/battery_percent"
    name: "Leaf Battery"
    value_template: "{{ value_json | round(2) }}"
    
  - platform: mqtt
    state_topic: "leaf/status/last_updated"
    name: "Leaf Status"
    
  - platform: mqtt
    state_topic: "leaf/status/charging_status"
    name: "Leaf Battery Charg Status"

(Remember to add/check correct indends if you copy/paste)

 

(Update: I dropped the sensor.leaf_battery_remaining and added round(2) for the battery_percent)

Automation

After getting MQTT to work as expected, I could do some automation. The script below will fetch new status from the car at 21:00, then check if the car is NOT_CHARGING and the battery is below 50% at 21:30. If this criteria is met, it will send a push-message to remind me.

# LEAF: Update Carwings data
- alias: 'Carwings update'
  trigger:
  - platform: time
    at: "21:00:00"
  action:
  - service: mqtt.publish
    data:
        topic: "leaf/control/update"
        payload: "1" 

# LEAF: Charge-reminder
- alias: 'Carwings update'
  trigger:
  - platform: time
    at: "21:30:00"
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: sensor.leaf_battery_charg_status
        state: 'NOT_CHARGING'
      - condition: numeric_state
        entity_id: 'sensor.leaf_battery'
        below: '50'
  action:
  - service: notify.ios_robertiphone7
    data:
        message: "The battery is below 50% Charge?"
        title: "Nissan Leaf"
  - service: notify.ios_veronicaiphone6s
    data:
        message: "The battery is below 50% Charge?"
        title: "Nissan Leaf"