Merge branch 'current' into next

This commit is contained in:
Paulus Schoutsen 2018-03-23 14:07:56 -07:00
commit 772fb32af9
791 changed files with 1385 additions and 1251 deletions

View file

@ -39,7 +39,7 @@ There are several circumstances under which `initialize()` might be called:
- Following a change in the status of Daylight Savings Time
- Following a restart of Home Assistant
In every case, the App is responsible for recreating any state it might need as if it were the first time it was ever started. If `initialize()` is called, the app can safely assume that it is either being loaded for the first time, or that all callbacks and timers have been canceled. In either case, the APP will need to recreate them. Depending upon the application it may be desirable for the App to establish state such as whether or not a particular light is on, within the `initialize()` function to ensure that everything is as expected or to make immediate remedial action (e.g. turn off a light that might have been left on by mistake when the app was restarted).
In every case, the App is responsible for recreating any state it might need as if it were the first time it was ever started. If `initialize()` is called, the app can safely assume that it is either being loaded for the first time, or that all callbacks and timers have been canceled. In either case, the APP will need to recreate them. Depending upon the application it may be desirable for the App to establish state such as whether or not a particular light is on, within the `initialize()` function to ensure that everything is as expected or to make immediate remedial action (e.g., turn off a light that might have been left on by mistake when the app was restarted).
After the `initialize()` function is in place, the rest of the app consists of functions that are called by the various callback mechanisms, and any additional functions the user wants to add as part of the program logic. Apps are able to subscribe to 2 main classes of events:
@ -150,7 +150,7 @@ light = light.garage
## {% linkable_title Callback Constraints %}
Callback constraints are a feature of AppDaemon that removes the need for repetition of some common coding checks. Many Apps will wish to process their callbacks only when certain conditions are met, e.g. someone is home, and it's after sunset. These kinds of conditions crop up a lot, and use of callback constraints can significantly simplify the logic required within callbacks.
Callback constraints are a feature of AppDaemon that removes the need for repetition of some common coding checks. Many Apps will wish to process their callbacks only when certain conditions are met, e.g., someone is home, and it's after sunset. These kinds of conditions crop up a lot, and use of callback constraints can significantly simplify the logic required within callbacks.
Put simply, callback constraints are one or more conditions on callback execution that can be applied to an individual App. An App's callbacks will only be executed if all of the constraints are met. If a constraint is absent it will not be checked for.
@ -194,7 +194,7 @@ constrain_input_boolean = input_boolean.enable_motion_detection,off
```
### {% linkable_title input_select %}
The input_select constraint prevents callbacks unless the specified input_select is set to one or more of the nominated (comma separated) values. This is useful to allow certain Apps to be turned on and off according to some flag, e.g. a house mode flag.
The input_select constraint prevents callbacks unless the specified input_select is set to one or more of the nominated (comma separated) values. This is useful to allow certain Apps to be turned on and off according to some flag, e.g., a house mode flag.
```ini
# Single value
@ -272,7 +272,7 @@ Any other attributes such as brightness for a lamp will only be present if the e
Also bear in mind that some attributes such as brightness for a light, will not be present when the light is off.
In most cases, the attribute `state` has the most important value in it, e.g. for a light or switch this will be `on` or `off`, for a sensor it will be the value of that sensor. Many of the AppDaemon API calls and callbacks will implicitly return the value of state unless told to do otherwise.
In most cases, the attribute `state` has the most important value in it, e.g., for a light or switch this will be `on` or `off`, for a sensor it will be the value of that sensor. Many of the AppDaemon API calls and callbacks will implicitly return the value of state unless told to do otherwise.
### {% linkable_title get_state() %}
@ -294,9 +294,9 @@ All parameters are optional, and if `get_state()` is called with no parameters i
##### {% linkable_title entity %}
This is the name of an entity or device type. If just a device type is provided, e.g. `light` or `binary_sensor`, `get_state()` will return a dictionary of all devices of that type, indexed by the entity_id, containing all the state for each entity.
This is the name of an entity or device type. If just a device type is provided, e.g., `light` or `binary_sensor`, `get_state()` will return a dictionary of all devices of that type, indexed by the entity_id, containing all the state for each entity.
If a fully qualified `entity_id` is provided, `get_state()` will return the state attribute for that entity, e.g. `on` or `off` for a light.
If a fully qualified `entity_id` is provided, `get_state()` will return the state attribute for that entity, e.g., `on` or `off` for a light.
##### {% linkable_title attribute %}
@ -345,11 +345,11 @@ set_state(entity_id, **kwargs)
##### {% linkable_title entity_id %}
Entity id for which the state is to be set, e.g. `light.office_1`.
Entity id for which the state is to be set, e.g., `light.office_1`.
##### {% linkable_title values %}
A list of keyword values to be changed or added to the entities state. e.g. `state = "off"`. Note that any optional attributes such as colors for bulbs etc, need to reside in a dictionary called `attributes`; see the example.
A list of keyword values to be changed or added to the entities state. e.g., `state = "off"`. Note that any optional attributes such as colors for bulbs etc, need to reside in a dictionary called `attributes`; see the example.
#### {% linkable_title Examples %}
@ -461,7 +461,7 @@ handle = listen_state(callback, entity = None, **kwargs)
#### {% linkable_title Returns %}
A unique identifier that can be used to cancel the callback if required. Since variables created within object methods are local to the function they are created in, and in all likelihood the cancellation will be invoked later in a different function, it is recommended that handles are stored in the object namespace, e.g. `self.handle`.
A unique identifier that can be used to cancel the callback if required. Since variables created within object methods are local to the function they are created in, and in all likelihood the cancellation will be invoked later in a different function, it is recommended that handles are stored in the object namespace, e.g., `self.handle`.
#### {% linkable_title Parameters %}
@ -473,9 +473,9 @@ Function to be invoked when the requested state change occurs. It must conform t
##### {% linkable_title entity %}
This is the name of an entity or device type. If just a device type is provided, e.g. `light` or `binary_sensor`, `listen_state()` will subscribe to state changes of all devices of that type. If a fully qualified `entity_id` is provided, `listen_state()` will listen for state changes for just that entity.
This is the name of an entity or device type. If just a device type is provided, e.g., `light` or `binary_sensor`, `listen_state()` will subscribe to state changes of all devices of that type. If a fully qualified `entity_id` is provided, `listen_state()` will listen for state changes for just that entity.
When called, AppDaemon will supply the callback function, in old and new, with the state attribute for that entity, e.g. `on` or `off` for a light.
When called, AppDaemon will supply the callback function, in old and new, with the state attribute for that entity, e.g., `on` or `off` for a light.
##### {% linkable_title attribute (optional) %}
@ -949,11 +949,11 @@ All of the scheduler calls above support 2 additional optional arguments, `rando
For example:
```python
# Run a callback in 2 minutes minus a random number of seconds between 0 and 60, e.g. run between 60 and 120 seconds from now
# Run a callback in 2 minutes minus a random number of seconds between 0 and 60, e.g., run between 60 and 120 seconds from now
self.handle = self.run_in(callback, 120, random_start = -60, **kwargs)
# Run a callback in 2 minutes plus a random number of seconds between 0 and 60, e.g. run between 120 and 180 seconds from now
# Run a callback in 2 minutes plus a random number of seconds between 0 and 60, e.g., run between 120 and 180 seconds from now
self.handle = self.run_in(callback, 120, random_end = 60, **kwargs)
# Run a callback in 2 minutes plus or minus a random number of seconds between 0 and 60, e.g. run between 60 and 180 seconds from now
# Run a callback in 2 minutes plus or minus a random number of seconds between 0 and 60, e.g., run between 60 and 180 seconds from now
self.handle = self.run_in(callback, 120, random_start = -60, random_end = 60, **kwargs)
```
@ -1150,11 +1150,11 @@ None
##### {% linkable_title service %}
The service name, e.g. `light.turn_on`.
The service name, e.g., `light.turn_on`.
##### {% linkable_title \*\*kwargs %}
Each service has different parameter requirements. This argument allows you to specify a comma separated list of keyword value pairs, e.g. `entity_id = light.office_1`. These parameters will be different for every service and can be discovered using the developer tools. Most if not all service calls require an `entity_id` however, so use of the above example is very common with this call.
Each service has different parameter requirements. This argument allows you to specify a comma separated list of keyword value pairs, e.g., `entity_id = light.office_1`. These parameters will be different for every service and can be discovered using the developer tools. Most if not all service calls require an `entity_id` however, so use of the above example is very common with this call.
#### {% linkable_title Examples %}
@ -1187,7 +1187,7 @@ None
##### {% linkable_title entity_id %}
Fully qualified entity_id of the thing to be turned on, e.g. `light.office_lamp` or ```scene.downstairs_on```
Fully qualified entity_id of the thing to be turned on, e.g., `light.office_lamp` or ```scene.downstairs_on```
##### {% linkable_title \*\*kwargs %}
@ -1219,7 +1219,7 @@ None
##### {% linkable_title entity_id %}
Fully qualified entity_id of the thing to be turned off, e.g. `light.office_lamp` or `scene.downstairs_on`.
Fully qualified entity_id of the thing to be turned off, e.g., `light.office_lamp` or `scene.downstairs_on`.
#### {% linkable_title Examples %}
@ -1246,7 +1246,7 @@ None
##### {% linkable_title entity_id %}
Fully qualified entity_id of the thing to be toggled, e.g. `light.office_lamp` or `scene.downstairs_on`.
Fully qualified entity_id of the thing to be toggled, e.g., `light.office_lamp` or `scene.downstairs_on`.
#### {% linkable_title Examples %}
@ -1273,7 +1273,7 @@ None
##### {% linkable_title entity_id %}
Fully qualified entity_id of the input_number to be changed, e.g. `input_number.alarm_hour`.
Fully qualified entity_id of the input_number to be changed, e.g., `input_number.alarm_hour`.
##### {% linkable_title value %}
@ -1303,7 +1303,7 @@ None
##### {% linkable_title entity_id %}
Fully qualified entity_id of the input_select to be changed, e.g. `input_select.mode`.
Fully qualified entity_id of the input_select to be changed, e.g., `input_select.mode`.
##### {% linkable_title value %}
@ -1385,7 +1385,7 @@ A standard Python object reference.
#### {% linkable_title event_name %}
Name of the event that was called, e.g. `call_service`.
Name of the event that was called, e.g., `call_service`.
#### {% linkable_title data %}
@ -1528,7 +1528,7 @@ def service(self, event_name, data):
#### {% linkable_title event_name %}
The name of the event that caused the callback, e.g. `"MODE_CHANGE"` or `call_service`.
The name of the event that caused the callback, e.g., `"MODE_CHANGE"` or `call_service`.
#### {% linkable_title data %}
@ -1617,7 +1617,7 @@ A string representing the location of the tracker.
##### {% linkable_title tracker_id %}
Fully qualified entity_id of the device tracker to query, e.g. `device_tracker.andrew`.
Fully qualified entity_id of the device tracker to query, e.g., `device_tracker.andrew`.
#### {% linkable_title Examples %}
@ -1871,7 +1871,7 @@ self.log("{} ({}) is {}".format(tracker, self.friendly_name(tracker), self.get_
### {% linkable_title split_entity() %}
`split_entity()` will take a fully qualified entity id of the form `light.hall_light` and split it into 2 values, the device and the entity, e.g. `light` and `hall_light`.
`split_entity()` will take a fully qualified entity id of the form `light.hall_light` and split it into 2 values, the device and the entity, e.g., `light` and `hall_light`.
#### {% linkable_title Synopsis %}
@ -1925,7 +1925,7 @@ MyApp.turn_light_on()
### {% linkable_title split_device_list() %}
`split_device_list()` will take a comma separated list of device types (or anything else for that matter) and return them as an iterable list. This is intended to assist in use cases where the App takes a list of entities from an argument, e.g. a list of sensors to monitor. If only one entry is provided, an iterable list will still be returned to avoid the need for special processing.
`split_device_list()` will take a comma separated list of device types (or anything else for that matter) and return them as an iterable list. This is intended to assist in use cases where the App takes a list of entities from an argument, e.g., a list of sensors to monitor. If only one entry is provided, an iterable list will still be returned to avoid the need for special processing.
#### {% linkable_title Synopsis %}
@ -1941,7 +1941,7 @@ A list of split devices with 1 or more entries.
```python
for sensor in self.split_device_list(self.args["sensors"]):
do something for each sensor, e.g. make a state subscription
do something for each sensor, e.g., make a state subscription
```

View file

@ -29,7 +29,7 @@ So why `AppDaemon`? AppDaemon is not meant to replace Home Assistant Automations
- New paradigm - some problems require a procedural and/or iterative approach, and `AppDaemon` Apps are a much more natural fit for this. Recent enhancements to Home Assistant scripts and templates have made huge strides, but for the most complex scenarios, Apps can do things that Automations can't
- Ease of use - AppDaemon's API is full of helper functions that make programming as easy and natural as possible. The functions and their operation are as "Pythonic" as possible, experienced Python programmers should feel right at home.
- Reuse - write a piece of code once and instantiate it as an app as many times as you need with different parameters e.g. a motion light program that you can use in 5 different places around your home. The code stays the same, you just dynamically add new instances of it in the config file
- Reuse - write a piece of code once and instantiate it as an app as many times as you need with different parameters e.g., a motion light program that you can use in 5 different places around your home. The code stays the same, you just dynamically add new instances of it in the config file
- Dynamic - AppDaemon has been designed from the start to enable the user to make changes without requiring a restart of Home Assistant, thanks to its loose coupling. However, it is better than that - the user can make changes to code and AppDaemon will automatically reload the code, figure out which Apps were using it and restart them to use the new code with out the need to restart `AppDaemon` itself. It is also possible to change parameters for an individual or multiple apps and have them picked up dynamically, and for a final trick, removing or adding apps is also picked up dynamically. Testing cycles become a lot more efficient as a result.
- Complex logic - Python's If/Else constructs are clearer and easier to code for arbitrarily complex nested logic
- Durable variables and state - variables can be kept between events to keep track of things like the number of times a motion sensor has been activated, or how long it has been since a door opened

View file

@ -1,7 +1,7 @@
---
layout: page
title: "Configuration Backup to Dropbox"
description: "Instructions how backup your Home Assistant configuration to Dropbox"
description: "Instructions on how backup your Home Assistant configuration to Dropbox"
date: 2017-04-24 18:00
sidebar: true
comments: false

View file

@ -1,7 +1,7 @@
---
layout: page
title: "Configuration Backup to GitHub"
description: "Instructions how backup your Home Assistant configuration to GitHub"
description: "Instructions on how backup your Home Assistant configuration to GitHub"
date: 2017-01-05 18:00
sidebar: true
comments: false
@ -35,7 +35,7 @@ Some best practices to consider before putting your configuration on GitHub:
### {% linkable_title Step 1: Installing and Initializing Git %}
In order to put your configuration on GitHub, you must install the git package on your Home Assistant server (instructions below will work on Raspberry Pi, Ubunutu, or any Debian-based system):
In order to put your configuration on GitHub, you must install the git package on your Home Assistant server (instructions below will work on Raspberry Pi, Ubunutu, or any Debian-based system) *note: this isn't required in Hass.io, it's included as default so proceed to step 2*:
```bash
$ sudo apt-get update

