in the past i had a few times trouble with HA on the RPI.
oke, i made a backup image and backup my settings daily and my sensor values every 15 minutes.
i have a spare SD card ready to take over if needed.
but then it still can happen that the RPI stops running when you are not around to reset it.
so i started working on an emergency plan.
there are 2 possible things that go wrong:
- HA stops running
- the RPI stops running
i havent had 1 time that HA has stopped working so that wasnt my first priority.
so i started to make sure that the RPI keeps running.
there also are 2 options
- the RPI stops running, but it can be restarted without any problems
- the RPI stops working completely.
the first one is the most easy part to control, so i have created a plan for that.
the second one i am working on.
what i needed to make sure my RPI restart when it stops running:
a) a second RPI (i had an old RPI2 lying around)
b) an arduino or esp (i have a lot of arduino nanos lying around so i used those)
c) a NRF24 tranceiver (i use mysensors for a lot of things, so i have lots of those)
d) a relayboard with 1 relay
i did use mysensors because it is very simple to setup. and there is no need for extra configuring or anything.
i connected it this way:
the cinfiguration.yaml from the backup is quite simple
homeassistant:
name: backup Home Assistant
latitude: YOUR_LATITUDE
longitude: YOUR_LONGTITUDE
unit_system: metric
time_zone: Europe/Berlin
customize: !include customize.yaml
elevation: 102
frontend:
http:
api_password: !secret http_password
notify:
- name: your_notify_name
platform: pushbullet
api_key: YOUR_API_KEY
device_tracker:
- platform: ping
interval_seconds: 10
consider_home: 30
hosts:
rpi3: YOUR_HA_IP
sensor:
- platform: rest
name: HA time
resource: http://YOUR_HA_IP:8123/api/states/sensor.date__time?api_password=YOUR_HA_PWD
value_template: '{{ value_json.state }}'
- platform: time_date
display_options:
- 'date_time'
mysensors:
gateways:
- device: '/dev/ttyUSB0'
persistence_file: '/home/pi/.homeassistant/mysensors.json'
optimistic: false
persistence: true
version: '2.0'
group:
everything:
name: Everything
entities:
- sensor.date__time
- sensor.ha_time
- device_tracker.rpi3
- switch.backup_gateway_0_1
- switch.backup_gateway_0_200
the arduino sketch is also simple:
#define MY_DEBUG
#define MY_RADIO_NRF24
#define MY_RF24_CHANNEL 40 //voor de backup gateway
#define MY_GATEWAY_SERIAL
#include <MySensors.h>
#define RELAY_1 5 // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
#define RELAY_ON 1 // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
#define CHILD_ID_RELAY1 1
MyMessage msg1(CHILD_ID_RELAY1, V_STATUS);
#define CONTROLESWITCH 200
MyMessage msgcontroleswitch(CONTROLESWITCH, V_STATUS);
bool reported=false;
long time=0;
long time2=0;
void before() {
pinMode(RELAY_1, OUTPUT);
digitalWrite(RELAY_1, loadState(CHILD_ID_RELAY1)?RELAY_ON:RELAY_OFF);
}
void setup() {
}
void presentation() {
sendSketchInfo("backup gateway", "1.0");
present(CONTROLESWITCH,S_BINARY);
present(CHILD_ID_RELAY1, S_BINARY);
}
void loop() {
if ( not reported){
report();
reported=true;
}
if (millis()-time>1800000){
reportagain();
}
}
void receive(const MyMessage &message) {
if (message.type==V_STATUS) {
if (message.sensor==CONTROLESWITCH){
reportagain();
}
if (message.sensor==CHILD_ID_RELAY1){
digitalWrite(RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
saveState(CHILD_ID_RELAY1, message.getBool());
send(msg1.set(message.getBool()));
}
}
}
void report(){
send(msgcontroleswitch.set(0));
send(msg1.setSensor(CHILD_ID_RELAY1).set(loadState(CHILD_ID_RELAY1)));
}
void reportagain(){
send(msgcontroleswitch.set(0));
send(msg1.setSensor(CHILD_ID_RELAY1).set(loadState(CHILD_ID_RELAY1)));
time=millis();
}
in HA it shows like this:
then i have an app in Appdaemon:
###########################################################################################
# #
# Rene Tode ( [email protected] ) #
# 2017/05/17 Germany #
# #
###########################################################################################
import appdaemon.appapi as appapi
import datetime
import time
class check_running(appapi.AppDaemon):
def initialize(self):
runtime = datetime.time(12, 0, 0)
self.timestamp = datetime.datetime.now()
self.run_every(self.Check_if_still_running,self.timestamp,10)
def Check_if_still_running(self, kwargs):
self.timestamp = datetime.datetime.now()
own_time = datetime.datetime.strptime(self.get_state("sensor.date__time"),"%Y-%m-%d, %H:%M")
ha_time_str = self.get_state("sensor.ha_time")
if ha_time_str == "unknown":
self.log("Warning: Home Assistant is down!")
self.run_in(self.restartRPI,60)
else:
ha_time = datetime.datetime.strptime(ha_time_str,"%Y-%m-%d, %H:%M")
time_difference = own_time - ha_time
if time_difference > datetime.timedelta(seconds=60):
self.log("Warning: There is a difference bigger then 60 seconds")
else:
self.log("Home Assistant is running correct")
if self.get_state("device_tracker.rpi3") != "home":
self.log("Warning: The RPI sensor shows that the RPI isnt running!")
self.run_in(self.restartRPI,60)
def restartRPI(self.kwargs):
if self.get_state("device_tracker.rpi3") != "home" or self.get_state("sensor.ha_time") == "unknown":
self.turn_off("switch.backup_gateway_0_1")
time.sleep(5)
self.turn_on("switch.backup_gateway_0_1")
and the appdaemon.cfg is quite empty also:
[AppDaemon]
ha_url = http://YOUR_BACKUP_HA_IP:8123
ha_key = YOUR_BACKUP_HA_PWD
logfile = STDOUT
errorfile = /home/pi/.homeassistant/appdasherror.log
app_dir = /home/pi/.homeassistant/apps/
threads = 20
timeout = 30
disable_apps = 0
dash_force_compile = 0
dash_compile_on_start = 1
[checkrunning]
module = check_running
class = check_running
next part of my project is restarting a complete copy from HA in the RPI 2 if the RPI 3 fails completely.
there are a few parts hard to realize because of the fact that the second RPI has another IP address.
could be that i create a third RPI. which is normally not running with the same IP and i let the RPI 2 start that if the running RPI fails completely. settings could be retrieved from the backup server after startup before HA starts.
i hope this helps others to create ideas or make their own emergency switch.