Send command to device only when needed

Is there an easy way to send a command to a device only if it would result in a change? My specific use case is motorized blinds. I only want to send the command to change position if they aren’t already in the requested position.

The reason for that is the DC adapter it uses is whiny when the motor is processing and the automation runs while we’re watching tv (so the noise is irritating).

Current automation:

alias: Blinds - Greatroom West - Master Controller
description: ''
trigger:
  - platform: sun
    event: sunset
    offset: '00:60:00'
  - platform: state
    entity_id: input_boolean.auto_blinds_greatroom_west
    to: 'on'
  - platform: state
    entity_id: input_boolean.dark_outside
  - platform: state
    entity_id: sun.sun
    attribute: elevation
  - platform: device
    device_id: 3b0f9db703b143d6951c21fbb8b63255
    domain: media_player
    entity_id: media_player.denon_avr_s720w
    type: turned_off
    for:
      hours: 0
      minutes: 2
      seconds: 0
      milliseconds: 0
  - platform: device
    device_id: 3b0f9db703b143d6951c21fbb8b63255
    domain: media_player
    entity_id: media_player.denon_avr_s720w
    type: turned_on
  - platform: sun
    event: sunrise
  - platform: state
    entity_id: media_player.shield_living_room
condition:
  - condition: state
    entity_id: input_boolean.auto_blinds_greatroom_west
    state: 'on'
action:
  - choose:
      - conditions:
          - condition: or
            conditions:
              - condition: sun
                after: sunset
                after_offset: '00:55:00'
              - condition: sun
                before: sunrise
        sequence:
          - device_id: 7808f9da3c1f435e838acf6b36f23352
            domain: cover
            entity_id: cover.blinds_greatroom_west
            type: set_position
      - conditions:
          - condition: state
            entity_id: input_boolean.dark_outside
            state: 'on'
        sequence:
          - device_id: 7808f9da3c1f435e838acf6b36f23352
            domain: cover
            entity_id: cover.blinds_greatroom_west
            type: set_position
            position: 100
      - conditions:
          - condition: numeric_state
            entity_id: sun.sun
            attribute: elevation
            above: '2.6'
            below: '75'
          - condition: numeric_state
            entity_id: sun.sun
            attribute: azimuth
            above: '190'
          - condition: or
            conditions:
              - condition: state
                entity_id: binary_sensor.outside_hot
                state: 'true'
              - condition: device
                device_id: 3b0f9db703b143d6951c21fbb8b63255
                domain: media_player
                entity_id: media_player.denon_avr_s720w
                type: is_on
              - condition: state
                state: playing
                entity_id: media_player.shield_living_room
        sequence:
          - device_id: 7808f9da3c1f435e838acf6b36f23352
            domain: cover
            entity_id: cover.blinds_greatroom_west
            type: set_position
    default:
      - device_id: 7808f9da3c1f435e838acf6b36f23352
        domain: cover
        entity_id: cover.blinds_greatroom_west
        type: set_position
        position: 100
mode: single

A numeric state condition can do that if you are using an automation to send the commands.

I don’t understand what you mean in this case. I attached the automation code to the initial post to hopefully better show what I’m working with.

I mean if you know what you are going to set the blinds to, check and see if they are already in that state as a condition of the action. Like this:

          - condition: not
            conditions: 
              - condition: state
                entity_id: cover.blinds_greatroom_west
                attribute: position
                state: #[to_state_here]

I would have filled out the to_state but you seem to not be setting the state correctly in your actions. There is no position to set here:

        sequence:
          - device_id: 7808f9da3c1f435e838acf6b36f23352
            domain: cover
            entity_id: cover.blinds_greatroom_west
            type: set_position

So I have no idea what to set it to.

The automation was configured using the visual editor instead of yaml. In the case where there is no position provided it goes to 0.

I started down the not already in position approach but was delayed by the having a default choice of going to open. That’s when I started wondering if there was a config thing I’m missing.

I ended up writing a script to help with this

alias: Smart Blind Control
description: Only send command to device if needed
fields:
  entity_id:
    name: Control entity
    description: Entity to control
    selector:
      entity: null
  position:
    name: Desired position
    description: Desired position for blinds
    selector:
      number:
        min: 0
        max: 100
sequence:
  - service: logbook.log
    data:
      name: Smart blind control
      message: '{{ entity_id }} - {{ position }}'
      entity_id: '{{ entity_id }}'
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ state_attr(entity_id, "current_position") != position }}'
        sequence:
          - service: cover.set_cover_position
            target:
              entity_id: '{{ entity_id }}'
            data:
              position: '{{ position }}'
    default: []
mode: single
icon: mdi:brain

Then it gets called from the automation instead of the cover.set_cover_position service

      - service: script.smart_blind_control
        data:
          position: 100
          entity_id: cover.blinds_greatroom_west