Integration for Home Assistant for the Crestron XSIG symbol
Currently supported devices:
- Lights
- Thermostats
- Shades
- Binary Sensor
- Sensor
- Switch
- Media Player
- Add the
crestrondirectory toconfig/custom_components - Add the appropriate sections to
configuration.yaml(see below) - Add a
crestron:block to the root of yourconfiguration.yaml- The component acts as a TCP server, so you must specify the port number to listen on using the
port:parameter.
- The component acts as a TCP server, so you must specify the port number to listen on using the
- Restart Home Assistant
If you would like to separate the instances of this integration (for example, to use across multiple Crestron processor slots), you may achieve this by duplicating this component in Home Assistant.
- Add the
crestroncomponent as above - Duplicate the component folder in
custom_componentswith a new name (e.g.crestron_audio) - Edit
manifest.jsonto change the domain the match the folder name - Edit
const.pyto change the domain to match the folder name - Add a block for the new domain in your
configuration.yaml- Note: You must use a different port than for the original integration
- Follow the steps below on your Crestron processor to set up a new TCP/IP client and XSIG(s)
At the end your configuration.yaml should look something like this:
crestron:
port: 8000
crestron_audio:
port: 8001And make sure when defining new devices you specify the correct platform
light:
- platform: crestron # Communicates over port 8000
media_player:
- platform: crestron_audio # Communicates over port 8001I've also created a script to automate this process as it can become a bit cumbersone and source can easily become out of sync. The gist can be found here.
- Add a TCP/IP Client device to the control system
- Configure the client device with the IP address of Home Assistant
- Set the port number on the TCP/IP client symbol to match what you have configured for
port:inconfiguration.yaml - Wire up logic to the
Connectsignal of your TCP/IP client (or just set it to1to have it connected all the time) - Add an "Intersystem Communication" symbol (quick key = xsig).
- Connect the TX & RX of the XSIG symbol to the TCP/IP Client.
- Attach your Analog, Serial and Digital signals to the input/output joins.
- Note you can use multiple XSIGs attached to the same TCP/IP Client serials. I found its simplest to use one for digitals and one for analogs/serials to keep the numbering simpler (see below).
Caution: Join numbers can be confusing when mixing analog/serials and digtals on the same XSIG symbol. Even though the symbol starts numbering the digitals at "1", the XSIG will actually send the join number corresponding to where the signal appears sequentially in the entire list of signals. For example, if you have 25 analog signals followed by 10 digital signals attached to the same XSIG, the digitals will be sent as 26-35, even though they are labeled 1 - 10 on the symbol. You can either account for this in your configuration on the HA side, or just use one symbol for Analogs and another for Digitals. Since the XSIG lets you combine Analog/Serial joins on the same symbol, you can have one XSIG for Analog/Serial joins and another for digitals. This keeps the join numbering simple.
The crestron: entry is mandatory as is the port: definition under it. So at a minimum, you will need:
crestron:
port: 16384Then, if you want to make use of the control surface (touchpanels/kepads) syncing capability, you will need to add either a to_joins, a from_joins section, or both (see below).
Finally, add entries for each HA component/platform type to your configuration.yaml for the appropriate entity type in Home Assistant:
| Crestron Device | Home Assistant component type |
|---|---|
| Light | light |
| Thermostat | climate |
| Shades | cover |
| read-only Digital Join | binary_sensor |
| read-only Analog Join | sensor |
| read-write Digital Join | switch |
| Audio/Video Switcher | media_player |
To be clear: if you configure multiple platforms (light, cover, climate, ...) plus synchronization in both directions, your configuration.yaml will look something like:
crestron:
port: 32768
to_joins:
...
from_joins:
...
light:
- platform: crestron
...
climate:
- platform: crestron
...
cover:
- platform: crestron
...
binary_sensor:
- platform: crestron
...
sensor:
- platform: crestron
...
switch:
- platform: crestron
...
media_player:
- platform: crestron
...This platform supports monochromatic "brightness" type lights (basically, anything that can have its brightness represented by an analog join on the control system). I tested this with a CLX-1DIM8 panel and multiple CLW-DIMEX switches.
light:
- platform: crestron
name: "Dummy Light"
brightness_join: 9
type: brightness- name: The entity id will be derived from this string (lower-cased with _ for spaces). The friendly name will be set to this string.
- brightness_join: The analog join on the XSIG symbol that represents the light's brightness.
- type: The only supported value for now is brightness. TODO: add support for other HA light types.
This platform should work with anything that looks like a CHV-TSTAT/THSTAT (analog joins for heat, cooling setpoints, digital joins for modes, fan modes, and relay states). I tested this with multiple CHV-TSTAT and CHV-THSTATs.
TODO: Add support for humidity control on CHV_THSTAT.
climate:
- platform: crestron
name: "Upstairs Thermostat"
heat_sp_join: 2
cool_sp_join: 3
reg_temp_join: 4
mode_heat_join: 1
mode_cool_join: 2
mode_auto_join: 3
mode_off_join: 4
fan_on_join: 5
fan_auto_join: 6
h1_join: 7
h2_join: 8
c1_join: 9
fa_join: 10- name: The entity id will be derived from this string (lower-cased with _ for spaces). The friendly name will be set to this string.
- heat_sp_join: analog join that represents the heat setpoint
- cool_sp_join: analog join that represents the cool setpoint
- reg_temp_join: analog join that represents the room temperature read by the thermostat. The CHV-TSTAT calls this the "regulation temperture" because it my be derived from averaging a bunch of room temperature sensors. This is so called because it is the temperature used by the thermostat to decide when to make calls for heating or cooling.
- mode_heat_join: digital feedback (read-only) join that is high when the thermostat is in heating mode
- mode_heat_join: digital feedback (read-only) join that is high when the thermostat is in cooling mode
- mode_auto_join: digital feedback (read-only) join that is high when the thermostat is in auto mode
- mode_off_join: digital feedback (read-only) join that is high when the thermostat mode is set to off
- fan_on_join: digital feedback (read-only) join that is high when the thermostat fan mode is set to (always) on
- fan_on_join: digital feedback (read-only) join that is high when the thermostat fan mode is set to auto
- h1_join: digital feedback (read-only) join that represents the state of the stage 1 heat relay
- h2_join: digital feedback (read-only) join that represents the state of the stage 2 heat relay
- c1_join: digital feedback (read-only) join that represents the state of the stage 1 cool relay
- fa_join: digital feedback (read-only) join that represents the state of the stage fan relay
This should work with any shade that uses an analog join for position plus digital joins for is_opening/closing, is_closed and stop. I tested with CSM-QMTDC shades.
cover:
- platform: crestron
name: "Living Room Shades"
type: shade
pos_join: 26
is_opening_join: 41
is_closing_join: 42
stop_join: 43
is_closed_join: 44- name: The entity id will be derived from this string (lower-cased with _ for spaces). The friendly name will be set to this string.
- pos_join: analog join that represents the shade position. The value follow the typical definition for a Crestron analog shade (0 = closed, 65535 = open).
- is_opening_join: digital feedback (read-only) join that is high when shade is in the process of opening
- is_closing_join: digital feedback (read-only) join that is high when shade is in the process of closed
- is_closed_join: digital feedback (read-only) join that is high when shade is fully closed
- stop_join: digital join that can be pulsed high to stop the shade opening/closing
This can represent any read-only digital signal on the control system. I typically comment out the "in" signals on the XSIG symbol to keep the "in" and "out" signals lined up.
binary_sensor:
- platform: crestron
name: "Air Compressor"
is_on_join: 57
device_class: power- name: The entity id will be derived from this string (lower-cased with _ for spaces). The friendly name will be set to this string.
- is_on_join: digital feedback (read-only) join to represent as a binary sensor in Home Assistant
- device_class: any device class supported by the binary_sensor integration. This mostly affects how the value will be expressed in various UIs.
This can represent any read-only analog signal on the control system. I typically comment out the "in" signals on the XSIG symbol to keep the "in" and "out" signals lined up. Remember that an analog join on the control system is a 16-bit value that can range from 0-65535. So for many symbol types (especially those representing a brightness or percent) you will need to make use of the divisor: parameter.
Example divisors:
- For sensors that return 10ths of a degree: 10
- For joins that represent a percent: 655.35 (to convert the 1-65535 range to 1-100)
sensor:
- platform: crestron
name: "Outside Temperature"
value_join: 1
device_class: "temperature"
unit_of_measurement: "F"
divisor: 10- name: The entity id will be derived from this string (lower-cased with _ for spaces). The friendly name will be set to this string.
- value_join: analog join to represent as a sensor in Home Assistant
- device_class: any device class supported by the sensor integration. This mostly affects how the value will be expressed in various UIs.
- unit_of_measurement: Unit of measurement appropriate for the device class as documented here.
- divisor: (optional) number to divide the analog join by to get the correct sensor value. For example, a crestron temperature sensor returns tenths of a degree (754 represents 75.4 degrees), so you would use a divisor of 10. Defaults to 1.
This could represent any digital signal on the contol system that you want to be able to control/view from HA.
switch:
- platform: crestron
name: "Dummy Switch"
switch_join: 65
pulsed: False- name: The entity id will be derived from this string (lower-cased with _ for spaces). The friendly name will be set to this string.
- switch_join: digital join to represent as a switch in Home Assistant
- pulsed: indicates whether the switch is toggled by a signal pulse, or that it switches by providing the requested state.
Use media_player to represent the output of a multi-zone switcher. For example a PAD-8A is an 8x8 (8 inputs x 8 outputs) audio switcher. This can be represented by 8 media player components (one for each output). The component supports source selection (input selection) and volume + mute control. So it is modeled as a "speaker" media player type in Home Assistant.
Source selection can use either one analog join containing a source number, or one digital join per source. Configure one method for each media player, not both.
For analog source selection, use the existing source_number_join and sources options:
media_player:
- platform: crestron
name: "Kitchen Speakers"
power_on_join: 25
power_off_join: 26
mute_join: 27
volume_join: 19
source_number_join: 13
sources:
1: "Android TV"
2: "Roku"
3: "Apple TV"
4: "Chromecast"
7: "Volumio"
8: "Crestron Streamer"
default_source: 3For digital source selection, map each digital join to its source name. A high signal provides source feedback, and selecting a source pulses its join:
media_player:
- platform: crestron
name: "Kitchen Speakers"
power_on_join: 25
power_off_join: 26
mute_join: 27
volume_join: 19
source_digital_joins:
10: "Sonos"
11: "XM"
12: "FM"
default_source: 10- name: The entity id will be derived from this string (lower-cased with _ for spaces). The friendly name will be set to this string.
- power_on_join: digital feedback that represents the state of the audio zone's power. The same join is pulsed when turning the zone on.
- power_off_join: digital join that represents the power off button of the audio zone. The signal will be pulsed.
- mute_join: digital join that represents the mute state of the channel. The signal is pulsed when Home Assistant requests a mute change.
- volume_join: analog join that represents the volume of the channel (0-65535).
- source_number_join: for analog source selection, the analog join that represents the selected input for the output channel.
- sources: for analog source selection, a dictionary mapping each source number to the name shown in Home Assistant. Selecting a source writes its number to
source_number_join. - source_digital_joins: for digital source selection, a dictionary mapping each digital join to the name shown in Home Assistant. A high join identifies the current source, and selecting a source pulses that join for 50 ms. If no configured join is high, the current source is unknown.
- default_source: optional source key to select after powering on. Use the analog source number with
sources, or the digital join number withsource_digital_joins.
The deprecated source_default spelling remains accepted for compatibility; new configurations should use default_source.
If you have Crestron touch panels or keypads, it can be useful to keep certain feedback/display joins in sync with Home Assistant state and to be able to invoke Home Assistant functionality (via a script) when a button is pressed or a join changes. This functionality was added with v0.2. There are two directions to sync: from HA states to control system joins and from control system joins to HA (using scripts).
There are two sections in configuration.yaml under the root crestron: key:
to_joinsfor syncing HA state to control system joinsfrom_joinsfor invoking HA scripts when control system joins change
crestron:
port: 5555
to_joins:
...
from_joins:
...The to_joins section will list all the joins you want to map HA state changes to. For each join, you list either:
- a simple
entity_idwith optionalattributeto map entity state directly to a join. - a
value_templatethat lets you map almost any combination of state values (including the full power of template logic) to the listed join.
crestron:
port: 12345
...
to_joins:
- join: d12
entity_id: switch.compressor
- join: a35
value_template: "{{value|int * 10}}"
- join: s4
value_template: "Current weather conditions: {{state('weather.home')}}"
- join: a2
entity_id: media_player.kitchen
attribute: volume_level
- join: s4
value_template: "http://homeassistant:8123{{ state_attr('media_player.volumio', 'entity_picture') }}"- to_joins: begins the section
- join: for each join, list the join type and number. The type prefix is 'a' for analog joins, 'd' for digital joins and 's' for serial joins. So s32 would be serial join #32. The value of this join will be set to either the state/attribute of the configured entity ID or the output of the configured template.
- entity_id: the entity ID to sync this join to. If no attribute is listed the join will be set to entity's state value whenever the state changes.
- attribute: use the listed attribute value for the join value instead of the entity's state.
- value_template: used instead of entity_id/attribute if you need more flexibility on how to set the value (prefix/suffix or math operations) or even to set the join value based on multiple entity IDs/state values. You have the full power of HA templating to work with here.
Note that when you specify an
entity_id, all changes to that entity_id will result in a join update being sent to the control system. When you specify avalue_templatea change to any referenced entity will trigger a join update.
The from_joins section will list all the joins you want to track from the control system. When each join changes the configured functionality will be invoked.
crestron:
port: 54321
...
from_joins:
- join: a2
script:
service: input_text.set_value
data:
entity_id: input_text.test
value: "Master BR temperature is {{value|int / 10}}"
- join: d35
script:
service: media_player.media_previous_track
data:
entity_id: media_player.volumio
- join: d36
script:
service: media_player.media_play_pause
data:
entity_id: media_player.volumio
- join: d37
script:
service: media_player.media_next_track
data:
entity_id: media_player.volumio
- join: d74
script:
service: media_player.select_source
data:
entity_id: media_player.volumio
source: "{{state_attr('media_player.volumio', 'source_list')[0]}}"
- join: d75
script:
service: media_player.select_source
data:
entity_id: media_player.volumio
source: "{{state_attr('media_player.volumio', 'source_list')[1]}}"
- join: d76
script:
service: media_player.select_source
data:
entity_id: media_player.volumio
source: "{{state_attr('media_player.volumio', 'source_list')[2]}}"- from_joins: begins the section
- join: for each join, list the join type and number. The type prefix is 'a' for analog joins, 'd' for digital joins and 's' for serial joins. So s32 would be serial join #32. Any change in the listed join will invoke the configured behavior.
- script: This is a standard HA script. It follows the HA scripting sytax.