Introduction: Vehicle Presence Detection - Home Automation
This instructable will provide information on how to setup "Vehicle Presence Detection" for your home automation system. This will work with any home automation system that supports MQTT, such as OpenHAB, Home Assistant etc. Personally I use OpenHAB, therefore that will be the system I provide examples for in this article. You will need to adjust the home automation rules to suit your own home automation software.
What does this give me?
Quite simply, this will tell your home automation system whether your vehicle is home or away. Knowing whether your car is home or away is rather mundane in itself, it's the automated rules that you can perform when you drive to or from home is what makes this project more convenient (eg: if arriving home, automatically open the garage door, automatically turn on front entrance lights if arriving home at night etc. Or if leaving home, automatically close the garage door, turn off all house lights, lock the front door, turn on alarm system etc) This project utilises a Wemos D1 Mini Pro with Antenna. They can be purchased for around US$5 from many online stores, such as eBay, Aliexpress or Banggood. (or in fact, any ESP8266 chip that supports an external antenna is recommended)
This assumes that where you usually park your vehicle, is close enough to your Wireless Access Point to get a relatively good signal. Due to the body of a vehicle being largely made of metal, this will attenuate the signal and cause a poorer than normal signal. You should be getting 2 bars or stronger signal strength from where you park your vehicle usually. This is primarily why this project utilises a Wemos Pro with external antenna in order to achieve a better signal.
How does it work?
The Wemos D1 Mini Pro (an ESP8266 Wifi device) will reside in your car and while powered on, will attempt to connect to your Wifi. As you drive away from your house, Wifi signal will be lost and your Home Automation system will be updated to indicate that your car is AWAY. When you drive back home again, the Wemos will associate with your Wireless Access Point and inform your Home Automation system that the car is HOME. Be aware however, that simply determining a wifi state of "connected" or "disconnected" is not sufficient enough to determine where the car is!
First of all, we only want the Wemos running when the car is on - otherwise (and even though the Wemos is relatively low power consumption) it could eventually drain the cars battery. Therefore, the Wemos in this project will only power on when your car ignition is on / the car is started. Now consider if you arrive home and then turn your car off when parked in your garage - the Wemos will also get turned off, Wifi signal is lost - however your car is still at home - not actually away.
In this project, when the Wemos is powered up it constantly polls, detects and evaluates RSSI (wireless signal strength) values. RSSI is measured in dB, which is a logarithmic scale of sound levels and, in terms of wireless signal, is expressed in negative values. For most people, Wifi strength will be seen as "bars" on their cellphones. Roughly speaking, RSSI to bar conversion is as follows:
- 5 bars = -54dB or greater
- 4 bars = -55dB to -64dB
- 3 bars = -65dB to -70dB
- 2 bars = -71dB to -78dB
- 1 bar = -79dB to -82dB
- 0 bars = -83dB or worse
The Arduino code is configured to take (by default, as settings are configurable) 4 samples of RSSI strength every 500msec, then takes an average from those 4 x samples. On first power up, the Wemos establishes a signal strength baseline from those 4 samples then subtracts a threshold value (by default, 8, which effectively sets the wireless client to a weaker RSSI than it really is). After that, it continues taking 4 samples every 500msec, and every 2 seconds will compare the new RSSI average from the initial baseline it took on startup. If the signal strength gets weaker from the baseline then it assumes the vehicle is moving away from the wireless access point, conversely if the signal strength gets stronger then it assumes the vehicle is moving closer to the wireless access point. That state alone does not determine home or away however.
Within OpenHAB, RULES are used to take a combination of both "homeoraway" state (0 for AWAY, 1 for HOME) that is received from the Wemos as well as MQTT LWT (last will and testament) status to determine the most likely vehicle status from both these states.
MQTT LWT (last will and testament) is a method where the MQTT broker checks to see whether it has received regular polling messages from the MQTT client. For example, in this project a "keep alive" (value of "1") status is sent from the Wemos to the MQTT Broker every 10 seconds. If no status is received by the MQTT Broker within a certain period of time, then LWT kicks in and assumes the device is dead; the broker automatically sets that status to "dead" (value of "0")
The OpenHAB rules determine the most likely vehicle status from both RSSI state and LWT status to make an informed decision, as follows:
- LWT = alive & RSSI = getting stronger, ...then (arriving) = HOME
- LWT = alive & RSSI = getting weaker, ...then (most likely leaving, but still) = HOME
- LWT = dead & (last) RSSI = getting stronger, ...then = HOME
- LWT = dead & (last) RSSI = getting weaker, ...then = AWAY
So as per above, only a weaker signal and LWT dead will effectively generate an Away. All other messages the vehicle is considered Home.
The only parts you need are a Wemos D1 Mini Pro.
Step 1: Arduino Code
All necessary Arduino code and OpenHAB Files are downloadable from here:
Run up your Arduino IDE. Ensure the correct board and COM port are selected, ensure that the libraries "ESP8266" and "PubSubClient" are included (from menu's, Sketch, Include Library, Manage Libraries) Download and open the .INO code from the above link in Arduino IDE, also download and configure the OpenHAB items, sitemap and rules file and save into your own home automation setup (adjust where necessary). Update the top of the code to include your own wireless SSID, password and MQTT Broker IP address. Alternately alter the MQTT Prefix and Vehicle ID (must be unique per vehicle) to suit your own setup.
Connect the USB cable to the Wemos and upload the Sketch. You can test the functionality by opening the Serial Monitor whilst USB is connected between the Wemos and your computer. Cover the Wemos signal with your hand to reduce signal strength, and monitor the output, hold it up closer to your access point and the output should change. Test this in conjunction with MQTT as per Testing below (when you eventually plug this into your car, ensure the Wemos is connected to a USB port in your car that is only powered on when the ignition is on, and is powered off when the ignition is off. If your car has no USB port, consider wiring in a 12V to 5V USB DC-DC converter)
MQTT is a "subscribe / publish" messaging system. One or more devices can talk to an "MQTT broker" and "subscribe" to a certain topic. Any incoming messages from any other device that are "published" to that same topic, will be pushed out by the broker to any other device that has subscribed to that topic. It is an extremely lightweight and simple to use protocol and perfect as a simple triggering system such as the one here.
For testing, you can view incoming MQTT messages from the Wemos to your MQTT broker by running the following command on your Mosquitto server (Mosquitto is one of many MQTT Broker software available). This command subscribes to incoming messages regarding the vehicles state (the # is a wildcard):
mosquitto_sub -v -t openhab/vehicle/#
You should see inbound messages coming in from the Wemos every 10 seconds or so with the number "1" (meaning "I'm alive") If you see constant "0's" (or no response) then there is no communication. Once you see the number 1 coming in, then it means the Wemos is communicating with the MQTT broker. You should see messages similar to the following, remembering a "homeoraway" state of 0 means AWAY and 1 means HOME. You should also see "status" messages of 0 meaning dead or 1 meaning alive.
openhab/vehicle/ford/homeoraway 1 openhab/vehicle/ford/homeoraway 1 openhab/vehicle/ford/status 1 openhab/vehicle/ford/homeoraway 1 openhab/vehicle/ford/homeoraway 1 openhab/vehicle/ford/homeoraway 1 openhab/vehicle/ford/status 1 openhab/vehicle/ford/homeoraway 0 openhab/vehicle/ford/homeoraway 0 openhab/vehicle/ford/status 0
Also remember that it is the rules that ultimately determines the true state. If you have left the logging entries in the rules file, from the command line in OpenHAB run the following to see log entries, you should see corresponding entries such as the following:
pi@openhab2:~ $ tail -10f /var/log/openhab2/openhab.log
2019-08-20 09:25:06.537 [INFO ] [lipse.smarthome.model.script.vehicle] - Ford Ranger is HOME (STATE)<br>2019-08-20 09:25:06.554 [INFO ] [lipse.smarthome.model.script.vehicle] - Vehicle true state Home 2019-08-20 09:25:06.986 [INFO ] [lipse.smarthome.model.script.vehicle] - Ford Ranger is HOME (LWT) 2019-08-20 09:25:18.249 [INFO ] [lipse.smarthome.model.script.vehicle] - Ford Ranger is HOME (LWT) 2019-08-20 09:25:29.071 [INFO ] [lipse.smarthome.model.script.vehicle] - Ford Ranger is HOME (LWT) 2019-08-20 09:25:39.879 [INFO ] [lipse.smarthome.model.script.vehicle] - Ford Ranger is HOME (LWT) 2019-08-20 09:25:50.707 [INFO ] [lipse.smarthome.model.script.vehicle] - Ford Ranger is HOME (LWT) 2019-08-20 09:25:54.151 [INFO ] [lipse.smarthome.model.script.vehicle] - STATE - AWAY received, but LWT says we're home 2019-08-20 09:26:19.259 [INFO ] [lipse.smarthome.model.script.vehicle] - Ford Ranger is AWAY (LWT) 2019-08-20 09:26:19.278 [INFO ] [lipse.smarthome.model.script.vehicle] - Vehicle true state Away
You may want to tweak the following settings in the top of the code to take more samples, or take them more or less often, or send keep alive messages more or less often, depending on your setup:
// Milliseconds to wait between signal strength tests
unsigned long cl_SampleDelayMillis = 500; // Number of samples to take every 'SampleDelayMillis' (before making a decision) const int ci_SamplesToTake = 5; // Buffer added to baseline to qualify for making better "leaving" or "arriving" decisions const int ci_RSSIBuffer = 5; // Send alive every (LWT) const int ci_SendAliveEvery = 10;
Step 2: Installation
If you have a 3D printer (or know someone with one), consider printing out a small case for your Wemos with Antenna. Wemos D1 Mini Pro case:
This will keep things nice and tidy.
5V USB Power
If your vehicle does not come with a USB adapter, or the USB adapter you have in your car stays powered on all the time, you can purchase 12V to 5V USB adapters fairly cheap off Aliexpress, eBay or similar. You will need a multi-meter to determine a suitable 12V feed from your ignition and ground to wire this in.
The preferred mounting location would be under your dash. Several reasons for this, accessibility in case you need to unplug it, weather proof and finally the fact it's surrounded by slightly less "metal" than it would be if it were mounted around your engine bay. We need to get the best signal strength possible to ensure accurate samples and status sent back to your home automation system.
3 years ago on Step 2
Much better method. Send an up-time message. If Home-Assistant gets a message with an up-time of less than a minute and then the device drops the connection, then Elvis has left the building. If the first message received has an up-time of >10 minutes (adjust as needed), the prodigal son has returned.
Reply 2 years ago
Original idea of signal strength is smart. Are there any spurious causes of signal drops though?
Up time is a clever, simple measure.
+ Another idea: a short duration power supply would enable the device to detect vehicle being switched off and give it enough time to notify home base, then you'd have a way of knowing it was disconnect-due-to-power-off (arrival) and not disconnect-due-to-signal-loss (departure).
Reply 2 years ago
The uptime is working fine for me. The only issue has been if I start the car and then sit there for a while, such as when working on the car, or if I come home and turn the car off and then turn it back on for some reason. But I have it set with a minimum up-time of 10 mins before it decides I'm back home and that gives me plenty of time to start the car, turn on wipers, turn on heat, check mirrors or whatever else I may do and then pull on out in the morning. The one part that was a bit difficult was getting it to get connected quickly enough due to the range of the wireless so I turned off the wifi-scan and set a static IP so it'd connect faster. Then it just sends a MQTT message every second when/if it's connected. Node-red keeps an eye on those and if it sees one. it looks at the up-time. If it's < 10 mins, it turns stuff off and then ignores all MQTT messages for at least 10 mins (that way it's not sending out a msg to Alexa or Home Assistant every second.) If it sees an up-time >10 mins, it turns things on and then again ignores all messages for at least 10 mins.
So when the car starts, the presence-device boots, (eventually) connects to wifi and MQTT and starts sending an incrementing counter. But the payload time is always from boot, not from connect time. It'd have to be powered-on for 9+ hours straight before it'd roll over/glitch (I used either int16_t or uint16_t. I forgot how.)
Reply 2 years ago
Thanks for your comment. The static IP is a good idea, the instructable I posted is more a concept than anything else, although I do use it myself and also have the intermittent issue of not connecting quick enough so will try the static IP. I wanted to keep this as simple as possible so it’s easy for most people to adopt. I’m considering doing a newer version where the ESP is always powered but will go into sleep mode after 10 secs, and have a mosfet connected to the ignition wire (triggered when key is on) then to a GPIO pin to wake the ESP up. Then the logic is if the ignition is on and ESP is woken up the car is at home and about to leave. Alternately if the ignition is turned off the mosfet is triggered switching a GPIO pin indicating the car is home (with logic before and after obviously)
Reply 2 years ago
The following will help get the wifi lock the fastest:
const char* ssid = "********";
const char* password = "********";
WiFi.persistent( false );
WiFi.mode( WIFI_STA );
WiFi.begin( WLAN_SSID, WLAN_PASSWD );
You can also change the last line to the following to avoid the wifi scan and save even more time (but it's not as flexible as changing routers will mean it needs to be reprogrammed.)
WiFi.begin( WLAN_SSID, WLAN_PASSWD, channel, ap_mac, true );
Reply 2 years ago
Thanks, yeah sleep mode is something I’ve considered. I’ll do another instructable when I get around to coding and testing it as there is the odd spurious event where WiFi strength isn’t consistent.