View file

@ -1,7 +1,7 @@
---
layout: page
title: "Configuration Backup to USB drive"
description: "Instructions how backup your Home Assistant configuration to USB drive"
description: "Instructions on how backup your Home Assistant configuration to USB drive"
date: 2017-04-29 08:00
sidebar: true
comments: false

View file

@ -10,7 +10,7 @@ footer: true
---
<p class='note'>
If you are using Hass.io, do not use this guide. Instead, use the [DuckDNS add-on](/addons/duckdns/) to automatically maintain a subdomain including HTTPS certificates via Let's Encrypt.
If you are using Hass.io or Hassbian, do not use this guide. Instead, use the [DuckDNS add-on](/addons/duckdns/) for Hass.io or the [DuckDNS suite](https://github.com/home-assistant/hassbian-scripts/blob/master/docs/duckdns.md) for Hassbian to automatically maintain a subdomain including HTTPS certificates via Let's Encrypt.
</p>
<p class=' note warning'>
@ -29,9 +29,9 @@ This guide was added by mf_social on 16/03/2017 and was valid at the time of wri
* If you are not using Home Assistant on a Debian/Raspian/Hassbian system you will be able to convert any of the terminology I use in to the correct syntax for your system.
* You understand that this is a 'guide' covering the general application of these things to the general masses and there are things outside of the scope of it, and it does not cover every eventuality (although I have made some notes where people may stumble). Also, I have used some turns of phrase to make it easier to understand for the novice reader which people of advanced knowledge may say is innacurate. My goal here is to get you through this guide with a satisfactory outcome and have a decent understanding of what you are doing and why, not to teach you advanced internet communication protocols.
* Each step presumes you have fully completed the previous step successfully, so if you did an earlier step following a different guide, please ensure that you have not missed anything out that may affect the step you have jumped to, and ensure that you adapt any commands to take in to account different file placements from other guides.
Steps we will take:
- 0 - Gain a basic level of understanding around IP addresses, port numbers and port forwarding
- 1 - Set your device to have a static IP address
- 2 - Set up port forwarding without TLS/SSL and test connection
@ -42,48 +42,48 @@ Steps we will take:
- 7 - Set up a sensor to monitor the expiry date of the certificate
- 8 - Set up an automatic renewal of the TLS/SSL certificate
- 9 - Set up an alert to warn us if something went wrong
### {% linkable_title 0 - Gain a basic level of understanding around IP addresses, port numbers and port forwarding %}
An IP address is a bit like a phone number. When you access your Home Assistant instance you type something similar to 192.168.0.200:8123 in to your address bar of your browser. The bit before the colon is the IP address (in this case 192.168.0.200) and the bit after is the port number (in this case 8123). When you SSH in to the device running Home Assistant you will use the same IP address, and you will use port 22. You may not be aware that you are using port 22, but if you are using Putty look in the box next to where you type the IP address, you will see that it has already selected port 22 for you.
So, if an IP address is like a phone number, a port number is like an extension number. An analogy would be if you phone your local doctors on 192-1680-200 and the receptionist answers, you ask to speak to Dr. Smith and she will put you through to extension 8123, which is the phone Dr. Smith is sitting at. The doctors surgery is the device your Home Assistant is running on, Dr. Smith is your Home Assistant. Thusly, your Home Assistant instance is 'waiting for your call' on port 8123, at the device IP 192.168.0.200 .
Now, to speak to the outside world your connection goes through a router. Your router will have two IP addresses. One is the internal network number, most likely 192.168.0.1 in my example, and an external IP address that incoming traffic is sent to. In the example of calling the doctors, the external IP is your telephone number's area code.
So, when we want to connect to our Home Assistant instance from outside our network we will need to call the correct extension number, at the correct phone number, in the correct area code.
We will be looking for a system to run like this (in this example I will pretend our external IP is 12.12.12.12):
```text
Outside world -> 12.12.12.12:8123 -> your router -> 192.168.0.200:8123
```
Sounds simple? It really is except for two small, but easy to overcome, complications:
* IP addresses are often dynamically allocated, so they can change.
* Because of the way the internet works you cannot chain IP addresses together to get from where you are, to where you want to go.
To get around the issue of changing IP addresses we must remember that there are two IP addresses affected. Your external one (which we will 'call' to get on to your network from the internet) and your internal one (192.168.0.200 in the example I am currently using).
So, we can use a static IP to ensure that whenever our device running Home Assistant connects to our router it always uses the same address. This way our internal IP never changes. This is covered in step 1 below.
We then have no control over our external IP, as our Service Provider will give us a new one at random intervals. To fix this we will use a service called DuckDNS which will give us a name for our connection (something like examplehome.duckdns.org) and behind the scenes will continue to update your external IP. So no matter how many times the IP address changes, typing examplehome.duckdns.org in to our browser will convert to the correct, up-to-date, IP address. This is covered in step 3 below.
To get around the issue of not being able to chain the IP addresses together (I can't say I want to call 12:12:12:12 and be put through to 192.168.0.200, and then be put through to extension 8123) we use port forwarding. Port forwarding is the process of telling your router which device to allow the outside connection to speak to. In the doctors surgery example, port forwarding is the receptionist. This takes a call from outside, and forwards it to the correct extension number inside. It is important to note that port forwarding can forward an incoming request for one port to a different port on your internal network if you so choose, and we will be doing this later on. The end result being that when we have our TSL/SSL certificate our incoming call will be requesting port 443 (because that is the SSL port, like the SSH port is always 22), but our port forwarding rule will forward this to our HA instance on port 8123. When this guide is completed we will run something like this:
```text
Outside world -> https://examplehome.duckdns.org -> 12.12.12.12:443 -> your router -> 192.168.0.200:8123
```
So, let's make it happen...
### {% linkable_title 1 - Set your device to have a static IP address %}
Whenever a device is connected to a network it has an IP address. This IP address is often dynamically assigned to the device on connection. This means there are occasions where the IP address you use to access Home Assistant, or SSH in to the device running Home Assistant, may change. Setting a static IP address means that the device will always be on the same address.
SSH in to your system running Home Assistant and login.
Type the following command to list your network interfaces:
```bash
$ ifconfig
```
@ -94,17 +94,17 @@ You will receive an output similar to the image below:
<img src='/images/screenshots/ip-set.jpg' />
Screenshot
</p>
Make a note of the interface name and the IP address you are currently on. In the picture it is the wireless connection that is highlighted, but with your setup it may be the wired one (eth0 or similar), make sure you get the correct information.
Then type the following command to open the text file that controls your network connection:
```bash
```bash
$ sudo nano /etc/dhcpcd.conf
```
At the bottom of the file add the following lines:
```text
interface wlan0 <----- or the interface you just wrote down.
@ -195,13 +195,17 @@ In the domains section pick a name for your subdomain, this can be anything you
The URL you will be using later to access your Home Assistant instance from outside will be the subdomain you picked, followed by duckdns.org . For our example we will say our URL is examplehome.duckdns.org
On the top left of duckdns.org select the install option. Then pick your operating system from the list. In our example we will use a Raspberry Pi. In the dropdown box select the URL you just created.
Set up Home Assistant to keep your DuckDNS URL and external IP address in sync. In your `configuration.yaml` file add the following:
Duckdns.org will now generate personalised instructions for you to follow so that your device can update their website every time your IP address changes. Carefully follow the instructions given on duckdns.org to set up your device.
```yaml
duckdns:
domain: examplehome
access_token: abcdefgh-1234-abcd-1234-abcdefgh
```
At the end of the instructions DuckDNS will suggest you set up port forwarding. No need, we have already done this in step 2.
The access token is available on your DuckDNS page. Restart Home Assistant after the change.
What you have now done is set up DuckDNS so that whenever you type examplehome.duckdns.org in to your browser it will convert that to your router's external IP address. Your external IP address will always be up to date because your device running Home Assistant will update DuckDNS every time it changes.
What you have now done is set up DuckDNS so that whenever you type examplehome.duckdns.org in to your browser it will convert that to your router's external IP address. Your external IP address will always be up to date because Homeassistant will update DuckDNS every time it changes.
Now type your new URL in to your address bar on your browser with port 8123 on the end:
@ -251,7 +255,7 @@ $ sudo adduser hass sudo
If you did not already log in as the user that currently runs Home Assistant, change to that user (usually `hass` or `homeassistant` - you may have used a command similar to this in the past):
```bash
$ sudo su -s /bin/bash hass
$ sudo su -s /bin/bash hass
```
Make sure you are in the home directory for the Home Assistant user:
@ -272,7 +276,7 @@ $ chmod a+x certbot-auto
You might need to stop Home Assistant before continuing with the next step. You can do this via the Web-UI or use the following command if you are running on Hassbian:
```text
$ sudo systemctl stop home-assistant@homeassistant.service
$ sudo systemctl stop home-assistant@homeassistant.service
```
You can restart Home Assistant after the next step using the same command and replacing `stop` with `start`.
@ -336,7 +340,7 @@ http:
ssl_key: /etc/letsencrypt/live/examplehome.duckdns.org/privkey.pem
base_url: examplehome.duckdns.org
```
You may wish to set up other options for the [http](https://home-assistant.io/components/http/) component at this point, these extra options are beyond the scope of this guide.
Save the changes to configuration.yaml. Restart Home Assistant.
@ -363,7 +367,7 @@ https://YOUR-HA-IP:8123
Some cases such as this are where your router does not allow 'loopback' or where there is a problem with incoming connections due to technical failure. In these cases you can still use your internal connection and safely ignore the warnings.
If you were previously using a webapp on your phone/tablet to access your Home Assistant you should delete the old one and create a new one with the new address. The old one will no longer work as it is not keyed to your new, secure URL. Instructions for creating your new webapp can be found here:
If you were previously using a webapp on your phone/tablet to access your Home Assistant you should delete the old one and create a new one with the new address. The old one will no longer work as it is not keyed to your new, secure URL. Instructions for creating your new webapp can be found here:
```text
https://home-assistant.io/docs/frontend/mobile/
@ -387,11 +391,11 @@ You are now part of one of two groups:
* If you have BOTH rules you are able to set up auto renewals of your certificates using port 80 and the standard http challenge, as performed above.
* If you only have one, you are still able to set up auto renewals of your certificates, but will have to specify additional options when renewing that will temporarily stop Home Assistant and use port 8123 for certificate renewal.
Please remember whether you are a ONE-RULE person or a BOTH-RULE person for step 8!
Let's Encrypt certificates only last for 90 days. When they have less than 30 days left they can be renewed. Renewal is a simple process.
Move on to step 7 to see how to monitor your certificates expiry date, and be ready to renew your certificate when the time comes.
### {% linkable_title 7 - Set up a sensor to monitor the expiry date of the certificate %}
@ -402,9 +406,9 @@ Setting a sensor to read the number of days left on your TLS/SSL certificate bef
* You can set automations based on the number of days left
* You can set alerts to notify you if your certificate has not been renewed and is coming close to expiry.
* If you cannot set up automatic renewals due to your ISP blocking port 80, you will have timely reminders to complete the process manually.
If you do not wish to set up a sensor you can skip straight to step 8 to learn how to update your certificates.
The sensor will rely on a command line program that needs to be installed on your device running Home Assistant. SSH in to the device and run the following commands:
```bash
@ -442,33 +446,33 @@ If you are a ONE-RULE person (from step 6), you can automatically renew your cer
If you are a TWO-RULE person (from step 6), you can automatically renew your certificate using a `http-01` challenge and port 80.
There are a number of options for automating the renewal process:
#### Option 1:
Your certificate can be renewed as a 'cron job' - cron jobs are background tasks run by the computer at specified intervals (and are totally independent of Home Assistant). Defining cron is outside of the scope of this guide but you will have had dealings with `crontab` when setting up DuckDNS in step 3
To set a cron job to run the script at regular intervals:
* SSH in to your device running Home Assistant.
* Change to your Home Assistant user (command similar to):
```bash
$ sudo su -s /bin/bash hass
```
* Open the crontab:
```bash
$ crontab -e
```
* If you are a TWO-RULE Person: Scroll to the bottom of the file and paste in the following line
```text
30 2 * * 1 ~/certbot/certbot-auto renew --quiet --no-self-upgrade --standalone --preferred-challenges http-01
```
* If you are a ONE-RULE Person: Scroll to the bottom of the file and paste in the following line
```text
30 2 * * 1 ~/certbot/certbot-auto renew --quiet --no-self-upgrade --standalone --preferred-challenges tls-sni-01 --tls-sni-01-port 8123 --pre-hook "sudo systemctl stop home-assistant@homeassistant.service" --post-hook "sudo systemctl start home-assistant@homeassistant.service"
```
@ -478,17 +482,17 @@ $ crontab -e
3. We define pre-hooks and post-hooks that stop our Home Assistant service before certbot runs, freeing port 8123 for certificate renewal, and restart Home Assistant after renewal is complete.
* Save the file and exit
#### Option 2:
You can set an automation in Home Assistant to run the certbot renewal script.
Add the following sections to your configuration.yaml if you are a TWO-RULE person
```yaml
shell_command:
```yaml
shell_command:
renew_ssl: ~/certbot/certbot-auto renew --quiet --no-self-upgrade --standalone --preferred-challenges http-01
automation:
- alias: 'Auto Renew SSL Cert'
trigger:
@ -502,34 +506,34 @@ If you are a ONE-RULE person, replace the `certbot-auto` command above with `~/c
#### Option 3:
You can manually update the certificate when your certificate is less than 30 days to expiry.
To manually update:
To manually update:
* SSH in to your device running Home Assistant.
* Change to your Home Assistant user (command similar to):
```bash
$ su - s /bin/bash hass
```
* Change to your certbot folder
```bash
$ cd ~/certbot/
```
* Run the renewal command
```bash
$ ./certbot-auto renew --quiet --no-self-upgrade --standalone --preferred-challenges http-01
```
* If you are a ONE-RULE person, replace the `certbot-auto` command above with `~/certbot/certbot-auto renew --quiet --no-self-upgrade --standalone --preferred-challenges tls-sni-01 --tls-sni-01-port 8123 --pre-hook "sudo systemctl stop home-assistant@homeassistant.service" --post-hook "sudo systemctl start home-assistant@homeassistant.service"`
So, now were all set up. We have our secured, remotely accessible Home Assistant instance and we're on track for keeping our certificates up to date. But what if something goes wrong? What if the automation didn't fire? What if the cron job forgot to run? What if the dog ate my homework? Read on to set up an alert so you can be notified in plenty of time if you need to step in and sort out any failures.
### {% linkable_title 9 - Set up an alert to warn us if something went wrong. %}
We set up our automatic renewal of our certificates and whatever method we used the certificate should be renewed on or around 30 days before it expires. But what if a week later it still hasn't been? This alert will go off if the expiry time on the certificate gets down to 21 days. This will give you 3 weeks to fix the problem, get your new certificate installed and get another 90 days of secure Home Assistant connections in play.
In your `configuration.yaml` add the following automation, adding your preferred notification platform where appropriate:
@ -546,7 +550,7 @@ automation:
data:
message: 'Warning - SSL certificate expires in 21 days and has not been automatically renewed'
```
If you receive this warning notification, follow the steps for a manual update from step 8. Any error messages received at that point can be googled and resolved. If the manual update goes without a hitch there may be something wrong with your chosen method for automatic updates, and you can start troubleshooting from there.
So, that's it. We've taken a Home Assistant instance that was only reachable on the local network, made it accessible from the internet, secured it, and set up a system to ensure that it always stays secure. Well done, go and treat yourself to a cookie!

View file

@ -47,7 +47,7 @@ There are no dependencies on Python modules that are not part of the standard li
### {% linkable_title Configuration %}
Near the top of the `configurator.py`-file you will find some global variables you can change to customize the configurator. If you are unfamiliar with Python: when setting variables of the type _string_, you have to write that within quotation marks. The default settings are fine for just checking out the configurator quickly. With more customized setups you should change some settings though.
To keep your settings across updates it is also possible to save settings in an external file. In that case copy [settings.conf](https://github.com/danielperna84/hass-configurator/blob/master/settings.conf) wherever you like and append the full path to the file to the command when starting the configurator. E.g. `sudo .configurator.py /home/homeassistant/.homeassistant/mysettings.conf`. This file is in JSON format. So make sure it has a valid syntax (you can set the editor to JSON to get syntax highlighting for the settings). The major difference to the settings in the py-file is, that `None` becomes `null`.
To keep your settings across updates it is also possible to save settings in an external file. In that case copy [settings.conf](https://github.com/danielperna84/hass-configurator/blob/master/settings.conf) wherever you like and append the full path to the file to the command when starting the configurator. e.g., `sudo .configurator.py /home/homeassistant/.homeassistant/mysettings.conf`. This file is in JSON format. So make sure it has a valid syntax (you can set the editor to JSON to get syntax highlighting for the settings). The major difference to the settings in the py-file is, that `None` becomes `null`.
#### LISTENIP (string)
The IP the service is listening on. By default it is binding to `0.0.0.0`, which is every interface on the system.
@ -66,11 +66,11 @@ Set credentials in the form of `"username:password"` if authentication should be
#### ALLOWED_NETWORKS (list)
Limit access to the configurator by adding allowed IP addresses / networks to the list, e.g `ALLOWED_NETWORKS = ["192.168.0.0/24", "172.16.47.23"]`
#### BANNED_IPS (list)
List of statically banned IP addresses, e.g. `BANNED_IPS = ["1.1.1.1", "2.2.2.2"]`
List of statically banned IP addresses, e.g., `BANNED_IPS = ["1.1.1.1", "2.2.2.2"]`
#### BANLIMIT (integer)
Ban IPs after `n` failed login attempts. Restart the service to reset banning. The default of `0` disables this feature. `CREDENTIALS` has to be set for this to work.
#### IGNORE_PATTERN (list)
Files and folders to ignore in the UI, e.g. `IGNORE_PATTERN = [".*", "*.log", "__pycache__"]`.
Files and folders to ignore in the UI, e.g., `IGNORE_PATTERN = [".*", "*.log", "__pycache__"]`.
#### DIRSFIRST (bool)
If set to `True`, directories will be displayed at the top of the filebrowser.
#### GIT (bool)
@ -81,7 +81,7 @@ __Note regarding `ALLOWED_NETWORKS`, `BANNED_IPS` and `BANLIMIT`__:
The way this is implemented works in the following order:
1. (Only if `CREDENTIALS` is set) Check credentials
- Failure: Retry `BANLIMIT` times, after that return error 420 (unless you try again without any authentication headers set, e.g. private tab of your browser)
- Failure: Retry `BANLIMIT` times, after that return error 420 (unless you try again without any authentication headers set, e.g., private tab of your browser)
- Success: Continue
2. Check if client IP address is in `BANNED_IPS`
- Yes: Return error 420

View file

@ -1,7 +1,7 @@
---
layout: page
title: "Synology"
description: "Instructions how to get Home Assistant up and running on Synology"
description: "Instructions on how to get Home Assistant up and running on Synology"
release_date: 2016-12-07 15:00:00 -0500
sidebar: true
comments: false