Automation with real code (not YAML)

Sorry, English is not my native language and I never used this abbreviation before.

Almost. I found more difficult to change brightness, than turn lights on and off. So let is change a little bit:

  1. There are 8 bulbs (bulb1, bulb2, bulb3, bulb4, bulb5, bulb6, bulb7, bulb8)
  2. There are 4 switches (sw1, sw2, sw3, sw4)
  3. Sw1 adds a light to those currently on (in sequence so if 1 and 2 are on, the next would be 3)
  4. Sw2 removes a light from those currently on but in reverse order (so 1,2,3 on sw3 leaves just 1,2)
  5. Sw3 decrees brightness of lights currently on (ie, if 1,2,3 are on and are at 70% brightness, then lights 1,2,3 brightness become 60%)
  6. Sw4 increeses brightness of lights currently on (ie, if 1,2,3 are on and are at 70% brightness, then lights 1,2,3 brightness become 80%)

Here is example how it can be done in pseudocode, if it will help you:

class LivingRoomLights(){
    
    string[] lights = ["bulb1", "bulb2", "bulb3", "bulb4", "bulb5", "bulb6", "bulb7", "bulb8"];
    int currentAmount = 8;

    Initialize(Switch switch){
        switch.OnButton1 += IncreseAmount;
        switch.OnButton2 += DecreesAmount;
        switch.OnButton3 += IncreseBrightness;
        switch.OnButton4 += DecreesBrightness;
    }

    void IncreseAmount(){
        if (currentAmount < 8)
        {
            currentAmount++;
            UpdateLights(0);
        }
    }
    void DecreesAmount(){
        if (currentAmount > 0)
        {
            currentAmount--;
            UpdateLights(0);
        }
    }
    void IncreseBrightness(){
        UpdateLights(10);
    }
    void DecreesBrightness(){
        UpdateLights(-10);
    }

    void UpdateLights(int additionalBrightness){
        for (int i = 0; i < lights.length; i++)
        {
            Light light = HomeAssistant.GetLight(lights[i]);
            if (i <= currentAmount)
            {
                light.SetBrightness(light.currentBrightness + additionalBrightness);
            }else{
                light.TurnOff();
            }
        }
    }
}

Code is not optimized, it is just for demonstration purposes.

P.S.

No, it is pretty simple. Those lights can blink different colors. I checked. But I feel it will be almost impossible write game in YAML

I really like your idea of dynamic scenes and groups! It sound as nice and simple workaround for changing amount of lights!
Do you have similar idea for the game?

Updating brightness of lights turned off is impossible with built in light integration. Also not all lights/bulbs are enabled to do so.

Considering you own bulbs which support such feature the only way is to communicate with them directly, using their api (http, mqtt whatever else is supported)

Just a reminder

I understand about brightness of turned off lights. But what about workaround advised by @petro? Dynamically change not light brightness, but light brightness in the scene? And then, instead of turning on light, turning on this scene, which will turn light on the correct brightness?

Btw, it is just thinking about possibilities. Automation from topic (changing amount and brightness of lights) dose not require changing brightness of turned off lights.

1 Like

So to get ALL the lights on youā€™d be willing to flip the switch 8 times ???
And the same to get them off ??? This seems very unwieldly with a WAF of 0 (Hell, it has a MeAF of 0)

