Loop over list in a script

Hi everyone,
enjoying the power of HA for a couple of weeks, I’m struggling with something for the past couple of days.
I’m trying to create a script that iterates over a list and call a shell command over them. Basically, in bash it would be

for i in foo bar baz qux; do
    some_command $i
done

My current implementation looks like this (the service call doesn’t complain, but it does nothing):

service: shell_command.integration
data:
  id: >
    {%- set mylist = '20a45378cfe4c36c89ad16e056da59b1
    e5633f2cf5aea5403e54b6d87a96e843 8cb9b789e7d1a4332f7e0c7381965d13
    f007dc7017cb69eeab71a93bc740d79c' -%} {{mylist.split(" ")}}
  state: disable

For those who are wondering, I’ve made a python script to activate/deactivate integrations without having to use the webUI. It allows me to turn on the camera plugs (yi-hack) and to activate the integration without having to let the cameras on and without my logs being filled with warnings if they are off :slight_smile:

This python3 script is called from a shell_command with an uuid and state as parameter.

Thank you for your answers!

P.S:

  • I can provide the python script if someone is interested.
  • If someone has a better solution, I’m all hear (but AFAIK, there’s no automation for activate/deactivate integrations)

EDIT: I’ve also created an input_select with the 4 values but I’m definitely not sure how to use it :confused:

Alright, answering to myself ^^

I’ve come to modify my python script to handle multiple id in a same command line.

Here’s the script:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from time import sleep
import websocket
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-i", "--id", help="Intergation's ID (see .storage/core.config_entries)", nargs='+', required=True)
parser.add_argument("-s", "--state", help="enable/diable integration", choices=['enable', 'disable'], required=True)
parser.add_argument("-b", "--bearer", help="bearer token", required=True)
args = parser.parse_args()

ha = "127.0.0.1:8123"
ids = args.id
state = args.state
bearer = args.bearer

ws = websocket.WebSocket()
ws.connect("ws://"+ha+"/api/websocket")

json_auth = "{\"type\":\"auth\",\"access_token\":\""+bearer+"\"}"
ws.send(json_auth)
wsid = 0

for id in ids:
  wsid += 1
  if state == 'enable':
      json_state = "{\"type\":\"config_entries/disable\",\"entry_id\":\""+id+"\",\"disabled_by\":null,\"id\":"+str(wsid)+"}"
  elif state == 'disable':
      json_state = "{\"type\":\"config_entries/disable\",\"entry_id\":\""+id+"\",\"disabled_by\":\"user\",\"id\":"+str(wsid)+"}"
  ws.send(json_state)

and the corresponding shell_command:

integration: python /config/shell/integration.py -i {{ id }} -s {{ state }} -b <TOKEN>

I can then use this in a script to activate/deactivate yi-hack integrations when I start/stop alarmo:

cameras_start:
  alias: cameras_start
  sequence:
  - service: switch.turn_on
    data:
      entity_id: group.plugs_cameras
  - service: shell_command.integration
    data:
      id: '{%- set mylist = ''20a45378cfe4c36c89ad16e056da59b1 e5633f2cf5aea5403e54b6d87a96e843
        8cb9b789e7d1a4332f7e0c7381965d13 f007dc7017cb69eeab71a93bc740d79c'' -%} {{mylist.split("
        ")}}

        '
      state: enable
  - service: homeassistant.restart
    data: {}
  mode: single

And finally use this script in an automation when the state of alarmo is on arming.

It’s not very HA-style but it works :slight_smile: If anybody has a better solution, like looping over each id in a set or by using a input_select, be my guest!

Side note: I haven’t been able to store the token in the secrets.yml file, I only get errors stating that token does not exist, while it works very well for integrations. Is there any limitations with this file? Doesn’t it work for anything other than integrations?

Thanks!

1 Like

One of HA’s lead devs created a custom integration, Spook, that includes those two actions among its abilities.

Regarding the iteration, you would use a repeat for each action:

repeat:
  for_each:
    - 20a45378cfe4c36c89ad16e056da59b1
    - e5633f2cf5aea5403e54b6d87a96e843
    - 8cb9b789e7d1a4332f7e0c7381965d13
    - f007dc7017cb69eeab71a93bc740d79c
  sequence:
    - service: shell_command.integration
      data:
        id: "{{ repeat.item }}"
        state: disable

The for_each configuration variable accepts templates that return a list as long as the list items are simple objects, so you could use the following instead of the static list shown above:

{{ state_attr('input_select.EXAMPLE', 'options') }}

Thanks @Didgeridrew !
I posted that a while ago and I basically remove the activate/deactivate integrations part, but good to know for Spook.

And thanks for the code, it’s always good to know!