My IKEA Bilresa scrollwheel example

I tried to get all my 3 IKEA Bilresa to work in only one pyscript file. All 3 have similar setup in different rooms. This works for me. Sorry for swedish annotiatons.

Room 1,2 and 3. 3 different Bilresa one for each room. Mode 1 (left LED), mode 2 (middle LED), mode 3 (right LED) (say room 2,3,4 in code)

Mode 1: Ceiling lamp - on/ff (klick), Dimmable light (scroll left/right). TAK
Mode 2: Window light (if plug klick on/off) (if dimmable klick on/off and scroll left/right for dimmer). FONSTER
Mode 3: Rollerblind motor aqara (aqara - klick up/down, scroll left or right to move blinds partly up/down. COVER


# ========= TRIGGER =========
@state_trigger(
    # TAK
    "event.bilresa_scroll_wheel_knapp_1_2",
    "event.bilresa_scroll_wheel_knapp_2_2",
    "event.bilresa_scroll_wheel_knapp_3_2",
    "event.bilresa_scroll_wheel_knapp_1_3",
    "event.bilresa_scroll_wheel_knapp_2_3",
    "event.bilresa_scroll_wheel_knapp_3_3",
    "event.bilresa_scroll_wheel_knapp_1_4",
    "event.bilresa_scroll_wheel_knapp_2_4",
    "event.bilresa_scroll_wheel_knapp_3_4",

    # FÖNSTER
    "event.bilresa_scroll_wheel_knapp_4_2",
    "event.bilresa_scroll_wheel_knapp_5_2",
    "event.bilresa_scroll_wheel_knapp_6_2",
    "event.bilresa_scroll_wheel_knapp_4_3",
    "event.bilresa_scroll_wheel_knapp_5_3",
    "event.bilresa_scroll_wheel_knapp_6_3",
    "event.bilresa_scroll_wheel_knapp_4_4",
    "event.bilresa_scroll_wheel_knapp_5_4",
    "event.bilresa_scroll_wheel_knapp_6_4",

    # GARDIN
    "event.bilresa_scroll_wheel_knapp_7_2",
    "event.bilresa_scroll_wheel_knapp_8_2",
    "event.bilresa_scroll_wheel_knapp_9_2",
    "event.bilresa_scroll_wheel_knapp_7_3",
    "event.bilresa_scroll_wheel_knapp_8_3",
    "event.bilresa_scroll_wheel_knapp_9_3",
    "event.bilresa_scroll_wheel_knapp_7_4",
    "event.bilresa_scroll_wheel_knapp_8_4",
    "event.bilresa_scroll_wheel_knapp_9_4",
)
def handle_all(var_name=None, value=None, old=None):

    # SPÄRR 1: Avbryt omedelbart om tillståndet blir tomt eller okänt
    if not value or value in ["unknown", "unavailable"]:
        return

    # ========= ATTRIBUT =========
    attrs = state.getattr(var_name)
    if not attrs:
        return

    event_type = attrs.get("event_type")
    if not event_type:
        return

    # SPÄRR 2: Lyssna bara på giltiga knapphändelser
    if event_type not in ["InitialPress", "multi_press_1", "multi_press_2", "multi_press_3", "multi_press_4", "multi_press_5", "multi_press_6", "multi_press_7"]:
        return

    # SPÄRR 3: KONTROLLERA ATT HÄNDELSEN ÄR FÄRSK (Stoppar alla nätverksdippar)
    try:
        from datetime import datetime
        
        tids_strang = value.split("+")[0]
        handelse_tid = datetime.fromisoformat(tids_strang)
        
        sekunder_sedan = (datetime.utcnow() - handelse_tid).total_seconds()
        
        if sekunder_sedan > 5.0:
            log.info(f"Bilresa Spärr: Blockerade gammal nätverkssignal för {var_name} ({sekunder_sedan}s gammal)")
            return
    except Exception as e:
        pass

    # ========= PARSA =========
    parts = var_name.split("_")
    knapp = parts[-2]
    rum = parts[-1]

    log.info(f"Bilresa: rum={rum} knapp={knapp} event={event_type}")

    # ========= MULTIPRESS =========
    count = 1
    if event_type.startswith("multi_press_"):
        try:
            count = int(event_type.split("_")[-1])
        except:
            count = 1

    step = max(5, 5 * count)

    # ========= ENHETER PER RUM =========
    if rum == "2":      # DISAS RUM
        TAK = "light.e27_1"
        FONSTER = None
        COVER = "cover.rullgardin_01"

    elif rum == "3":    # TILLAS RUM
        TAK = "light.e27_2"
        FONSTER = "switch.grillplats_plug"
        COVER = "cover.rullgardin_03"

    elif rum == "4":    # LOS RUM
        TAK = "light.e27_6"
        FONSTER = "light.e14_2"
        COVER = "cover.rullgardin_02"
    else:
        return

    # ========= TAKLAMPA LOGIK =========
    if knapp == "1":
        light.turn_on(entity_id=TAK, brightness_step_pct=step, transition=0.1)
    elif knapp == "2":
        light.turn_on(entity_id=TAK, brightness_step_pct=-step, transition=0.1)
    elif knapp == "3":
        if state.get(TAK) == "on": light.turn_off(entity_id=TAK)
        else: light.turn_on(entity_id=TAK)

    # ========= FÖNSTERLAMPA LOGIK =========
    elif knapp == "4":
        if not FONSTER: return
        if FONSTER.startswith("switch"): 
            switch.turn_on(entity_id=FONSTER)
        else: 
            if event_type == "InitialPress":
                light.turn_on(entity_id=FONSTER)
            else:
                light.turn_on(entity_id=FONSTER, brightness_step_pct=step, transition=0.1)

    elif knapp == "5":
        if not FONSTER: return
        if FONSTER.startswith("switch"): 
            switch.turn_off(entity_id=FONSTER)
        else: 
            if event_type == "InitialPress":
                light.turn_off(entity_id=FONSTER)
            else:
                light.turn_on(entity_id=FONSTER, brightness_step_pct=-step, transition=0.1)

    elif knapp == "6":
        if not FONSTER: return
        if FONSTER.startswith("switch"): switch.toggle(entity_id=FONSTER)
        else:
            if state.get(FONSTER) == "on": light.turn_off(entity_id=FONSTER)
            else: light.turn_on(entity_id=FONSTER)

    # ========= RULLGARDIN LOGIK =========
    elif knapp in ["7", "8", "9"]:
        if not COVER: return

        current_state = state.get(COVER)
        cover_attrs = state.getattr(COVER)
        pos = cover_attrs.get("current_position", 0) if cover_attrs else 0

        if knapp == "7":
            if event_type == "InitialPress": cover.open_cover(entity_id=COVER)
            else:
                new_pos = min(100, pos + step)
                cover.set_cover_position(entity_id=COVER, position=new_pos)

        elif knapp == "8":
            if event_type == "InitialPress": cover.close_cover(entity_id=COVER)
            else:
                new_pos = max(0, pos - step)
                cover.set_cover_position(entity_id=COVER, position=new_pos)

        elif knapp == "9":
            if current_state == "closed" or pos == 0: cover.open_cover(entity_id=COVER)
            else: cover.close_cover(entity_id=COVER)