I believe Hue Bulbs can be set to colour cycle (@Burningstone (who has experience of this) for a fact check here, can you read the bulb during this process ?)
Not sure about ā€˜blinkingā€™ is this a random pattern ? peculiar to Yeelight ? through HA or only Through their App ? Can you read the bulb attributes when in this state (or do you set it to that state) ? What are we looking for - a match to 255, 0, 0 ??? Do you know what the other colours are ? How many (just 3, 6, 12 ??? ie where on the colour wheel are they ?

Re:The brightness - most bulbs donā€™t work well at low brightness values
All mine are Ikea Ledare - some models/ratings run down as low as 6% others need 19% Are you sure you can get as low as 10% (we can do whatever - just checking)

I tend to write pseudo code in ā€˜basicā€™ style, less non technical people get confused that way so its actually easier to be clear and specific this actually looks like ā€¦ Java ?

Extra Note : I donā€™t like scenes, Donā€™t use them, If I want something to change, I change the automation that sets it, that way itā€™s easy to tweak and to set sequences and pauses on stepped changes.

Ten programmers will write this 10 different ways, Teras will write it his way and I will write it mine, they will be completely different, and the code I tend to post on the forum will be as basic as possible to allow others to learn (as generally Iā€™m only half a page ahead in the text book to the newbies :rofl:). I will leave the scenes to petroā€™s tender mercies :smiley:

Nearly there to start writing code

Edit2:

Stop saying that, tell me how the hardware works, how itā€™s controlled from HA and Iā€™ll write the code

Of coursenot. I just dose not see the point to ask about things I already know. Double-presses, triple-presses or different switches can be used for that. If it is really important to you, not to just show, how it can be done, but to make useful automation, you can add sw5 and sw6 there for turning on and off all selected lights. But I donā€™t see point in wasting extra time on it.

Sorry, I donā€™t know what those abbreviations mean.

Are those questions related to Game? I will look into it, but most of your questions sound unnecessary:

Any random answer to this question will not change logic of automation. Let it be just Red, Green and Blue lights. It is simplest case for making example.

My last project was made with .Net Core + React. Since it dose not look like JavaScript, I can bet my brain took inspiration from C#.

Nearly? What else you want to know for changing amount of lights? I will answer any questions.

Ok, I will find how itā€™s controlled by Home Assistant (and what exactly this question implys) and write it to you.

I like to know that I know all there is to know about an application before getting to roll my sleeves up (start work) That way less things come to bite me in the ass (they still do but smaller bites and less often)

Sorry, when youā€™ve been on the forum long enough you pick abreviations up
WAF - is ā€œWife Approval Factorā€ (your chances of buying more kit based on how impressed she was with your last efforts) :rofl:
MeAF - is an extension to WAF but this time being ā€œMe Approval Factorā€ (as in - ā€œI wouldnā€™t be satisfied with this shitā€) :rofl:

Okay, I accept what you say about Sw5 & 6 and Iā€™ll just ignore them

I think we only need information about the Game hardware (Iā€™m less concerned about that as IF it is possible to do as you say, then itā€™s limited to a very small subset of users (based on the hardware) so the benefits of an example piece of code will be close to zero - but Iā€™ll reserve judgement till we see it)

The wife has some jobs for me tomorrow and the dog is going in for surgery Monday but Iā€™ll start as soon as I have a ā€˜blockā€™ of time.

This is my first stab though : -

input_number:
  in_lvgrm_lamps_on:
    name: Living Room Lamps On
    min: 0
    max: 8
    step: 1
    mode: box
    icon: mdi:lightbulb-multiple
  in_lvgrm_lamp_brightness:
    name: Livingroom Lamp Brightness
    min: 0
    max: 100
    step: 10
    mode: box
    icon: mdi:brightness-2

automation:
  #name: Sw1 On
  - alias: au_lvgrm_sw1
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: light.sw1
        to: 'on'
        from: 'off'
    action:
      - service: input_number.increment
        entity_id: input_number.in_lvgrm_lamps_on
  #name: Sw2 On
  - alias: au_lvgrm_sw1
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: light.sw2
        to: 'on'
        from: 'off'
    action:
      - service: input_number.decrement
        entity_id: input_number.in_lvgrm_lamps_on
  #name: Sw3 On
  - alias: au_lvgrm_sw3
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: light.sw3
        to: 'on'
        from: 'off'
    action:
      - service: input_number.increment
        entity_id: input_number.in_lvgrm_lamp_brightness
  #name: Sw4 On
  - alias: au_lvgrm_sw1
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: light.sw4
        to: 'on'
        from: 'off'
    action:
      - service: input_number.decrement
        entity_id: input_number.in_lvgrm_lamp_brightness
  #name: What Happened ?
  - alias: au_lvgrm_lights_adjust
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: input_number.in_lvgrm_lamps_on
      - platform: state
        entity_id: in_lvgrm_lamp_brightness_off
    action:
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 0 else 'off' }}
        data:
          entity_id: light.bulb1
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 1 else 'off' }}
        data:
          entity_id: light.bulb2
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 2 else 'off' }}
        data:
          entity_id: light.bulb3
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 3 else 'off' }}
        data:
          entity_id: light.bulb4
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 4 else 'off' }}
        data:
          entity_id: light.bulb5
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 5 else 'off' }}
        data:
          entity_id: light.bulb6
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 6 else 'off' }}
        data:
          entity_id: light.bulb7
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5
      - service: light.turn_{{ 'on' if states('input_number.in_lvgrm_lamps_on') | int > 7 else 'off' }}
        data:
          entity_id: light.bulb8
          brightness_pct: {{ states('input_number.in_lvgrm_lamp_brightness') | int }}
          transistion: 5

