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"