Ikea Styrbar Force OTA if on V1.0.024

I think it worked now, thanks

So went trough the whole update process and still on 1.0.024. Saw the update in the log till 100%. Must be doing something wrong.

2023-03-11 17:41:35.343 DEBUG (MainThread) [zigpy.zcl] [0xABBB:1:0x0019] OTA upgrade_end handler for 'IKEA of Sweden Remote Control N2': status=Status.SUCCESS, manufacturer_id=4476, image_type=4555, file_version=581

2023-03-11 17:41:35.344 DEBUG (MainThread) [zigpy.zcl] [0xABBB:1:0x0019] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 1>, disable_default_response=1, reserved=0, *is_cluster=True, *is_general=False, *is_reply=True), tsn=1, command_id=7, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)

2023-03-11 17:41:35.344 DEBUG (MainThread) [zigpy.zcl] [0xABBB:1:0x0019] Sending reply: upgrade_end_response(manufacturer_code=4476, image_type=4555, file_version=581, current_time=0, upgrade_time=0)

file_version=581 is this right?

1 Like

I had to re-pair my device after update ':slight_smile: try that

Also follow this post afterwards to fix the battery showing as above 100%

Do we still need to apply this manual quirk workaround as of 2023.4 ?

Good question. My N2’s are now reporting 128% battery level. And the custom quirk is reporting exceptions. :rofl:

Logger: zhaquirks
Source: custom_zha_quirks/fourbtnremote.py:44
First occurred: 25 April 2023 at 08:23:49 (1 occurrences)
Last logged: 25 April 2023 at 08:23:49

Unexpected exception importing custom quirk 'fourbtnremote'
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/zhaquirks/__init__.py", line 454, in setup
    importer.find_module(modname).load_module(modname)
  File "<frozen importlib._bootstrap_external>", line 548, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1063, in load_module
  File "<frozen importlib._bootstrap_external>", line 888, in load_module
  File "<frozen importlib._bootstrap>", line 290, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 719, in _load
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/config/custom_zha_quirks/fourbtnremote.py", line 44, in <module>
    from zhaquirks.ikea import (
ImportError: cannot import name 'PowerConfiguration2AAACluster' from 'zhaquirks.ikea' (/usr/local/lib/python3.10/site-packages/zhaquirks/ikea/__init__.py)

I fixed the 128% battery level and quirk exception issues by changing fourbtnremote.py, replacing all occurrences of “PowerConfiguration2AAACluster” with “DoublingPowerConfig2AAACluster” and restarting HA.

The modified custom_zha_quirks\fourbtnremote.py file is as follows:

"""Device handler for IKEA of Sweden TRADFRI remote control."""
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    Identify,
    LevelControl,
    OnOff,
    Ota,
    PollControl,
    PowerConfiguration,
)
from zigpy.zcl.clusters.lightlink import LightLink

from zhaquirks.const import (
    CLUSTER_ID,
    COMMAND,
    COMMAND_HOLD,
    COMMAND_MOVE,
    COMMAND_MOVE_ON_OFF,
    COMMAND_OFF,
    COMMAND_ON,
    COMMAND_PRESS,
    COMMAND_STOP,
    COMMAND_STOP_ON_OFF,
    DEVICE_TYPE,
    DIM_DOWN,
    DIM_UP,
    ENDPOINT_ID,
    ENDPOINTS,
    INPUT_CLUSTERS,
    LEFT,
    LONG_PRESS,
    LONG_RELEASE,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PARAMS,
    PROFILE_ID,
    RIGHT,
    SHORT_PRESS,
    TURN_OFF,
    TURN_ON,
)
from zhaquirks.ikea import (
    IKEA,
    IKEA_CLUSTER_ID,
    WWAH_CLUSTER_ID,
    DoublingPowerConfig2AAACluster,
    ScenesCluster,
)

from zhaquirks import DoublingPowerConfigurationCluster

class DoublingPowerConfig2AAAClusterSTYRBAR_2_4_5(DoublingPowerConfigurationCluster):
    """Updating Power attributes 2 AAA."""
    """And for STYRBAR V2.4.5 as it scales battery voltage between 0-255."""

    BATTERY_SIZES = 0x0031
    BATTERY_QUANTITY = 0x0033
    BATTERY_RATED_VOLTAGE = 0x0034
    
    BATTERY_PERCENTAGE_REMAINING  = 0x0021

    _CONSTANT_ATTRIBUTES = {
        BATTERY_SIZES: 4,
        BATTERY_QUANTITY: 2,
        BATTERY_RATED_VOLTAGE: 15,
    }

    def _update_attribute(self, attrid, value):
        if attrid == self.BATTERY_PERCENTAGE_REMAINING:
            value = (value / 255) * 100
        super()._update_attribute(attrid, value)