It may error on setting a bulb to ā€˜offā€™ with a brightness of (say) 50 (Not a problem for that bulb but the one following ā€¦ ??? ) (Edit2: Do we care though as weā€™d have finished with the automation ???)
if so, Iā€™ll just rebuild it with ā€˜chooseā€™
So this took less than an hour

This is written as a package
2 numbers and 5 automations
(Edit though I could probably reduce that to 2 and 3 :thinking: )

EDIT: I just realized I didnā€™t see your increment light method so everything below doesnā€™t quite hit your requirements. Never the less, you can use it for something.


That whole C# you have there is a really simple small automation service call.

  1. Create a light group for the 8 lights.
  2. Call light.turn_on with a brightness_step. Pretty much accomplishes that whole section of code in a few lines of yaml.
light:
- platform: group
  name: name of light group
  entities:
  - light.bulb1
     .. etc ..
  - light.bulb8

then call the following service.

- service: light.turn_on
  data:
    entity_id: light.name_of_light_group
    brightness_step: 10

And you can template any field. So you could make the 10 for brightness step dynamic.


Check out the scene docs to find out how to dynamically store and recall scenes.

Check out automation templating and general templating to create dynamic settings for fields.

I could swear I saw a post from @Mariusthvdb about dynamic grouping
I didnā€™t read it (just scanned)
But without dynamic Iā€™d have to make 8 groups :frowning_face:
But it would make the automation simpler

This satisfies your requirements:

group:
  my_lights:
    entities:
    - light.light1
    - light.light2
    - light.light3
    - light.light4
    - light.light5
    - light.light6
    - light.light7
    - light.light8

automation1

- alias: Adds a light to group of lights
  trigger:
  - platform: state
    entity_id: switch.switch1
    to: 'on'
  action:
  - service: group.set
    data:
      entity_id: group.my_current_lights
      entities: >
        {% set all_lights = state_attr('group.my_lights', 'entity_id') %}
        {% set current_lights = state_attr('group.my_current_lights', 'entity_id') | default([]) %}
        {{ current_lights + [ all_lights | reject('in', current_lights) | first ] }}

automation2

- alias: Removes a light from group of lights
  trigger:
  - platform: state
    entity_id: switch.switch2
    to: 'on'
  condition:
    condition: template
    value_template: "{{ state_attr('group.my_current_lights', 'entity_id') | default([]) | length > 0 }}"
  action:
  - service: group.set
    data:
      entity_id: group.my_current_lights
      entities: >
        {% set current_lights = state_attr('group.my_current_lights', 'entity_id') | default([]) %}
        {{ current_lights[:-1] }}

automation2

