Solved (epic!) Script for water-play-tile for kids!

Hi guys!

I’m working on a water-play-tile (outside) whicn means: a tile with 5 holes in it with water coming out. Now i’'ve built all logic in PHP. But now i’m trying to translate it to Ninja or whatever is needed.

But i dunno where to start. Is it even possible what i want? Or is another way easier?

Own writtten PHP code:

<?php

$pins = ['water_pin_14', 'water_pin_16', 'water_pin_17', 'water_pin_18', 'water_pin_19'];
$scriptStarted = true;
$maxIterations = 30;
$counter = 0;

$randomAmounts = [1,1,1,1,2,2,2,2,3,3,3,3,4,4,5,5];

while($scriptStarted and $counter < $maxIterations) {

    // Shuffle array
    shuffle($pins);
	
	// Shuffle randomAmounts
	shuffle($randomAmounts);
	
	// Pick random keys
	$randomPinKeys = array_rand($pins, $randomAmounts[0]);
	
	// If $randomPinKeys contains one element, it's unfortunately casted to int, cast it back to array
	if (is_numeric($randomPinKeys)) {
	    $randomPinKeys = [0 => $randomPinKeys];
	}
	
	// Turn off all pins
	foreach($pins as $pin) {
		echo 'turn off pin ' . $pin . PHP_EOL;
	}
	
	// Turn on random picked pins
	foreach ($randomPinKeys as $randomPinKey) {
		echo 'turning on pin ' . $pins[$randomPinKey] . PHP_EOL;
	}
	
	sleep(rand(3,8)); // Random wait between 3 and 8 seconds
	$counter++;
}

Edit

Fixed, please check below!

So where is this code going to run? In HA or on an ESP, or what’s the output going to be?
Just text as this is or something actually happening?

Good question.The code will actually just do turn off home assistant switches in the for-each, and turn on some switches in the foreach beneath it.

But i probably need to change it to Python, and then load it in HA and use the HA specific python code to toggle switches? Is that the right way?

Ninja?

Maybe you meant Jinja2?

I would simply use Home Assistant’s native scripting but you can certainly do it with python, appdaemon, pyscript, Node-Red, etc. Your first step is to decide which one you want to use.

Personally I would probably use Node red for this since it has good debugging and can easily handle more than one device at the time in a string format switch.switch1, switch.switch2 would turn on/off both entities.
That means you can just append/join the entities to one string and send them to a call service.
If you then save the entities (string) in a flow variable then you can only turn off the ones that was turned on in the last run and not do it on switches that is already off.

Yeah, Nailed it!

I changed it to Python. Simplified it, and moved some logic to Home Assistant Script and Automation. Works like a friggin charm now!

For those who wants to built this awesome water-play-tile for kids too, here is the source. If you want to know which physical parts you need (tile, drill, hose, etc) DM me :). I’m uploading a movie later this summer.

/// — pyscript/water_tile_logic.py

@service
def water_tile_logic(action=None, id=None):
    
    import random, time
    from collections import OrderedDict
    
    pins = OrderedDict([(0,'switch.water_pin_14'),(1,'switch.water_pin_16'),(2,'switch.water_pin_17'),(3,'switch.water_pin_18'),(4,'switch.water_pin_19')]);
    randomAmounts = OrderedDict([(0,1),(1,1),(2,1),(3,1),(4,2),(5,2),(6,2),(7,2),(8,3),(9,3),(10,3),(11,3),(12,4),(13,4),(14,5),(15,5)]);
    random.shuffle(pins);
    random.shuffle(randomAmounts);
    randomPinKeys = random.choices(pins, k=randomAmounts[0]);
    if ((type(randomPinKeys) == int or float)) :
        randomPinKeys = OrderedDict([(0,randomPinKeys)]);
    for randomPinKeyList in randomPinKeys.values() :
        for randomPinKey in randomPinKeyList :
            service.call("switch", "turn_on", entity_id=randomPinKey);

/// — automations.yaml

- id: '1647956518731'
  alias: Watertegel | Uitzetten
  description: ''
  trigger:
  - platform: state
    entity_id: input_boolean.watertegel
    to: 'off'
  condition: []
  action:
  - service: switch.turn_off
    data: {}
    target:
      entity_id:
      - switch.water_pin_14
      - switch.water_pin_16
      - switch.water_pin_17
      - switch.water_pin_18
      - switch.water_pin_19
  mode: single
- id: '1647957012014'
  alias: Watertegel | Aanzetten
  description: ''
  trigger:
  - platform: state
    entity_id: input_boolean.watertegel
    to: 'on'
  condition: []
  action:
  - service: script.random_water_tile
    data: {}
  mode: single

/// — add a helper:

/// — scripts.yaml

random_water_tile:
  alias: Random Water Tile
  sequence:
  - repeat:
      while:
      - condition: state
        entity_id: input_boolean.watertegel
        state: 'on'
      sequence:
      - service: switch.turn_off
        data: {}
        target:
          entity_id:
          - switch.water_pin_14
          - switch.water_pin_16
          - switch.water_pin_17
          - switch.water_pin_18
          - switch.water_pin_19
      - delay:
          hours: 0
          minutes: 0
          seconds: 0
          milliseconds: 500
      - service: pyscript.water_tile_logic
        data: {}
      - delay:
          seconds: '{{ range(2, 8)|random|int }}'
  mode: single
  icon: mdi:fountain

That’s it! Now, when toggle ‘Watertegel’ switch, there will be water coming out of the play tile in random order. E.g.

water hole 3 and 5 for 2 seconds
stopping water
water hole 1, 2, and 4 for 6 seconds
stopping water.
etc.

Height of water is depending on amount of active holes.

Have a nice summer guys!