class IkeaTradfriRemoteV1(CustomDevice):
    """Custom device representing IKEA of Sweden TRADFRI remote control V1.0.024."""

    signature = {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=820
        # device_version=1
        # input_clusters=[0, 1, 3, 32, 4096, 64599]
        # output_clusters=[3, 6, 8, 25, 4096]>
        MODELS_INFO: [(IKEA, "Remote Control N2")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    LightLink.cluster_id,
                    WWAH_CLUSTER_ID,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    Ota.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DoublingPowerConfig2AAACluster,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    LightLink.cluster_id,
                    WWAH_CLUSTER_ID,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    ScenesCluster,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    Ota.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        }
    }

    device_automation_triggers = {
        (SHORT_PRESS, TURN_ON): {COMMAND: COMMAND_ON, CLUSTER_ID: 6, ENDPOINT_ID: 1},
        (LONG_PRESS, DIM_UP): {
            COMMAND: COMMAND_MOVE_ON_OFF,
            CLUSTER_ID: 8,
            ENDPOINT_ID: 1,
            PARAMS: {"move_mode": 0},
        },
        (LONG_RELEASE, DIM_UP): {
            COMMAND: COMMAND_STOP_ON_OFF,
            CLUSTER_ID: 8,
            ENDPOINT_ID: 1,
        },
        (SHORT_PRESS, TURN_OFF): {COMMAND: COMMAND_OFF, CLUSTER_ID: 6, ENDPOINT_ID: 1},
        (LONG_PRESS, DIM_DOWN): {
            COMMAND: COMMAND_MOVE,
            CLUSTER_ID: 8,
            ENDPOINT_ID: 1,
            PARAMS: {"move_mode": 1},
        },
        (LONG_RELEASE, DIM_DOWN): {
            COMMAND: COMMAND_STOP,
            CLUSTER_ID: 8,
            ENDPOINT_ID: 1,
        },
        (SHORT_PRESS, LEFT): {
            COMMAND: COMMAND_PRESS,
            CLUSTER_ID: 5,
            ENDPOINT_ID: 1,
            PARAMS: {
                "param1": 257,
                "param2": 13,
                "param3": 0,
            },
        },
        (LONG_PRESS, LEFT): {
            COMMAND: COMMAND_HOLD,
            CLUSTER_ID: 5,
            ENDPOINT_ID: 1,
            PARAMS: {
                "param1": 3329,
                "param2": 0,
            },
        },
        (SHORT_PRESS, RIGHT): {
            COMMAND: COMMAND_PRESS,
            CLUSTER_ID: 5,
            ENDPOINT_ID: 1,
            PARAMS: {
                "param1": 256,
                "param2": 13,
                "param3": 0,
            },
        },
        (LONG_PRESS, RIGHT): {
            COMMAND: COMMAND_HOLD,
            CLUSTER_ID: 5,
            ENDPOINT_ID: 1,
            PARAMS: {
                "param1": 3328,
                "param2": 0,
            },
        },
    }


class IkeaTradfriRemoteV2(CustomDevice):
    """Custom device representing IKEA of Sweden TRADFRI remote control Version 2.4.5."""

    signature = {
        # <SimpleDescriptor endpoint=1 profile=260 device_type=820
        # device_version=1
        # input_clusters=[0, 1, 3, 32, 4096, 64599, 64636]
        # output_clusters=[3, 5, 6, 8, 25, 4096]>
        MODELS_INFO: [(IKEA, "Remote Control N2")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    LightLink.cluster_id,
                    WWAH_CLUSTER_ID,
                    IKEA_CLUSTER_ID,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    ScenesCluster.cluster_id,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    Ota.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    DoublingPowerConfig2AAAClusterSTYRBAR_2_4_5,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    LightLink.cluster_id,
                    WWAH_CLUSTER_ID,
                    IKEA_CLUSTER_ID,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    ScenesCluster,
                    OnOff.cluster_id,
                    LevelControl.cluster_id,
                    Ota.cluster_id,
                    LightLink.cluster_id,
                ],
            }
        }
    }

    device_automation_triggers = IkeaTradfriRemoteV1.device_automation_triggers.copy()

Hey there,
How did you manage to fix this error?
I’ve got the same problem, but waking up the remote from sleep before issuing the command isn’t working for me.

Managed to finally fix it through trial and error.
I think taking the batteries out of the remote and putting them back in made the remote accept the OTA, almost like a hard reset.
If for some reason the first attempt after putting the batteries in failed or abruptly pauses during the update, then I had to take the batteries out and put them back in again, otherwise I’d just get that error over and over.

As FYI -
With H.A Core 2024.5.4 installed on my raspberry 4, the OTA notifications showed my Ikea Strybar was on this very old version. I was unable to get it to take the update till I seen your comment here on the battery insertion… very helpful. I found that in Z2M clicking on the Permit Join button and then immediately push in the last battery initiated the download finally from Ikea. Automations were not working post that install now on v2.4.11 from v1.0.024. We removed and reinstalled the device and were good to go one again. Pairing was initiated via 4 quick clicks to the pairing button (inside). No scripts required. Hope this helps someone… Rick M

Thanks to everyone that contributes to a solution here. I’m on HA 2024.10.4 using a SONOFF ZBDongle-P and Zigbee2MQTT version: 1.40.2-1. Got in the mail today from IKEA a Styrbar remote that had this old firmware 1.0.024. At first seemed impossible to update. Probably would have worked the workarounds to use deconz and options where one would have to purchase another zigbee gateway, but the trick of pulling out one battery, press permit join all, insert battery and within around 3 seconds press the update button on the OTA of Zigbee2MQTT did indeed start the upgrade.