NOT MAINTAINED!
I'm no longer maintaining this repository!
That doesn't mean I don't use it, It just means this repository will not be maintained.
This app can be found in my appdaemon configuration.
You can still use the files ☝️, if you want.
These 👇 are the instructions.
AppDaemon Smart-Home skill for Alexa delivering Home Assistant's Climate entities as Thermostat endpoints.
This repository covers a couple of AppDaemon applications:
- Module Name:
ir_packets_control
Class Name:HandleMqttACUnit'</br> Handles the topics published by the MQTT HVAC component in Home Assistant,</br> The application will send the correct IR Packet to the configured IR Blaster (preferably
Broadlink`). - Module Name:
ir_packets_control
Class Name: `TemperatureSensorToMqtt'
Simple app for transforming state change events for a temperture sensor to mqtt messages for the climate entity,
Seeing that most Air-Conditioner units doesn't come with a built-in temperature sensor, we'll have to add it on-top (of course it is not mandatory, you can tweak the code a bit to disable this function). - Module Name:
smarthome_custom_ac
Class Name: `AlexaCustomAC'
This is the Smart-Home Skill backend. The class will register an API Endpoint in order to transform Home Assistant's MQTT HVAC component to Smart Thermostat Endpoints for Alexa.
This repository also introduces a couple AppDaemon global modules which I use throug out my code:
ir_packets_manager
is a module used by their_packats_control
module for holding the IR Packets.
Please Note: inside this module is where you will add you own IR Packets if you'll need to.little_helpers
holds the helper functions.alexa_request
used by thesmarthome_custom_ac
module, holds the different directive request objects.alexa_response_erros
used by thesmarthome_custom_ac
module, holds the different error response objects.alexa_response_success
used by thesmarthome_custom_ac
module, holds the different success response objects.
From Home Assistant point, AppDaemon is standing between the HVAC component and the Air Conditioner unit:
MQTT HVAC
publish mqtt messages >>
AppDaemon
picks up these messages and communicates them to Home Assistant
through it's REST API.
From Alexa's point, AppDaemon is standing between her and the Smart Thermostat Endpoint:
Alexa
will communicate to a designated Lambda function
>>
The Lambda function
will transfer the requests to AppDaemon
and the responses back to Alexa
>>
AppDaemon
will again communicate to Home Assistant
through it's REST API >>
Home Assistant
will act according to the previous flow and publish the mqtt messages to AppDaemon
.
I hope the makes sense, if not, I'll try to edit so it'll perhaps be clearer.
Anyways, I'm sure it'll make more sense as you go along with the guide.
- Home Assistant accessible from the outside your network.
- AppDaemon configured with both the HASS and the MQTT plugins.
- MQTT Broker I use Mosquitto
- IR Blaster preferably
Broadlink
connected to your Home Assistant environment. - Amazon Developer Account
- Amazon AWS Account
- ASK CLI configured and working. You can of course do it all via the various consoles, I prefer the cli. Follow this guide to familiarize yourself with
ask cli
. - OAuth 2.0 Auth-Code Infrastracture unless you host your own, you can just use Amazon's Security Profiles (it's built-in to the developer account anyway)
- Last but not least Infra-Red controlled Air-Conditioner unit
The following AC unit types are known and don't need any prior recording of the IR Packets,
If you're using any of the following units, you just saved yourself a lot of time.
If not... well, you'll have to aquire them before moving on with this guide.
There severl approaches for aquring the IR Packets, you might even find them online, but if you won't and you're using broadlink, I recommend NightRang3r's scripts.
- Electra Classic 35 type-name:
electra_classic_35
- Elco (I'm not what the actual model is, it's a small unit for the bedroom) type-name:
elco_small
If you do add your own packets (described later), please create a pull request commiting the updates, others might find it useful.
This part is pretty basic, just add an entity of mqtt
platform with the climate
component, MQTT HVAC:
- Please replace <thermostat_name> with the name of your ac unit (there are 5 recurrences).
- Please the
min_temp
and themax_temp
with your own unit's limitations. - Take note of the various mqtt topics, this is the way Home Assistant will communicate with AppDaemon.
- Restart your evnironment for the changes to take effect.
climate:
- platform: mqtt
name: "<thermostat_name>"
qos: 0
retain: false
send_if_off: false
initial: 25
current_temperature_topic: "tomerfi_thermostat/<thermostat_name>/current_temperature"
mode_command_topic: "tomerfi_thermostat/<thermostat_name>/mode"
modes:
- "off"
- "cool"
- "heat"
temperature_command_topic: "tomerfi_thermostat/<thermostat_name>/temperature"
fan_mode_command_topic: "tomerfi_thermostat/<thermostat_name>/fan"
fan_modes:
- "auto"
- "low"
- "medium"
- "high"
min_temp: 17
max_temp: 30
temp_step: 1
This section is better of splited to two sub-sections, the first one will cover the:
Home Assistant
>> AppDaemon
>> Home Assistant
>> IR Blaster
flow.
The second will cover the:
Alexa
>> Lambda
>> AppDaemon
>> Home Assistant
>> IR Blaster
flows.
Please configure both HASS and MQTT plugin for AppDaemon, here is the required configuration in <appdaemon_path>/appdaemon.yaml
, please change the <> values with your own:
appdaemon:
threads: 10
app_dir: <applications_path>
api_port: <api_access_port>
api_key: <api_password>
plugins:
HASS:
namespace: default
type: hass
ha_url: <home_assistant_url>
token: <long_lived_access_token>
MQTT:
namespace: mqtt
type: mqtt
verbose: false
client_host: <mqtt_server_name_ip>
client_port: <mqtt_server_name_port>
client_id: <mqtt_server_client_id>
client_user: <mqtt_server_user>
client_password: <mqtt_server_password>
Place the following modules from the repository in you <appdaemon_path>/<apps_path>/
:
- /appdaemon/apps/ir_packets_control
- /appdaemon/apps/ir_packets_manager
- /appdaemon/apps/little_helpers
The following modules need to be added only if you plan to use the Alexa skill part of the project, if not you can just skip the following modules: - /appdaemon/apps/alexa_request
- /appdaemon/apps/alexa_response_error
- /appdaemon/apps/alexa_response_success
- //appdaemon/apps/smarthome_custom_ac
ir_packets_manager
is the module managing the IR Packets. It's a simple module with a:
- A function-per-unit-type that returns a long dictionary containing the IR Packets (ie:
get_ir_dict_electra_classic_35()
).
If you'll need to add your own IR Packets, you'll need to create a new function exactly like the two existing ones. - A simple dictionary the translates the ac type name to the correct function (
ac_type_to_packet_func
).
If you'll need to add you own AC Type, you'll need to add akey-value
to this dict, containing the your new type name as key and the new function as value. - A function you don't need to worry about is
get_ac_packet(ac_type, mode, speed = None, temp = None)
, it's used internally to access the module.
You can see the full file here.
Here's a template for you IR Packets function, add your packets inside the quotation marks for the corresponding mode/fan/temp_x
key (note that this example is for a unit that supports 18-30 degrees temperature, you can add/subtract keys according to your unit type, just make sure to configure the same for the Home Assistant's component):
def get_ir_dict_your_ac_type():
return {
"off": "",
"cool" : {
"low" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
},
"medium" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
},
"high" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
},
"auto" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
}
},
"heat": {
"low" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
},
"medium" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
},
"high" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
},
"auto" : {
"temp_18": "",
"temp_19": "",
"temp_20": "",
"temp_21": "",
"temp_22": "",
"temp_23": "",
"temp_24": "",
"temp_25": "",
"temp_26": "",
"temp_27": "",
"temp_28": "",
"temp_29": "",
"temp_30": ""
}
}
}
Here is a template for the updated dictionary binding type name to function, the key is the type we use to configure the application, the value is the funcion you just created abobe this paragraph.
ac_type_to_packet_func = {
"elco_small": get_ir_dict_elco_small,
"electra_classic_35": get_ir_dict_electra_classic_35,
"your_ac_type_name": get_ir_dict_your_ac_type
}
After configuring Home Assistant's entity and gathering our IR Packets into the ir_packets_manager
module, we have an entity that publishes mqtt messages based on its activity, we now need to make AppDaemon catch these messages and instruct Home Assistant's API on what to do next with the correct IR Packet.
First, let's configure our applications in <appdaemon_path>/<apps_path>/apps.yaml>
:
- Please change
<thermostat_name>
with your unit's name - For
climate_entity
update the entity name you've created in the Home Assistant configuration section. - For
ir_send_service
update the name of you IR Blaster service. Please Note, if you're not usingBroadlink
, you should know that the application will send the IR Packet to the service as json with thepacket
key. - The
<thermostat_name>_control
application:- For
ac_type
update the type of you unit based on the previous section for aquiring the IR Packets. - For
default_mode_for_on
set the default mode of your unit, options are:heat
cool
- For
mode_command_topic
update the topic from you climate component'smode_command_topic
key. - For
temperature_command_topic
update the topic from you climate component'stemperature_command_topic
key. - For
fan_mode_command_topic
update the topic from you climate component'sfan_mode_command_topic
key.
- For
- The
temperature_sensor_to_mqtt
application:- For
sensor_entity
update with the full entity name of the sensor which holds the current temperature as its state. - For
topic
update the topic from you climate component'scurrent_temperature_topic
key. - The optional arguments
mode_entity_for_update
,temperature_entity_for_update
andfan_mode_entity_for_update
, are optional and used to change the state of any helpers you use for controlling the climate in order to keep your helpers in-sync with alexa's commands to the climate. Please Note, the state is change internally, no action will be taken by Home Assistant based on the state changed according to these option arguments.
- For
global_modules:
- ir_packets_manager
- little_helpers
- alexa_request #(ignore this if you don't plan on using Alexa)
- alexa_response_error #(ignore this if you don't plan on using Alexa)
- alexa_response_success #(ignore this if you don't plan on using Alexa)
<thermostat_name>_control:
module: ir_packets_control
class: HandleMqttACUnit
climate_entity: climate.entity_id
ir_send_service: switch.broadlink_send_packet_X
ac_type: "elco_small"
default_mode_for_on: "heat"
mode_command_topic: "tomerfi_thermostat/<thermostat_name>/mode"
temperature_command_topic: "tomerfi_thermostat/<thermostat_name>/temperature"
fan_mode_command_topic: "tomerfi_thermostat/<thermostat_name>/fan"
# the following are optional and in use only if you have any helper entities you need to keep in-sync with alexa's commands
mode_entity_for_update: input_select.input_select_controlling_operation_mode
temperature_entity_for_update: input_number.input_select_controlling_temperature_select
fan_mode_entity_for_update: input_select.input_select_controlling_fan_level
temperature_sensor_to_mqtt:
module: ir_packets_control
class: TemperatureSensorToMqtt
sensor_entity: sensor.nursery_broadlink_a1_temperature
topic: "tomerfi_thermostat/<thermostat_name>/current_temperature"
Restart your system and if everything was configured correctly, you can now use the climate entity
in Home Assistnat
and AppDaemon
will handle the rest.
If everything is working, please continue to the next section and configure Alexa's skill.
If you reached this part, you now have a fully working climate component
controlling your ac unit. Now we want to spice it up with some and create an API Endpoint
that will respond to Alexa's requests.
Add the following application configuration to your <appdaemon_path>/<apps_path>/apps.yaml
:
- For
entities
replace with you entity id from the Home Assistant's configuration section (multiple unit supported). - For
default_mode_for_on
set the default mode of your unit, options are:heat
cool
- For
scale
choose your scale in use, option are:CELSIUS
FAHRENHEIT
KELVIN
smarthome_custom_ac:
module: smarthome_custom_ac
class: AlexaCustomAC
entities:
- climate.entity_id
default_mode_for_on: "heat"
scale: "CELSIUS"
global_dependencies:
- alexa_requests
- alexa_response_error
- alexa_response_success
- little_helpers
That's it, you now have a working Smart-Home Alexa skill backend, ready to respond to request sent to:
https://<your_ha_ip_or_name>/api/appdaemon/AlexaCustomAC
Jump over to the next section for configuring your Alexa skill.
The skill is actually ready, you just need to configure it and deploy it to Alexa
and Lambda
servers.
The alexa
folder in the repository is the skill to be deployed:
.ask
holds the configuration for theask cli
end with details for the deployment..venv
is a python3 virtual environment created by thepost_new_hook_sh
script, detailed next.hooks/post_new_hook.sh
is the script executed by theask cli
right after aask new
command is issued, it's job is to create a python venv and install all the packages described inrequirements.txt
in order to make sure everything is going to work ok.
There's no need for you to useask new
in this project, the skill is already created, that's why the.venv
folder is included.hooks/pre_deploy_hook.sh
is the script executed by theask cli
for before the deployment based on theask deploy
command, its job it to create a folder and prepare it with all the code and the modules to be uploaded to lambda.lambda/lambda_func.py
is the lambda function for the skill, it will recieve requests from Alexa's servers and forward them to our newAppDaemon
API Endpoint, and of course transfer ourAppDaemon
responses back to Alexa's servers.
THIS IS THE ONLY FILE YOU NEED TO EDIT BEFORE DEPLOYMENTlambda/requirements.txt
is the python requirements file for the lambda required python modules.skill.json
is the skill configuration file.
Open the file /alexa/lambda/lambda_func.py
, updated your Home Assistant/AppDaemon url, save the the file and that's it. You're ready for deployment.
Please Note, as for AppDaemon 3.0.2 version, Legacy Password is requierd.
In future version, I think Andrew plans on implenting the Long-Lived Access Tokens methodology from Home Assistant, if so I'll update this repository accordingly, so please follow it for any future adjustments.
The text to be edited by you is, of course lose the less-then and greater-then characters:
api_url = "https://<your_ha_fqdn_and port>/api/appdaemon/AlexaCustomAC?api_password=<appdaemon_api_password>"
Place yourself in the same path as the .ask
folder, (which is inside the alexa
folder if you preserved the order of this repository) and type the following command:
ask deploy
That's it, your skill is deployed to both Alexa
and Lambda
servers.
For this stage, please prepare all of your chosen OAuth 2.0 service details.
If you don't have a OAuth 2.0 infrastructure at your disposal, I recommend using Amazon's Security Profile it's very simple and quick.
The redirect url for the configuration will be: https://pitangui.amazon.com/api/skill/link/M70Y38N3PTU2A.
After deploying your skill, you can now check the configuration file .ask/config
, you'll notice it's been updated with the details of your project.
Grab the skill id from the config file and run the following command:
ask api create-account-linking -s <your_skill_id>
This command will walk you through the proccess of configuring you account linking, configure it as follows:
- Authorization URL type your OAuth authorization url, add the
redirect_url
. If you're using Amazon's Security Profiles the value is: https://www.amazon.com/ap/oa/?redirect_url=https://pitangui.amazon.com/api/skill/link/M70Y38N3PTU2A - Client ID you OAuth client id.
- Scopes type
profile
- Domains leave blank or default
- Authorization Grant Type choose
AUTH_CODE
- Access Token URL type your OAuth access token url. If you're using Amazon's Security Profiles, the value is: https://api.amazon.com/auth/o2/token
- Client Secret type your OAuth client secret.
- Client Authentication Scheme choose
REQUEST_BODY_CREDENTIALS
Please Note, the ask api <subcommand>
tool is a direct access api to your skills, which means there's no need to re-deploy after using the ask api
tool, everything you do is done directly to your skills.