Examples

A fully working example for the Home Assistant integration can already be found in the designer repo. See the homeassistant_example.yaml in the example folder. To get that example working, you will also need to fill out the entries in ha_substitutions.yaml, following the directions in the comments. The configuration will automatically use those substitutions in the config.

Below are some examples from that file with a little more explanation than what is in the file. The substitution entities have also been changed for generic entity ids.

Calling Service Actions

Various elements will be set a tap_action to call predefined service when given an entity and no tap_action is set yet. For example, the Icon in the next section will already be configured to toggle light.livingroom. However, it may be desirable to call a service action from other elements, or call a different service action from an element. This can be done via the shorthand call-service-action. The data key of the action can then be set to the same yaml you’d use to call the service action from Home Assistant. The example below will allow a Button connected to a temperature sensor to toggle the livingroom light when tapped.

- type: Button
  entity: sensor.temperature
  tap_action:
    action: call-service-action
    data:
      action: light.toggle
      target:
        entity_id: light.livingroom

State Styles

The state_styles is relatively straight forward. If the entity’s state changed, these keys can be matched to a state, and the element’s properties will change accordingly. If the element has an entity_attribute set, the state is considered to be the value of that attribute. It can be used to show the state of a light, for example.

- type: Icon
  background_color: black
  background_shape: circle
  entity: light.livingroom
  state_styles:
    "on":
      icon: mdi:lightbulb
      icon_color: white
    "off":
      icon: mdi:lightbulb-off
      icon_color: gray

state_styles can also be made conditional by setting state_conditionals to true. In here, state is the variable matching the value of the entities state or linked attribute.

- type: Button
  entity: input_number.counter
  id: button-style
  state_conditionals: true
  state_styles:
    "default": "Eh"
    "state > 2": "That's Something"
    "state < -2": "This is even less than eh"

Attribute Styles

attribute_styles are similar to state_styles, just a lot more flexible (and consequently, more complex to use). They are applied in order, so if multiple conditions evaluate to true, the properties that are updated will take on the last value from a true condition. The styles are supplied as a list. The attribute key specifies the entity’s attribute to check, with state being a special value to use the state instead of an attribute. Under the states key, you can define a list of conditions that will be checked, via the same logic as the state_styles example above. An else key can also be provided, which specifies the element properties to apply if none of the conditions evaluate to true.

- type: Button
  entity: weather.home
  state_conditionals: true
  attribute_styles:
    - attribute: temperature
      states:
        - state: state > 19
          properties:
            background_color: green
        - state: state < 7.5
          properties:
            background_color: gray
      else:
        background_color: white
    - attribute: state
      states:
        - state: "'rain' in state"
          properties:
            font_color: steelblue
        - state: "'sun' in state"
          properties:
            font_color: yellow
      else:
        font_color: black

Trigger Functions

Currently it is not possible yet to give elements a custom trigger function, however entities can be given one. A trigger function takes two arguments, a trigger, which is a dict holder the trigger data, and the client, which is the object managing the connection to Home Assistant. The example below will simply print the last time a button was pressed when inkBoard starts. However, in the full example file, this example is expanded upon to also allow showing a popup when the button is pressed. In general, I would advise taking a look at the full example, as it shows a lot of the API features not available in the YAML config.

entities:
  - entity_id: input_button.my_button
      trigger_functions:
        - function: custom:custom_trigger
          call_on_connect: true
from inkBoarddesigner.integrations.homeassistant_client import client

def custom_trigger(trigger: "client.triggerDictType", client: "client.HAclient"):
    """A simple function to show how to work with trigger functions for home assistant entities.
    """

    entity = trigger["entity_id"]
    new_state = trigger["to_state"]["state"]

    if trigger["from_state"] == None:
        ##from_state is none if the client connected, as it does not gather the previous state of the entity,
        ## just the current state.
        print(f"Entity {entity} is in state {new_state}")

Tip

If you want to access the state of other entities, you can use client.stateDict, which is a dict the ids of all subscribed entities and their last received state.

As a quick reference, here is the full custom_trigger function from custom_functions.py.

A custom trigger to open a popup
 1def custom_trigger(trigger: "client.triggerDictType", client: "client.HAclient"):
 2    """A simple function to show how to work with trigger functions for home assistant entities.
 3
 4    Parameters
 5    ----------
 6    trigger : client.triggerDictType
 7        The full element trigger. Contains the to_state, from_state, amongst others.
 8    client : client.HAclient
 9        The client object managing the connection to Home Assistant.
10    """
11    
12    entity = trigger["entity_id"]
13    new_state = trigger["to_state"]["state"]
14
15    if trigger["from_state"] == None:
16        ##from_state is none if the client connected, as it does not gather the previous state of the entity, just the current state.
17        print(f"Entity {entity} is in state {new_state}")
18    else:
19        ##Although it prints it like this, keep in mind the function is triggered regardless of what triggered it.
20        ##I.e. it can also be the case that the trigger was caused by an attribute changing.
21        from_state = trigger["from_state"]["state"]
22
23        popup: PopupMenu = CORE.screen.elementRegister["trigger-popup"]
24
25        ##Since we call update later on, the title can be set like this.
26        ##Otherwise, this can be done like this too, however, a call to update is required with updated=True passed.
27        popup.title = trigger["to_state"]["attributes"].get("friendly_name","My Button")
28
29        press_now = dt.fromisoformat(new_state)
30        press_before = dt.fromisoformat(from_state)
31        press_dt = press_now - press_before
32
33        button_text = f"You pressed {entity} again after {press_dt.total_seconds()} seconds at {press_now}"
34        buttonButton = Button(button_text, multiline=True)
35        buttonIcon = Icon("mdi:gesture-tap-button", icon_color="homeassistant")
36
37        subsc_num = len(client.stateDict)
38        subscr_text = f"Subscribed to {subsc_num} entities"
39        subscrButton = Button(subscr_text, multiline=True)
40        subscrIcon = Icon("homeassistant", icon_color="homeassistant")
41
42        menulayout = GridLayout([buttonIcon,buttonButton, subscrIcon, subscrButton], column_sizes=["r", "?"], columns=2, rows=None)
43
44        popup.update({"menu_layout": menulayout})
45
46
47        popup.show()
48
49    return

Custom Element

Custom elements can be made similarly as via regular custom elements. It is useful to import the HAElement as a baseclass, as it provides the functionality for the entity property, state_styles, etc. Otherwise, the element needs to be given a trigger_function in addition to the usual required methods.