- alias:  Adds or removes brightness
  trigger:
  - platform: state
    entity_id: switch.switch3, switch.switch4
    to: 'on'
  action:
  - service: light.turn_on
    data:
      entity_id: "{{ state_attr('group.my_current_lights','entity_id') }}"
      brightness_pct: >
        {% set levels = expand('group.my_current_lights') | map(attribute='attributes.brightness_pct') | map('float') %}
        {% set level = levels | sum / level | count %}
        {{ level + 10 if trigger.to_state.object_id == 'switch3' else level - 10 }}

the last automation can be done a number of different ways. Either way, it can be done you just need to learn the current syntax used by HA. Took me about 20 minutes to write that. Itā€™s untested so there might be typoā€™s, but you get the idea.

2 Likes

group.set :wink:

I REALLY like automation3 (though itā€™s named automation2 (again !))

Auto 1 :
Iā€™m assuming that the reject first is to eject an [] empty inclusion from the default ???

Edit: @petro I donā€™t think this will work as it is, if you have 8 lights on at 100%, turn 4 off, reduce brightness to 50% then add 4 lights, they will come back on at 100% you need another two triggers and a second test in the action (I think)

@petroā€™s example shows that this isnā€™t really that complicated in yaml - itā€™s actually less code than the pseudo code proposed by the op (and even then the opā€™s code doesnā€™t fulfil the actual requirements he asked for because it neglects to actually turn any lights on in the first place).

But, Iā€™ll be honest here and say that as powerful as the combination of yaml and jinja is to do all of this and more, itā€™s a waste of everyoneā€™s brain power because this is a home automation platform. The whole point of it is that it automates your home environment around you without you having to interact with it.

OP wants to get off the sofa and flick a switch 8 (yes 8!) times just to turn on the living room lights - thatā€™s the exact opposite of home automation in my eyes.

3 Likes

That needs to be etched in STONE
:+1:

Every time I need to pick up an interface, I thinkā€¦ Bugger ! I need to improve my automations !

yep, thatā€™s the oneā€¦ :wink:
sorry @Mutt to only read this now. Otherwise I would have posted the automation once more. Petroā€™s examples show all there is to it.

1 Like

The end result of this thread should be the take-away that, with the current feature set of native YAML automations, as long as the data you need to access is already in Home Assistant (or you can get it in Home Assistant) thereā€™s very little (nothing?) that canā€™t be done.

Native Automations require understanding the YAML and Jinja syntax to write your automation. This takes some effort and, even after that effort, it may still not be your ā€œfavoriteā€ ā€œprogramming languageā€. Thankfully, Home Assistant is flexible, so there are other options (PyScript, AppDaemon, NetDaemon, python_script, and Node-RED, that Iā€™m aware of). If none of those make your heart sing, you can always cook up something new as long as you can either speak to a websocket or write enough python to make a custom component to hook into whatever you build.

If you want the largest community to help you along your journey, Native Home Assistant Automations are probably your best bet. AppDaemon and Node-RED come in second. And the rest follow that. Regardless of which choice you make, youā€™re not likely to get much help unless to TRY IT first and then post your requirements, your code, and your issue so people can help.

2 Likes

My advantage is that Iā€™ve kept all my Node-Red automations (just disabled the trigger conditions) after I converted them to YAML.
I can load my instance onto the Pi and re-enable the Node-Red automations and see what happens.

1 Like

Well, the bottom line here is that there isnā€™t a human-noticeable difference in execution time between an automation coded in Node-Red and one coded in YAML.
Of course, there is some resource overhead, but even on my Pi3 it was measured in a a percentage point of CPU and a few of memory use. I donā€™t think thatā€™s enough to concern most users.

a long while back, I tested a native automation compared to AppDaemon (which works the same way Node-RED does) and, while I could see a difference in the numbers, it was so small (less than 10ms) that most people wouldnā€™t notice it. The most ā€œtime sensitiveā€ thing I can think of in typical automations is motion/door activated lights. And, in both cases, 10ms will not matter when you factor in the delay from the motion/door sensor, the delay for whatever network it is on, the delay of the bulbā€™s network, and the delay from the bulb itself.

1 Like