I see this topic come up from time to time and I’ve read quite a few of the posts about how to make use of HA while in your RV so I wanted to share what I have come up with over the past year that is working well for me.
I have a few Z-Wave, a couple Zigbee, a few Bluetooth and some WiFi in my RV, along with the normal weather updates and so forth that I wanted to configure. I’m working on some ESPHome devices to replace all my current 12v light switches (WIP) so I needed to have everything in place because I’m addicted to home automation.
The first thing I did is rename my system so that I could reach homeassistant.local for my house but when my RV is plugged in and in front of my house pre-trip I wanted to be able to connect to that, so I went with renaming it to rvassistant.local via Settings → System → Network:
Now I can easily swap between the two without the IP address or any potential conflicts. I also subscribe to Nabu Casa so I can still always reach my home HA easily. I thought about wanting that on my RV but the fact is, currently, I’m not powering up HA when the RV is in storage so it’s not an issue right now, except I would like to take advantage of using TTS over Alexa through Nabu Casa, but it’s not critical because I also have homepods and link to HomeKit so Siri takes care of me on voice commands and I have Airfoil on my Mac laptop for any TTS needs for now.
Internet Connectivity
One of my really fun systems to create was Internet access. I have three systems for Internet, the park wifi (which always sucks) and I use a Ubiquity antenna for that but it is so strong that it overpowers using it to relay cell phones as hotspots so I also have a TP Link with a much “quieter” antenna power that easily relays in-rig cell phones and then my cellular Netgear Nighthawk M1. I’ll bounce around all three of those as either data plans get used up or speeds suck, so I created a system of sensors to know which Internet is currently active:
The system I use for this is that the Ubiquity and Hotspot are always the same IP address, but the TP link changes according to what wifi you are connected to, fortunately they have a generic domain name you can query that will resolve that (tplinkrepeater.net). The idea is that only one will be active, so if one pings then that’s our Internet. For this system I just created an input_select helper with Not Connected and then the three different Internet options and I wrote automation that says if none ping then it’s Not Connected, otherwise whichever pings changes the select so I’m never confused as to which gateway we are using. I do it like this:
alias: "Trigger: Internet Connectivity Changes Set Gateway"
description: >-
When the Internet connects check which gateway is active and set the helper to
that value
trigger:
- platform: state
entity_id:
- binary_sensor.internet
- platform: time_pattern
minutes: /15
condition: []
action:
- choose:
- conditions:
- condition: and
conditions:
- condition: not
conditions:
- condition: state
entity_id: binary_sensor.ubnt_bullet
state: "on"
- condition: not
conditions:
- condition: state
entity_id: binary_sensor.netgear_nighthawk
state: "on"
- condition: not
conditions:
- condition: state
entity_id: binary_sensor.tp_link
state: "on"
sequence:
- service: input_select.select_option
data:
option: Not Connected
target:
entity_id: input_select.internet_connectivity
- conditions:
- condition: state
entity_id: binary_sensor.ubnt_bullet
state: "on"
sequence:
- service: input_select.select_option
data:
option: Ubiquity WiFi Repeater
target:
entity_id: input_select.internet_connectivity
- conditions:
- condition: state
entity_id: binary_sensor.netgear_nighthawk
state: "on"
sequence:
- service: input_select.select_option
data:
option: Netgear Nighthawk Cellular Hotspot
target:
entity_id: input_select.internet_connectivity
- conditions:
- condition: state
entity_id: binary_sensor.tp_link
state: "on"
sequence:
- service: input_select.select_option
data:
option: TP-Link WiFi Repeater
target:
entity_id: input_select.internet_connectivity
mode: single
And whenever that helper changes, I have another trigger to reload Speedtest:
alias: "Trigger: Internet Connectivity Changes and We Are Online"
description: ""
trigger:
- platform: state
entity_id:
- input_select.internet_connectivity
- platform: state
entity_id:
- binary_sensor.internet
to: "on"
condition:
- condition: state
entity_id: binary_sensor.internet
state: "on"
action:
- service: homeassistant.reload_config_entry
data: {}
target:
entity_id:
- sensor.speedtest_download
mode: single
One of the reasons I set it up this way was so that all wifi in my RV was ever just one network, it’s just a run-of-the-mill Netgear wifi router with a WAN port, whatever is in that wan port is the Internet so I can swap out internet connections freely without changing the wifi name across all devices in the rig, only the actual device connected to the WAN port.
Internet Connectivity: Update April 15, 2024
I realized last season that Speedtest was blowing through my mobile data plan pretty fast, so I decided to change some aspects of how I use Speedtest to not having it downloading 400+mb frequently, instead now it only does it on demand and once per day when we wake up.
I first created three helper entities for Speedtest Last Download, Speedtest Last Upload and Speedtest Last Ping to capture the values from Speedtest before it gets disabled (so it doesn’t run). I then created a script to use Spook (HACS) to re-enable Speedtest, let it populate values (which it does when it initializes), push those values to my helpers and then disable Speedtest again:
refresh_speedtest:
alias: Refresh Speedtest
icon: "mdi:speedometer"
sequence:
- service: input_number.set_value
metadata: {}
data:
value: 0
target:
entity_id: input_number.speedtest_last_download
- service: input_number.set_value
metadata: {}
data:
value: 0
target:
entity_id: input_number.speedtest_last_upload
- service: input_number.set_value
metadata: {}
data:
value: 0
target:
entity_id: input_number.speedtest_last_ping
- service: homeassistant.enable_config_entry
data:
config_entry_id: a5c8e58af62c6173069bba92c4495122
- wait_template: "{{ states('sensor.speedtest_download') not in ['unavailable','unknown'] }}"
continue_on_timeout: true
timeout: "00:05:00"
- delay: "00:00:10"
- service: homeassistant.disable_config_entry
data:
config_entry_id: a5c8e58af62c6173069bba92c4495122
Then I have a button my dashboard that will fire that script outside of it’s scheduled run time. The new dash doesn’t differ much from the original as I set up the helper entities to use the same unit of measurement that Speedtest does.
Propane Sensors
My next fun project was wrangling my Mopeka propane sensors (Bluetooth) so that not only do I know which is active but it also lets me know when they are getting low. I utilize Cardmod a lot in my HA setups, so I have thresholds to change the color as the tank is getting low (still trial and error on this since tanks only fill to 80% to allow for gas expansion). So, at a glance I can see both my tanks are full:
And each click of the “Active Tank” changes another input_select to toggle between Driver, Passenger or Both:
swap_propane_tank:
alias: Swap Propane Tank
icon: mdi:propane-tank
sequence:
- service: input_select.select_option
data:
option: >
{% set side = states('input_select.active_propane_tank') %}
{% if side == 'Driver' %}
{{'Passenger'}}
{% elif side == 'Passenger' %}
{{'Dual'}}
{% else %}
{{'Driver'}}
{% endif %}
target:
entity_id: input_select.active_propane_tank
I have several groups of template sensors for each configuration, with one more for just reporting the top section (and other areas of my dashboard), so my summary template sensor looks like this:
sensor:
- name: "Active Propane Tank Level"
unique_id: "1041c2f9-daac-479e-b5cb-a18b90c4ef6a"
unit_of_measurement: "in"
device_class: distance
icon: mdi:arrow-left-right
state: >-
{% set side = states('input_select.active_propane_tank') %}
{% if side == 'Driver' %}
{{ states('sensor.propane_driver_tank_level') }}
{% elif side == 'Passenger' %}
{{ states('sensor.propane_passenger_tank_level') }}
{% elif side == 'Dual' %}
{% set driver = float(states('sensor.propane_driver_tank_level'), 0) %}
{% set passenger = float(states('sensor.propane_passenger_tank_level'), 0) %}
{{ driver + passenger | round(1) }}
{% endif %}
Knowing the tank levels has been super helpful so I know if I need to switch before going to bed, so I have automations that alert me if I need to switch tanks or take them in for refill.
Weather and Locations
Which takes me to weather and locations! This was a bit tricky, and I still want to refine this further, but my best option was to use a combination of date/time helpers to fire off on the day I’m traveling to a new park that will fire a script to force HA to change its location (this mostly for GPS tracking). So my travel dash looks like this:
And each date/time helper as well as the Force Stop buttons just execute scripts:
location_stop_2:
alias: RV Park Stop 2 (Location)
icon: mdi:map-marker
sequence:
- service: homeassistant.set_location
data:
latitude: 35.5888932
longitude: -106.0452443
- service: persistent_notification.create
data:
title: Add Weather to RV Assistant
message:
"You have arrived at your second stop, add this new location to the OpenWeatherMap integration as once-daily and update the dashboard to reflect the local weather.<br><br>
Use API Key [hidden to protect the innocent...] for OpenWeatherMap.<br><br>Happy camping!"
And, as the message says, I just set up a new OpenWeatherMap for that location. This part needs refinement.
I’ll try to remember to update this thread as I create new cool things for the RV but so far I’m super happy with how it has turned out! I have a few other bits like using some Broadlinks to allow me to issue voice commands to turn on the TV or change the output source or whatever.
One cool addition I made last month was adding a Belkin SoundForm Connect AirPlay 2 that lets me utilize the built-in RV distributed sound system with my Apple TV or any other AirPlay device, I love that thing, I don’t lose any ability to switch between indoor/outdoor speakers with a touch of the screen.
I also set up an ESPHome device at the house that pings my main house HA every 20 seconds or so in case it locks up while I’m on the road and if there’s no response for 2 minutes it will power off HA and power it back on, hopefully avoiding me having to call someone to reset it for me. Along with this my HA monitors my Internet and will reboot my internet router automatically over time until the connection returns, again hopefully avoiding any chance that I’m 500 miles away and can’t get to my home network.
I’m still working on decoding the Bluetooth from my Levelmate Pro so I can see the RV level on my HA dash, but it’s not that important since it has an app and the only time I use it is when I first arrive, but I’m a nerd so I want it on my dashboard not because I need it but because I can!
UPDATE: December 21, 2023
Over the summer I added a bluetooth temperature and humidity gauge that I stick above my RV thermostat with some Museum Putty and it works great with HA, I now get temperature and humidity over bluetooth for further integrations.
I’ve started working on my dynamic weather plugin that I hope to put on HACS by next spring, I wanted to wait until the dust settled from the changes to the forecast model.
I’m also working on a solar powered, cell enabled Internet option so I can keep in communication with my RV when stored.