Home Assistant component "design patterns"?

When adding support for a new device that exposes some attributes/methods, is there any design pattern or “standard way” for implementing this in HA, for example when it comes to how the user should configure the new device?

Let’s assume we have an online GPS-enabled coffee maker with attributes: position, water_level, coffee_strength, power_on. This device could expose sensors for water_level and coffee_strength, a binary sensor for power_on and a device tracker for the position to the user, (as well as a service coffee_maker.turn_on/turn_off?).

Variant 1a - Autodiscover and add everything

coffee_maker:
  username: user
  password: pass
  # all available sensors automatically discovered and added to the UI
  # can a device_tracker be autodiscovered btw?

Variant 1b - Autodiscover but only add sensors for the attributes as specified by the user in the configuration:

coffee_maker:
  username: user
  password: pass
  sensors:
  # optional list of sensors to be added
  # if present, only add sensors for the attributes present
    - water_level
    - coffee_strength
    - position

Variant 1c - Add the device tracker separately because it can not currently be auto discovered (?)

coffee_maker:
  username: user
  password: pass
  # available sensors autodiscovered

device_tracker:
- platform: coffee_maker  # hooks into the same coffee_maker component

Variant 2 - User has to configure each platform individually

coffee_maker: # shared configuration
  username: user
  password: pass

sensor:
  platform: coffee_maker
  monitored_condition:
    - water_level
 
binary_sensor:
  platform: coffee_maker
  monitored_condition:
    - power_on

Variant 3 - Only expose one main attribute for the device as a single sensor and put all other device attributes as device_state_attributes. The user can expose other attributes as sensors using template sensors.

sensor:
  - platform: coffee_maker # displays water_level by default
    username: user
    password: pass
  - platform: template
    sensors:
      coffee_level:
        value_template: {{ ... states.sensor.coffee_maker.coffee_level ... }}

Personally, I would prefer 1a/b, with sensible defaults, which would require the minimum level of changes to configuration.yaml.

I don’t have any problems accepting “there is no standard way - it’s up to the implementer to decide what method is the most approprote” as an answer :slight_smile:

(please ignore any YAML syntax errors in the examples above - it’s only for illustrating the concept)

2 Likes

So it is. It’s sub-optimal but most developers have their own preferences and enforcing a way to do things is a limitation.

Personally I often use “Variant 3” for new platforms/components. Why? Because the implementation is pretty straight-forward, no docs update is needed if there are more values exposed, and issues with too-many-api-call can be avoided. The configuration effort is almost the same as “Variant 1b” but with more flexibility.

My Rules of thumbs:

  • If it’s possible to share stuff, create a component.
  • Do auto discovery.
  • Does it make sense to expose this values as state or should it be an attribute.
  • Is it likely that people want different units of measurement.

Thank you. I agree, Variant 3 is simple and straight-forward when implementing, and also leaves most room for personal customization. Variant 1 could make it easier for new (unexperienced) users to discover available sensors, but would potentially also clutter/spam the UI and requiring manual disabling of unwanted components.