From 9718d9428a9e380dd985551dcaddd2feb52a9f07 Mon Sep 17 00:00:00 2001 From: Martin Bauer Date: Fri, 3 May 2024 20:55:18 +0200 Subject: [PATCH] ios actions --- google_assistant_service_account.json | 12 ++ pyscript/ios_actions.py | 255 ++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 google_assistant_service_account.json create mode 100644 pyscript/ios_actions.py diff --git a/google_assistant_service_account.json b/google_assistant_service_account.json new file mode 100644 index 0000000..e186657 --- /dev/null +++ b/google_assistant_service_account.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "homeassistant-291519", + "private_key_id": "5b1fdcd29c79c2b4979762e5942156d9a15aef6b", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaMwOaSlly1A8w\nEie6VrZr3bx5hQF/vuFJuViY7tRhYS+wSWhqJn0bpeWoUiZ5mMuhcX6fUSC945kD\nPq+RhCBLhcYh24X1Q+X6wncQq1Bz/f/cQYwpcPQm8RSUgl3OQpHd8pB7bDucf8mx\nqdOrZux7qihVTl6OKHp2BPYSsHBHtmmMGSCs1Et4tA3aNFivwKW7+PgXtae8nT52\nkXuV5pDF9ZnzaZZy/ZLXOrrsVVhOtzapssS/0L9CHbhR9e6fWucyCW4c5sG3e+h1\nLPZRZe5EPCAGAdawor2Rcmhn0K8scp3nHqEdZzWTqoNYxOSXZta5s9AYZ6gL/rkY\nP+3RhtWFAgMBAAECggEADcH78g3spadgdIZGJ6S5cW3O9Vul2tc1xA1mp3x1k/un\nFNgz2fa1plwanbY4qxQ0JOMarE3BeVe/bO/wm6/ZbsuQdjBfJxcoA4PKukDCtJqm\ns6jgf8kNa5UKZEauZmr/lzkfZXeuaOPo47JWiZ4s/sqbfyL3IkFfzbxbFSdLWUZ8\ndwEp3rBa/K6LsZG92kcU56OPisxuuXTDZYclX3Ezfjg2CQ3YTMebmmSqQKaQtJLN\nO1Mq3DTRZL9xQBAuL5zoEgpzi0vRyef6DxNNqge759lKi+Q4rwmU691XOPLSWPGg\n9Yci+x4EXmT3/HnMrci1e6Jo6GAhVONVBk8BQeTpkQKBgQDJBTkSZqFcCIKnhhUB\nwjzrZwmrQmHFWgc8VXBlBPO9mkgElSOfgAhV52/jtVYeP5r4Lu+48KphDnjZ+zYG\nrnNSBM8b/nEN/0p7uUB7mgbGAR/sgTEAvQVAk020UTxLlAAP3dOIIZv5N3pvuc3j\nk0sNeTvLWYKGrzFL2R9E0emMNQKBgQDEX4g5n8bJsnnzYwWWscGJ/NOUIyOXsvrX\n0CHNzw9Z6TK+dNCgVVPavwe5HMISF3NKLK6zngqYZ/Kq+7LWXGfMj/FSn2Eynt1r\nxMM85LvKUJup/m2q+tw9U4Ffp4EwXuiz7BCumxphyTihUkqWKgn6NMXhtUtZuucy\nIr69jucuEQKBgCp/RyyDs/M//VcrOn+vr69Yjiu9kevl94eizGse2+SmnDkTyn8q\n0xhOIFJ0gKtOaRW03osrnel85MG4oRhSgyDA0YQqi34ZDYcQh/hZfLsZe8VFHrX4\nQAcB3TiUv/l+ZXD1RYYPDOln+CNslYFaH1DO43w/BSAyI2rUkQ68jfJNAoGBAKNE\nKiZ+yO/5C5tnwMXBlH/9TIvlizoc/KFh0jki5kiCskXXKX2kc8ty+CDX4CLajGgn\nLjj4NSbxhbjS+6Vtvn89Tg67pDxKCR4IwapnIhrbWhDEELoPR/1U6EN3KNnmjuLI\najZBjnWurv6xRIIFAbadGcjGypcX5hCxApTnsx2BAoGALtJ+oelQg755VQD+z+IB\nh8Lllbb+42u7ezm0BNPlV890nt76GGWqPydDVDgtK/osr0hNOsAGk8I65D1H0GkN\nTB33Nva1TBSgXu8hLvo1gSzsMlTokMAP97THoA6Nb9i0W0vFPBtn4zdEW0fxqcb+\nqg1DXr6mU8xK0U0Vd8QXfWY=\n-----END PRIVATE KEY-----\n", + "client_email": "homeassistant-service@homeassistant-291519.iam.gserviceaccount.com", + "client_id": "110579585453038910562", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/homeassistant-service%40homeassistant-291519.iam.gserviceaccount.com" +} diff --git a/pyscript/ios_actions.py b/pyscript/ios_actions.py new file mode 100644 index 0000000..e991063 --- /dev/null +++ b/pyscript/ios_actions.py @@ -0,0 +1,255 @@ +from datetime import datetime, timedelta + +from ir_helpers import * + +TIMEOUT_REPEAT_PRESS = 5 # time to switch states when pressed shortly in sequence, in seconds + +# --------------------------------- Helper functions ---------------------------------------------------- + +light_scene_helper_dict = {} +def scene_helper(scene_function): + """Function to manage the repeated press of the same action + When pressed shortly in sequence, states are cycled + Otherwise light is toggled""" + unique_name_for_globals = id(scene_function) + is_on_func, scenes = scene_function() + last_called, call_idx = light_scene_helper_dict.get(unique_name_for_globals, (datetime.now(), -1)) + now = datetime.now() + time_since_last_call = now - last_called + recently_called = (time_since_last_call < timedelta(seconds=TIMEOUT_REPEAT_PRESS)) + light_already_on = is_on_func() + log.warning(f"{light_already_on=}") + if recently_called: + call_idx = (call_idx + 1) + else: + call_idx = -1 + + if light_already_on and call_idx == -1: + scenes[-1]() + call_idx = -1 + elif not light_already_on: + scenes[0]() + call_idx = 0 + else: + idx = call_idx % len(scenes) + scenes[idx]() + + light_scene_helper_dict[unique_name_for_globals] = (now, call_idx) + +# --------------------------------- "Scenes" for actions ---------------------------------------------------- + +def az_oben_licht_scenes(): + entity = "light.arbeitszimmer_oben_fluter" + now = datetime.now() + if now.hour >=8 and now.hour < 19: # day + scenes = [ + light_f("turn_on", entity, color_temp=180, brightness=230), + light_f("turn_on", entity, color_temp= 468, brightness=230), + light_f("turn_on", entity, color_temp= 468, brightness=100), + light_f("turn_off", entity) + ] + elif now.hour < 8: # morning + scenes = [ + light_f("turn_on", entity, color_temp=420, brightness=200, transition=60), + light_f("turn_on", entity, color_temp=420, brightness=250, transition=60), + light_f("turn_off", entity) + ] + else: # evening + scenes = [ + light_f("turn_on", entity, color_temp=470, brightness=100), + light_f("turn_on", entity, color_temp=470, brightness=20), + light_f("turn_off", entity) + ] + + is_on = lambda entity=entity: hass.states.get(entity).state == "on" + return is_on, scenes + +def kz_regal_scenes(): + now = datetime.now() + entity = "light.music_mouse_regal_licht" + + def fade_out_f(rgb_color, seconds): + return multiple_f(cover_f("close_cover", "cover_kinderzimmer_rollo"), + light_f("turn_on", entity, brightness=250, rgb_color=rgb_color, effect="side_0.5"), + light_f("turn_on", entity, brightness= 10, rgb_color=rgb_color, effect="side_0.5_inc4", transition=int(0.8 * seconds)), + light_f("turn_on", entity, brightness= 10, rgb_color=rgb_color, effect="side_0.2_inc8", transition=int(0.2 * seconds))), + + if now.hour >= 18: # abends + scenes = [ + fade_out_f([255, 182, 41], 10 * 60), + fade_out_f([255, 98, 231], 10 * 60), + light_f("turn_off", entity) + ] + else: + scenes = [ + light_f("turn_on", entity, brightness=250, rgb_color=[255, 182, 41], effect="static"), + light_f("turn_on", entity, brightness=250, rgb_color=[255, 98, 231], effect="static"), + light_f("turn_on", entity, brightness=250, rgb_color=[30, 30, 255], effect="static"), + light_f("turn_on", entity, brightness=200, effect="twocolorrandom"), + light_f("turn_off", entity) + ] + is_on = lambda entity=entity: hass.states.get(entity).state == "on" + return is_on, scenes + + +def az_unten_licht_scenes(): + scenes = [ + scene_f("arbeitszimmer_orange"), + scene_f("arbeitszimmer_hell"), + scene_f("arbeitszimmer_blau_grun"), + light_f("turn_off", "light.arbeitszimmer_lichter"), + ] + is_on = lambda: hass.states.get("light.arbeitszimmer_lichter").state == "on" + return is_on, scenes + +def wz_deckenlampe(): + scenes = [ + light_f("turn_off", "light.wohnzimmer_deckenlampe"), + light_f("turn_off", "light.wohnbereich_deckenlampen"), + multiple_f(light_f("turn_on", "light.kuche_deckenlampe", brightness=10), + light_f("turn_on", "light.esszimmer_deckenlampe_west", brightness=10), + light_f("turn_on", "light.wohnzimmer_deckenlampe", brightness=10), + ) + ] + + def is_off(): + entities = ["light.kuche_deckenlampe", + "light.esszimmer_deckenlampe_west", + "light.wohnzimmer_deckenlampe"] + return all(hass.states.get(e) == 'off' for e in entities) + + return is_off, scenes + +def wohnbereich_scenes(): + scenes = [ + scene_f("wohnbereich_orange"), + scene_f("wohnbereich_hell"), + scene_f("wohnbereich_blau_grun"), + scene_f("wohnbereich_grun"), + light_f("turn_off", "light.wohnbereich_lichter"), + ] + is_on = lambda: hass.states.get("light.wohnbereich_lichter").state == "on" + return is_on, scenes + +def essbereich_scenes(): + scenes = [ + scene_f("kuche_essbereich_orange"), + scene_f("kuche_essbereich_hell"), + scene_f("kuche_essbereich_blau_grun"), + scene_f("kuche_essbereich_grun"), + light_f("turn_off", "light.essbereich_lichter"), + ] + is_on = lambda: hass.states.get("light.essbereich_lichter").state == "on" + return is_on, scenes + +def wohnzimmer_scenes(): + scenes = [ + scene_f("wohnzimmer_orange"), + scene_f("wohnzimmer_hell"), + scene_f("wohnzimmer_dunkel"), + scene_f("wohnzimmer_blau_grun"), + scene_f("wohnzimmer_grun"), + light_f("turn_off", "light.wohnzimmer_lichter"), + ] + is_on = lambda: hass.states.get("light.wohnzimmer_lichter").state == "on" + return is_on, scenes + +def garten_vorne(): + scenes = [ + scene_f("garten_eingang_normal"), + scene_f("garten_eingang_hell"), + scene_f("garten_eingang_farbig"), + ] + is_on = lambda: hass.states.get("light.lichter_garten_eingang").state == "on" + return is_on, scenes + +def garten_sued(): + scenes = [ + scene_f("garten_sued_normal"), + scene_f("garten_sued_hell"), + scene_f("garten_sued_farbig"), + ] + is_on = lambda: hass.states.get("light.garten_sud").state == "on" + return is_on, scenes + +def garten_alles(): + scenes = [ + scene_f("garten_alles_normal"), + scene_f("garten_alles_hell"), + scene_f("garten_alles_farbig"), + ] + is_on = lambda: hass.states.get("light.garten_sud").state == "on" + return is_on, scenes + +# --------------------------------- HA App actions --------------------------------------------------------------------- + +@event_trigger("ios.action_fired") +def on_ios_action_fired(actionName, **kwargs): + if actionName == "az_oben_licht": + scene_helper(az_oben_licht_scenes) + elif actionName == "kz_regal": + scene_helper(kz_regal_scenes) + elif actionName == "az_unten_licht": + scene_helper(az_unten_licht_scenes) + elif actionName == "wz_deckenlampe": + scene_helper(wz_deckenlampe) + elif actionName == "wohnbereich": + scene_helper(wohnbereich_scenes) + elif actionName == "wohnzimmer": + scene_helper(wohnzimmer_scenes) + elif actionName == "essbereich": + scene_helper(essbereich_scenes) + elif actionName == "schlafzimmer_bett_bringen": + cover.close_cover(entity_id="cover.schlafzimmer_rollo_gross") + cover.close_cover(entity_id="cover.schlafzimmer_rollo_klein") + script.timed_sleep(media_content_id="Good Night", light_off_mins=15, music_off_mins=45, shuffle=False) + elif actionName == "garten_vorne": + scene_helper(garten_vorne) + elif actionName == "garten_sued": + scene_helper(garten_sued) + elif actionName == "garten_alles": + scene_helper(garten_alles) + + +# --------------------------- Shortcut (room dependent) --------------------------------------------------------------- + +@event_trigger("ios.shortcut_event") +def on_ios_shortcut_event(room, action, device, **kwargs): + if room == "unknown": + room = state.get("sensor.martins_apple_watch") + if room == "arbeitszimmer": + if action == "hass_ceiling_light": + light.toggle(entity_id="light.arbeitszimmer_deckenlampe") + elif action == "hass_light_off": + light.turn_off(entity_id="group.office") + elif action == "hass_light_darken": + dimmer.dim(entity_id="group.office", offset=-30) + elif action == "hass_light_brighten": + dimmer.dim(entity_id="group.office", offset=30) + elif action == "hass_light_orange": + scene.turn_on(entity_id="scene.arbeitszimmer_orange") + elif action == "hass_light_blue": + scene.turn_on(entity_id="scene.arbeitszimmer_blau_grun") + elif action == "hass_light_bright": + scene.turn_on(entity_id="scene.arbeitszimmer_hell") + elif action == "hass_cover_open": + cover.open_cover(entity_id="cover.arbeitszimmer_rollo") + elif action == "hass_cover_close": + cover.close_cover(entity_id="cover.arbeitszimmer_rollo") + elif action == "hass_cover_half": + cover_half.set_half(entity_id="cover.arbeitszimmer_rollo") + + if room == "buero_oben": + entity = "scene.arbeitszimmer_orange" + if action == "hass_light": + scene_helper(az_oben_licht_scenes) + elif action == "hass_light_orange": + light_f("turn_on", entity, color_temp=470, brightness=100)() + elif action == "hass_light_blue": + light_f("turn_on", entity, color_temp=180, brightness=230)() + elif action == "hass_light_darken": + dimmer.dim(entity_id=entity, offset=-30) + elif action == "hass_light_brighten": + dimmer.dim(entity_id=entity, offset=30) + elif action == "hass_light_off": + light.turn_off(entity_id=entity) \ No newline at end of file