Merge branch 'current' into next

This commit is contained in:
Franck Nijhof 2022-05-03 13:26:10 +02:00
commit b10f256133
No known key found for this signature in database
GPG Key ID: D62583BA8AB11CA3
18 changed files with 130 additions and 219 deletions

View File

@ -313,6 +313,7 @@ Supported abbreviations for device registry configuration:
The following software has built-in support for MQTT discovery:
- [Arilux AL-LC0X LED controllers](https://github.com/smrtnt/Arilux_AL-LC0X)
- [ebusd](https://github.com/john30/ebusd)
- [ecowitt2mqtt](https://github.com/bachya/ecowitt2mqtt)
- [ESPHome](https://esphome.io)
- [ESPurna](https://github.com/xoseperez/espurna)

View File

@ -388,6 +388,7 @@ The sunset/sunrise conditions do not work in locations inside the polar circles,
In those cases it is advised to use conditions evaluating the solar elevation instead of the before/after sunset/sunrise conditions.
</div>
This is an example of 1 hour offset after sunset:
```yaml
condition:
condition: sun
@ -395,7 +396,7 @@ condition:
after_offset: "-01:00:00"
```
This is an example of 1 hour offset after sunset.
This is 'when dark' - equivalent to a state condition on `sun.sun` of `below_horizon`:
```yaml
condition:
@ -404,7 +405,7 @@ condition:
before: sunrise
```
This is 'when dark' - equivalent to a state condition on `sun.sun` of `below_horizon`.
This is 'when light' - equivalent to a state condition on `sun.sun` of `above_horizon`:
```yaml
condition:
@ -413,8 +414,6 @@ condition:
before: sunset
```
This is 'when light' - equivalent to a state condition on `sun.sun` of `above_horizon`.
We cannot use both keys in this case as it will always be `false`.
```yaml
@ -429,7 +428,7 @@ condition:
A visual timeline is provided below showing an example of when these conditions are true. In this chart, sunrise is at 6:00, and sunset is at 18:00 (6:00 PM). The green areas of the chart indicate when the specified conditions are true.
<img src='/images/docs/scripts/sun-conditions.svg' alt='Graphic showing an example of sun conditions' />
![Graphic showing an example of sun conditions](/images/docs/scripts/sun-conditions.svg)
## Template condition

View File

@ -6,5 +6,5 @@
<p class='hero-buttons'>
<a href='/getting-started/'>Get started</a>
<a href='https://demo.home-assistant.io' target='_blank'>View demo</a>
<a href='/integrations/'>Browse 1000+ integrations</a>
<a href='/integrations/'>Browse 1900+ integrations</a>
</p>

View File

@ -207,11 +207,20 @@ _All these can be extended if your usage calls for more resources._
- title: VirtualBox
content: |
1. Create a new virtual machine
2. Select Type “Linux” and Version “Other Linux (64-bit)”
2. Select Type “Linux” and Version “Linux 2.6 / 3.x / 4.x (64-bit)”
3. Select “Use an existing virtual hard disk file”, select the unzipped VDI file from above
4. Edit the “Settings” of the VM and go “System” then “Motherboard” and select “Enable EFI”
5. Then go to “Network” “Adapter 1” choose “Bridged Adapter” and choose your Network adapter
6. Then go to “Audio” and choose “Intel HD Audio” as Audio Controller.
<div class="note info">
By default VirtualBox does not free up unused disk space. To automatically shrink the vdi disk image
the `discard` option must be enabled:
```bash
VBoxManage storageattach <VM name> --storagectl "SATA" --port 0 --device 0 --nonrotational on --discard on
```
</div>
- title: KVM
content: |

View File

@ -129,6 +129,10 @@ The `button.<your_vehicle>_find_vehicle` button requests the vehicle to update t
</div>
### Update the state / refresh from cloud
The `button.<vehicle_model>_refresh_from_cloud` button fetches the last state of the vehicles of all your accounts from the BMW server. This does *not* trigger an update from the vehicle; it gets the data from the BMW servers. So this service does *not* interact with your vehicles.
## Disclaimer
This software is not affiliated with or endorsed by BMW Group.

View File

@ -28,7 +28,7 @@ download_dir:
### Use the service
Go to the "Developer Tools", then to "Call Service", and choose `downloader/download_file` from the list of available services. Fill the "Service Data" field as shown in the example below and hit "CALL SERVICE".
Go to the "Developer Tools", then to "Services", and choose `downloader/download_file` from the list of available services. Fill the "Service Data" field as shown in the example below and hit "CALL SERVICE".
```json
{"url":"http://domain.tld/path/to/file"}
@ -45,8 +45,8 @@ This will download the file from the given URL.
### Download Status Events
When a download finished successfully, Home Assistant will emit a 'downloader_download_completed' event to the event bus which you can use to write automations against.
In case download failed another event 'downloader_download_failed' is emitted to indicate that the download did not complete successfully.
When a download finished successfully, Home Assistant will emit a `downloader_download_completed` event to the event bus which you can use to write automations against.
In case download failed another event `downloader_download_failed` is emitted to indicate that the download did not complete successfully.
Along with the event the following payload parameters are available:

View File

@ -123,16 +123,16 @@ Your Google Assistant devices will still communicate via the internet to:
<div class='note'>
The [HTTP integration](/integrations/http) must **not** be configured to use an SSL certificate with the [`ssl_certificate` option](/integrations/http/#ssl_certificate).
This is because the Google Assistant device will connect directly to the IP of your Home Assistant instance and will fail if it encounters an invalid SSL certificate.
For secure remote access, use a reverse proxy such as the {% my supervisor_addon addon="core_nginx_proxy" title="NGINX SSL" %} add-on instead of directing external traffic straight to Home Assistant.
</div>
1. Open the project you created in the [Actions on Google console](https://console.actions.google.com/).
2. Click `Develop` on the top of the page, then click `Actions` located in the hamburger menu on the top left.
3. Upload [this Javascript file](/assets/integrations/google_assistant/app.js) for both Node and Chrome by clicking the `Upload Javascript files` button.
3. Upload `app.js` from [here](https://github.com/NabuCasa/home-assistant-google-assistant-local-sdk/releases/latest) for both Node and Chrome by clicking the `Upload Javascript files` button.
4. Add device scan configuration:
1. Click `+ New scan config` if no configuration exists
2. Select `MDNS`
@ -251,7 +251,7 @@ Currently, the following domains are available to be used with Google Assistant,
- switch (on/off)
- fan (on/off/speed percentage/preset mode)
- light (on/off/brightness/rgb color/color temp)
- lock
- lock
- cover (on/off/set position)
- media_player (on/off/set volume (via set volume)/source (via set input source)/control playback)
- climate (temperature setting, hvac_mode)
@ -307,7 +307,7 @@ The `request_sync` service may fail with a 404 if the `project_id` of the HomeGr
1. Removing your project from the [Google Cloud API Console](https://console.cloud.google.com).
2. Add a new project to the [Actions on Google console](https://console.actions.google.com) Here you get a new `project_id`.
3. Run through the previously mentioned [Actions on Google console] setup instructions until the step to create a `service_account`.
4. Once you begin to create a new `service_account` in the [Google Cloud API Console], ensure you select the project created in [Actions on Google console] by verifying the `project_id`.
4. Once you begin to create a new `service_account` in the [Google Cloud API Console], ensure you select the project created in [Actions on Google console] by verifying the `project_id`.
5. Enable HomeGraph API to the new project.
Verify that the Google Assistant is available on `https://[YOUR HOME ASSISTANT URL:PORT]/api/google_assistant` If it is working it should return `405: Method Not Allowed` when opened in a browser or via curl.

View File

@ -293,3 +293,18 @@ When a group contains entities from domains that have multiple `on` states or on
It is possible to create a group that the system cannot calculate a group state. Groups with entities from unsupported domains will always have an unknown state.
These groups can still be in templates with the `expand()` directive, called using the `homeassistant.turn_on` and `homeassistant.turn_off` services, etc.
### Services
This integration provides the following services to modify groups and a service to reload the configuration without restarting Home Assistant itself.
| Service | Data | Description |
| ------- | ---- | ----------- |
| `set` | `Object ID` | Group id and part of entity id.
| | `Name` | Name of the group.
| | `Icon` | Name of the icon for the group.
| | `Entities` | List of all members in the group. Not compatible with **delta**.
| | `Add Entities` | List of members that will change on group listening.
| | `All` | Enable this option if the group should only turn on when all entities are on.
| `remove` | `Object ID` | Group id and part of entity id.
| `reload` | `Object ID` | Group id and part of entity id.

View File

@ -45,11 +45,11 @@ To obtain the `oauth_code` cookie value, follow the steps below:
* In the cookie list, double click on the value for the `oauth_code` cookie to select it, and copy the value. This is the authorization code
<div class='note'>
You can't write messages to yourself or get notifications in a group, if "you" write the message. The best way is to create a new Google Hangouts account for this integration.<br>
You can't write messages to yourself or get notifications in a group, if "you" write the message. The best way is to create a new Google Chat account for this integration.<br>
<br>
If you secured your account with 2-factor authentication: Only verification by app or SMS are supported. There is no support for verification by prompt on your phone.<br>
<br>
The manual authentication work-around is a result of unofficial support for using bots in hangouts from Google.
The manual authentication work-around is a result of unofficial support for using bots in Chat from Google.
</div>
The authentication token will be generated and stored internally.

View File

@ -19,7 +19,7 @@ templates.
The preferred way to configure input datetime is via the user interface at **Configuration** -> **Helpers**. Click the add button and then choose the **Date and/or time** option.
To be able to add **Helpers** via the user interface you should have `default_config:` in your `configuration.yaml`, it should already be there by default unless you removed it.
If you removed `default_config:` from you configuration, you must add `input_datetime:` to your `configuration.yaml` first, then you can use the UI.
If you removed `default_config:` from your configuration, you must add `input_datetime:` to your `configuration.yaml` first, then you can use the UI.
`input_datetime` can also be configured via YAML. To add three datetime inputs to your installation,
one with both date and time, and one with date or time each,
@ -87,7 +87,7 @@ automations and templates.
### Restore State
If you set a valid value for `initial` this integration will start with the state set to that value. Otherwise, it will restore the state it had prior to Home Assistant stopping.
If you set a valid value for `initial`, this integration will start with the state set to that value. Otherwise, it will restore the state it had prior to Home Assistant stopping.
### Services

View File

@ -24,6 +24,7 @@ The `mqtt` light platform lets you control your MQTT enabled lights through one
| RGBW Color | ✔ | ✔ | ✘ |
| RGBWW Color | ✔ | ✔ | ✘ |
| Transitions | ✘ | ✔ | ✔ |
| White | ✔ | ✔ | ✘ |
| XY Color | ✔ | ✔ | ✘ |
@ -299,17 +300,49 @@ rgb_command_template:
required: false
type: string
rgb_command_topic:
description: "The MQTT topic to publish commands to change the light's RGB state. Please note that the color value sent by Home Assistant is normalized to full brightness if `brightness_command_topic` is set. Brightness information is in this case sent separately in the `brightness_command_topic`. This will cause a light that expects an absolute color value (including brightness) to flicker."
description: "The MQTT topic to publish commands to change the light's RGB state."
required: false
type: string
rgb_state_topic:
description: "The MQTT topic subscribed to receive RGB state updates. The expected payload is the RGB values separated by commas, for example, `255,0,127`. Please note that the color value received by Home Assistant is normalized to full brightness. Brightness information is received separately in the `brightness_state_topic`."
description: "The MQTT topic subscribed to receive RGB state updates. The expected payload is the RGB values separated by commas, for example, `255,0,127`."
required: false
type: string
rgb_value_template:
description: "Defines a [template](/docs/configuration/templating/#processing-incoming-data) to extract the RGB value."
required: false
type: string
rgbw_command_template:
description: "Defines a [template](/docs/configuration/templating/) to compose message which will be sent to `rgbw_command_topic`. Available variables: `red`, `green`, `blue` and `white`."
required: false
type: string
rgbw_command_topic:
description: "The MQTT topic to publish commands to change the light's RGBW state."
required: false
type: string
rgbw_state_topic:
description: "The MQTT topic subscribed to receive RGBW state updates. The expected payload is the RGBW values separated by commas, for example, `255,0,127,64`."
required: false
type: string
rgbw_value_template:
description: "Defines a [template](/docs/configuration/templating/#processing-incoming-data) to extract the RGBW value."
required: false
type: string
rgbww_command_template:
description: "Defines a [template](/docs/configuration/templating/) to compose message which will be sent to `rgbww_command_topic`. Available variables: `red`, `green`, `blue`, `cold_white` and `warm_white`."
required: false
type: string
rgbww_command_topic:
description: "The MQTT topic to publish commands to change the light's RGBWW state."
required: false
type: string
rgbww_state_topic:
description: "The MQTT topic subscribed to receive RGBWW state updates. The expected payload is the RGBWW values separated by commas, for example, `255,0,127,64,32`."
required: false
type: string
rgbww_value_template:
description: "Defines a [template](/docs/configuration/templating/#processing-incoming-data) to extract the RGBWW value."
required: false
type: string
schema:
description: The schema to use. Must be `default` or omitted to select the default schema.
required: false

View File

@ -26,15 +26,27 @@ Additionally the following brands have been reported to also work with this inte
- [Brel Home](https://www.brel-home.nl/)
- [3 Day Blinds](https://www.3dayblinds.com/)
- [Dooya](http://www.dooya.com/)
- [Gaviota](https://www.gaviotagroup.com/en/)
- [Havana Shade](https://havanashade.com/)
- [Hurrican Shutters Wholesale](https://www.hurricaneshutterswholesale.com/)
- [Inspired Shades](https://www.inspired-shades.com/)
- [iSmartWindow](https://www.ismartwindow.co.nz/)
- [Martec](https://www.martec.co.nz/)
- [Motion Blinds](https://motionblinds.com/)
- [Raven Rock MRG](https://www.ravenrockmfg.com/)
- [Raven Rock MFG](https://www.ravenrockmfg.com/)
- [Smart Blinds](https://www.smartblinds.nl/)
- [Smart Home](https://www.smart-home.hu)
- [Uprise Smart Shades](http://uprisesmartshades.com)
This integration allows for both directly controlling blinds that support wifi-connection and controlling Uni- and Bi-direction blinds that connect to a 433MHz WiFi bridge.
The following bridges are reported to work with this integration:
- CM-20 Motion Blinds bridge
- CMD-01 Motion Blinds mini-bridge
- DD7002B Connector bridge
- D1554 Connector mini-bridge
- DD7002B Brel-Home box
- D1554 Brel Home USB plug
{% include integrations/config_flow.md %}
## Retrieving the API Key
@ -61,6 +73,9 @@ In the Brel Home app on Android go to the `me` page (home screen 4th tab), tap 5
The official Bloc Blinds app doesn't seem to hand out the API key on Android, it does seem to provide the API key on the iOS version of the official Bloc Blinds app.
### Connector app
Click the about page of the connector app 5 times to get the key ([iOS app](https://apps.apple.com/us/app/connector/id1344058317), [Android app](https://play.google.com/store/apps/details?id=com.smarthome.app.connector)).
## Top Down Bottom Up (TDBU) blinds
TDBU blinds consist of two bars controlled by two motors designated by Top and Bottom with fabric in between.

View File

@ -0,0 +1,31 @@
---
title: "Introducing the Home Assistant Creator Network!"
description: "We are looking to invest into our community and support the effort being put in."
date: 2022-04-29 00:00:00
date_formatted: "April 29, 2022"
comments: true
author: "Zack Barett"
categories: Community
og_image: /images/blog/2022-04-30-creator-network/CreatorNetwork_social.jpg
---
Hey Everyone! Today we are announcing our new program called the Home Assistant Creator Network! We are super excited to
start talking closely with creators to ensure everyone has the best information possible. We are looking to invest in our
community and support the effort being put into keeping our users informed. This is a way for Home Assistant to reward these
creators that are positively engaging with our users.
<p class='img'>
<img class="no-shadow" src='/images/blog/2022-04-30-creator-network/Creators.jpg' alt='Creators in the network'>
First Members of the Creator Network!
</p>
## What is the Creator Network?
The creator network will be a group of creators that are active and engaged with our community with consistent content that
builds the archive for Home Assistant. These creators are creating content for YouTube, Twitter, Instagram, TikTok, etc.
with the goal of helping people use Home Assistant. This can be through tutorials, unbiased product reviews, creating cool stuff and more.
We are looking forward to growing this network to be a group of creators that work together with each other and the Home Assistant Developers.
One of the biggest ways we are doing that is monthly calls with the network to discuss releases and upcoming changes.
Visit the [Home Assistant Creators Network](https://partner.home-assistant.io/creators/) for more information and how to apply.

View File

@ -1,193 +0,0 @@
"use strict";
/// <reference types="@google/local-home-sdk" />
/*
BASED ON: https://github.com/NabuCasa/home-assistant-google-assistant-local-sdk
Only removed the fart sound at the end.
For license information please check the repository.
*/
var App = smarthome.App;
var Constants = smarthome.Constants;
var DataFlow = smarthome.DataFlow;
var Execute = smarthome.Execute;
var Intents = smarthome.Intents;
var IntentFlow = smarthome.IntentFlow;
const findHassCustomDeviceDataByMdnsData = (requestId, devices, mdnsScanData) => {
let device;
device = devices.find((dev) => {
const customData = dev.customData;
return (customData &&
"webhookId" in customData &&
(!mdnsScanData.uuid || customData.uuid === mdnsScanData.uuid) &&
(!mdnsScanData.baseUrl || customData.baseUrl === mdnsScanData.baseUrl));
});
// backwards compatibility for HA < 0.109
if (!device) {
device = devices.find((dev) => dev.customData &&
"webhookId" in dev.customData);
}
if (!device) {
console.log(requestId, "Unable to find HASS connection info.", devices);
throw new IntentFlow.HandlerError(requestId, "invalidRequest", "Unable to find HASS connection info.");
}
return device.customData;
};
const findHassCustomDeviceDataByDeviceId = (requestId, devices, deviceId) => {
let device;
device = devices.find((dev) => {
const customData = dev.customData;
return (customData &&
"webhookId" in customData &&
customData.proxyDeviceId === deviceId);
});
if (!device) {
console.log(requestId, "Unable to find HASS connection info.", devices);
throw new IntentFlow.HandlerError(requestId, "invalidRequest", "Unable to find HASS connection info.");
}
return device.customData;
};
const createResponse = (request, payload) => ({
intent: request.inputs[0].intent,
requestId: request.requestId,
payload,
});
class UnknownInstance extends Error {
constructor(requestId) {
super();
this.requestId = requestId;
}
throwHandlerError() {
throw new IntentFlow.HandlerError(this.requestId, "invalidRequest", "Unknown Instance");
}
}
const forwardRequest = async (hassDeviceData, targetDeviceId, request) => {
const command = new DataFlow.HttpRequestData();
command.method = Constants.HttpOperation.POST;
command.requestId = request.requestId;
command.deviceId = targetDeviceId;
command.isSecure = hassDeviceData.httpSSL;
command.port = hassDeviceData.httpPort;
command.path = `/api/webhook/${hassDeviceData.webhookId}`;
command.data = JSON.stringify(request);
command.dataType = "application/json";
console.log(request.requestId, "Sending", command);
const deviceManager = await app.getDeviceManager();
let resp;
try {
resp = await new Promise((resolve, reject) => {
setTimeout(() => reject(-1), 10000);
deviceManager
.send(command)
.then((response) => resolve(response), reject);
});
// resp = (await deviceManager.send(command)) as HttpResponseData;
console.log(request.requestId, "Raw Response", resp);
}
catch (err) {
console.error(request.requestId, "Error making request", err);
throw new IntentFlow.HandlerError(request.requestId, "invalidRequest", err === -1 ? "Timeout" : err.message);
}
// Response if the webhook is not registered.
if (resp.httpResponse.statusCode === 200 && !resp.httpResponse.body) {
throw new UnknownInstance(request.requestId);
}
try {
const response = JSON.parse(resp.httpResponse.body);
// Local SDK wants this.
response.intent = request.inputs[0].intent;
console.log(request.requestId, "Response", response);
return response;
}
catch (err) {
console.error(request.requestId, "Error parsing body", err);
throw new IntentFlow.HandlerError(request.requestId, "invalidRequest", err.message);
}
};
const identifyHandler = async (request) => {
console.log("IDENTIFY intent:", request);
const deviceToIdentify = request.inputs[0].payload.device;
if (!deviceToIdentify.mdnsScanData) {
console.error(request.requestId, "No usable mdns scan data");
return createResponse(request, {});
}
if (!deviceToIdentify.mdnsScanData.serviceName.endsWith("._home-assistant._tcp.local")) {
console.error(request.requestId, "Not Home Assistant type");
return createResponse(request, {});
}
try {
const hassCustomData = findHassCustomDeviceDataByMdnsData(request.requestId, request.devices, deviceToIdentify.mdnsScanData.txt);
return await forwardRequest(hassCustomData, "", request);
}
catch (err) {
if (err instanceof UnknownInstance) {
return createResponse(request, {});
}
throw err;
}
};
const reachableDevicesHandler = async (request) => {
console.log("REACHABLE_DEVICES intent:", request);
const hassCustomData = findHassCustomDeviceDataByDeviceId(request.requestId, request.devices, request.inputs[0].payload.device.id);
try {
return forwardRequest(hassCustomData,
// Old code would sent it to the proxy ID: hassCustomData.proxyDeviceId
// But tutorial claims otherwise, but maybe it is not for hub devices??
// https://developers.google.com/assistant/smarthome/develop/local#implement_the_execute_handler
// Sending it to the device that has to receive the command as per the tutorial
request.inputs[0].payload.device.id, request);
}
catch (err) {
if (err instanceof UnknownInstance) {
err.throwHandlerError();
}
throw err;
}
};
const executeHandler = async (request) => {
console.log("EXECUTE intent:", request);
const device = request.inputs[0].payload.commands[0].devices[0];
try {
return forwardRequest(device.customData, device.id, request);
}
catch (err) {
if (err instanceof UnknownInstance) {
err.throwHandlerError();
}
throw err;
}
};
const queryHandler = async (request) => {
console.log("QUERY intent:", request);
const device = request.inputs[0].payload.devices[0];
try {
return await forwardRequest(device.customData, device.id, request);
} catch (err) {
if (err instanceof UnknownInstance) {
err.throwHandlerError();
}
throw err;
}
};
const app = new App("1.1.0");
app
.onIdentify(identifyHandler)
.onReachableDevices(reachableDevicesHandler)
.onExecute(executeHandler)
.onQuery(queryHandler)
// @ts-ignore
.onIndicate((req) => console.log("Indicate", req))
// @ts-ignore
.onParseNotification((req) => console.log("ParseNotification", req))
// @ts-ignore
.onProvision((req) => console.log("Provision", req))
// @ts-ignore
.onRegister((req) => console.log("Register", req))
// @ts-ignore
.onUnprovision((req) => console.log("Unprovision", req))
// @ts-ignore
.onUpdate((req) => console.log("Update", req))
.listen()
.then(() => {
console.log("Ready!");
})
.catch((e) => console.error(e));

View File

@ -7,7 +7,7 @@ The onboarding process takes care of the initial setup for Home Assistant, such
<div class='note'>
The steps below do not apply to Home Assistant Core installations, for those types of installations, [see here](/docs/configuration/).
The steps below do not apply to Home Assistant Core & Container installations, for those types of installations, [see here](/docs/configuration/).
</div>

View File

@ -29,11 +29,8 @@ Have you found an issue in your Home Assistant installation? Please report it. R
## Videos, talks, workshops and alike
- [PyconFR 2018 - Faire de la domotique libriste avec Python](https://www.youtube.com/watch?v=Eu6umBJ51I4) (French) ([Slides](https://hackmd.io/p/BJTSyDkqm)) - October 2018
- [Build your own smart home with Home Assistant](https://zmonkey.org/blog/files/Home%20Assistant%202018%20v1.0.pdf) at [OpenWest](https://openwest.org) - June 2018
- [Automate your home with Home Assistant](https://www.youtube.com/watch?v=SSrgi4iHGbs) at [foss-north 2018](https://foss-north.se/2018/speakers-and-talks.html#jparadies) - March 2018
- [Home Assistant - Smart Home für Jedermann](https://www.youtube.com/watch?v=74oPCh0NS4Y) (German) at [Pi and More 2018](https://piandmore.de/de/conference/pam10-5/schedule/event/305) ([Slides](https://benleb.de/talks/pam105_homeassistant.pdf)) - February 2018
- [Home Assistant](https://github.com/home-assistant/home-assistant-assets/tree/master/english/2017-qecampX) at QECampX 2017 - October 2017
- [Open Source Heimautomation mit Home Assistant](https://github.com/home-assistant/home-assistant-assets/tree/master/german/2017-maker-faire-zurich) at [Mini Maker Faire Zurich 2017](https://www.makerfairezurich.ch/en/) - September 2017
- [Why we can't have the Internet of Nice Things: A home automation primer](https://www.openwest.org/custom/description.php?id=92) at [OpenWest 2017](https://www.openwest.org) - July 2017
- [Home Automation with Home Assistant](https://github.com/jjmontesl/talk-hass-pydaygalicia2017) at [PyDay Galicia 2017](https://pyday2017.python-vigo.es/gl/) - June 2017
- [Home Automation with Python](https://www.youtube.com/watch?v=KNFZSSCPUyM) at [GLT 2017](https://glt17.linuxtage.at) - April 2017

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB