Custom Component: Nikobus

update:

so today we are at that stage

{
    "nikobus_button": [
        {
            "description": "BT_GF_Living_Sofa_Wall_Light_Up",
            "address": "004E2C",
            "impacted_module": [
                {
                    "address": "0E6C",
                    "group": "1"
                }
            ],
            "discovered_info": [
                {
                    "type": "IR Button with 4 Operation Points",
                    "model": "05-348",
                    "address": "0D1C80",
                    "channels": 4,
                    "key": "1C"
                }
            ]
        },

The idea is now to go for

{
    "nikobus_button": [
        {
            "description": "BT_GF_Living_Sofa_Wall_Light_Up",
            "address": "004E2C",
            "impacted_module": [
                {
                    "address": "0E6C",
                    "group": "1"
                }
            ],
            "discovered_info": [
                {
                    "type": "IR Button with 4 Operation Points",
                    "model": "05-348",
                    "address": "0D1C80",
                    "channels": 4,
                    "key": "1C"
                }
            "discovered_link": [
                {
                    "impacted_module": "0E6C",
                    "output": 7,
                    "timer": null,
                    "mode": "M01 On/Off"
                }

            ]
        },

So I will be adding “discovered_link” that will report the impacted_module of the button, the module output, its mode ‘on/off’ / push button / etc and associated timer if any.

BUT I will always rely on the user provided data, this section :

        {
            "description": "BT_GF_Living_Sofa_Wall_Light_Up",
            "address": "004E2C",
            "impacted_module": [
                {
                    "address": "0E6C",
                    "group": "1"
                }
            ],

and if and only if, 1- the button is not existing or 2- the user has applied no customization then I will failback to the discovered data.

So no impact to your current setup and ways of working, data is enriched only if you decide to run the discovery service, it’s a manual process that only a user can trigger.

a. You could keep asis and decide not to run the discovery.

b. You could run discovery with you current data and setup without impact (you can then read the button file to search for discrenpencies, etc…) No more manual updating of the file might you update your Nikobus config, just run discovery again.

c. One could setup nikobus without any user input, if that’s the wish. fully relying on discovery vs user inputs.

As was not far from completion, then I tried the discovery on dimmer modules. I could never imagine someone would code a protocol to extract data from modules that is almost different by module type… anyway, I know how to reverse engineer them, will just need more time…

eg,
one inventory item from a switch or shutter module
$0510$2E055B300477C95802200573EE8002310677C9264710
on from a dimmer
$0522$1E6C0E5F1550000300B4FF452CA9

Do not ask why they are not using the same form of payload for same purpose :slight_smile: back to the drawing board.

Quick update:
Switch, Dimmer and Shutter Nikobus button are discovered just fine together with their relation to module outputs.

eg

{
    "module_address": "4707",
    "channels": {
        "Channel 1": [
            {
                "button_address": "1D054A",
                "push_button_address": "94A82E",
                "button_key": "1",
                "timer": "None",
                "mode": "M01 (On / off)"
            },
            {
                "button_address": "1CFBA0",
                "push_button_address": "C177CE",
                "button_key": "3",
                "timer": "0s",
                "mode": "M03 (Off, with operation time)"
            },
            {
                "button_address": "1DF256",
                "push_button_address": "5A93EE",
                "button_key": "2",
                "timer": "0s",
                "mode": "M03 (Off, with operation time)"
            }
        ],

I need to deep dive on 2 types of button, IR Buttons and 8 Position Buttons. They do not behave like others.

I will release a version (beta) that does not yet manages those button types, for the testers to validate and provide feedback. enjoy the weekend !

Release 0.4.7 is out, if you wish to experiment with discovery, it has today no impact on your installation other that adding data to the nikobus_button_config.json so it’s safe to try out.

! PCLink Mandatory !

!! Take a copy of your original json configuration file !! Better safe than sorry :slight_smile:

Step 1 ) run the discovery without parameter, call the service query_module_inventory from the developer tools. This will populate “discovered_info” which is mandatory data for Step 2 success. it also creates a nikobus_module_discovered.json file in the config directory.

Step 2 ) once step 1 is complete, wait 5 minutes or check debuglog for discovery completion. run the discovery again but this time with “module_address : ALL” or a specific module address if you want to limit the discovery to a specific module.

This will populate “discovered_link”

Now, in your config directory, enjoy an enhanced nikobus_button_config.json file`

discovered_info and discovered_link have been added by reading your installation configuration from Nikobus.

        {
            "description": "BT_GF_Garage_Garden_Light_On",
            "address": "00854E",
            "impacted_module": [
                {
                    "address": "4707",
                    "group": "2"
                }
            ],
            "discovered_info": [
                {
                    "type": "Button with 4 Operation Points",
                    "model": "05-346",
                    "address": "1CA840",
                    "channels": 4,
                    "key": "1C"
                }
            ],
            "discovered_link": {
                "module_address": "4707",
                "channel": "Channel 12",
                "mode": "M01 (On / off)",
                "timer": "None"
            }
        },

You will / might get error in the log if you have IR buttons and / or 8 buttons switches. please revert with findings

So this is what to expect for IR or 8 buttons switches

I still have some ghosting lights, every now and then. With ghosting, I mean a light turns on without any script, automation or human action triggering this light intentionally. I think what causes this: sometimes corrupt data is received from the nikobus controller, and then the integration updates its internal state with a wrong value, and when one or more outputs of the corrupted addressgroup is triggered, that wrong state is used in a command towards the nikobus controller, causing a light to turn on.

Some logging:

2025-03-02 08:55:51.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE18202000000FFFF006A9E0E
2025-03-02 08:55:51.034 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000FFFF00 (Address: 82E1)
2025-03-02 08:57:57.031 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE18202000000FFFF006A9E0E
2025-03-02 08:57:57.031 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000FFFF00 (Address: 82E1)
2025-03-02 09:00:02.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE18202000000FFFF06A9E0E
2025-03-02 09:00:02.034 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000FFFF06 (Address: 82E1)
2025-03-02 09:02:07.047 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE182020000000000FFB8F2E7
2025-03-02 09:02:07.047 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 0000000000FF (Address: 82E1)

You can see the first 2 incoming state updates are still correct.
In the 3rd incoming state a 0 byte is missing, in the state of the last (6th) output of that group, however the integration is taking the next byte that is no part of the value (a 6 in this case).
Some time later:

2025-03-02 09:16:48.046 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE182020000000000FFB8F2E7
2025-03-02 09:16:48.046 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 0000000000FF (Address: 82E1)
2025-03-02 09:18:53.048 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE18202000000000FFB8F2E7
2025-03-02 09:18:53.049 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000000FFB (Address: 82E1)
2025-03-02 09:20:58.040 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE182020000000000FFB8F2E7
2025-03-02 09:20:58.040 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 0000000000FF (Address: 82E1)
2025-03-02 09:23:03.042 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE18202000000000FFB8F2E7
2025-03-02 09:23:03.043 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000000FFB (Address: 82E1)
2025-03-02 09:25:08.045 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE182020000000000FFB8F2E7
2025-03-02 09:25:08.045 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 0000000000FF (Address: 82E1)
2025-03-02 09:27:13.047 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE18202000000000FFB8F2E7
2025-03-02 09:27:13.048 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000000FFB (Address: 82E1)
2025-03-02 09:29:18.039 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE182020000000000FFB8F2E7
2025-03-02 09:29:18.040 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 0000000000FF (Address: 82E1)

Same kind of weirdness, starting with a missing byte…

I don’t why that that bad data is coming in, perhaps my installation really is getting too old, or the serial cable is faulty… Anyway, would it be possible to make that piece of code a little more robust. Perhaps check the length of the incoming data, or isn’t there a checksum involved? I would suggest to just drop data notification if it smells corrupt, and log why.

Full logging of that first case:

2025-03-02 09:00:01.094 DEBUG (MainThread) [custom_components.nikobus.coordinator] Refreshing data for module address: 82E1
2025-03-02 09:00:01.094 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Getting output state - Address: 82E1, Group: 1
2025-03-02 09:00:01.094 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Queueing command: $1012E18273D620
2025-03-02 09:00:01.095 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Command queued: $1012E18273D620
2025-03-02 09:00:01.794 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Dequeued command: $1012E18273D620
2025-03-02 09:00:01.794 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Processing command: $1012E18273D620 with address: 82E1
2025-03-02 09:00:01.795 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Sending command $1012E18273D620 to address 82E1, waiting for answer
2025-03-02 09:00:01.795 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Prepared signals: ACK=$0512, ANSWER=$1CE182, COMMAND=$1012E18273D620, ADDRESS=82E1
2025-03-02 09:00:01.796 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Attempt 1/3 waiting for ACK: $0512, ANSWER: $1CE182
2025-03-02 09:00:02.032 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: $0512$1CE18202000000FFFF06A9E0E
2025-03-02 09:00:02.033 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Manual refresh command answer: $0512$1CE18202000000FFFF06A9E0E
2025-03-02 09:00:02.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CE18202000000FFFF06A9E0E
2025-03-02 09:00:02.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] ACK received
2025-03-02 09:00:02.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Answer received
2025-03-02 09:00:02.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Extracted state from message: 000000FFFF06
2025-03-02 09:00:02.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Received valid state from device.
2025-03-02 09:00:02.034 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000FFFF06 (Address: 82E1)

I see that the bolded entry is missing a zero, as you noted. I’ll check if I can reverse the CRC; if not, I’ll simply verify the payload length for validity.

$0512$1CE18202000000FFFF006A9E0E
$0512$1CE18202000000FFFF006A9E0E
$0512$1CE18202000000FFFF06A9E0E
$0512$1CE182020000000000FFB8F2E7

Do you have to ACK that message? If so, don’t ACK it when you ignore it :wink:

Indeed :slight_smile:

Here is a quick fix for the nkblistener.py code but still have to manage the ACK.

I will have to do the same for the other commands, I will check if I can centralize it.

            if any(message.startswith(refresh) for refresh in MANUAL_REFRESH_COMMAND):
                _LOGGER.debug("Manual refresh command answer: %s", message)
                
                # Check if the message meets the expected length criteria
                EXPECTED_MESSAGE_LENGTH = 32
                if len(message) != EXPECTED_MESSAGE_LENGTH:
                    _LOGGER.error(
                        "Invalid message length: %d (expected: %d).",
                        len(message),
                        EXPECTED_MESSAGE_LENGTH
                    )
                    return
                
                if not message.startswith(BUTTON_COMMAND_PREFIX):
                    await self.response_queue.put(message)
                return

I will keep the ACK; When a wrong payload is received it is not added to the queue for processing, ACK will timeout and send the request again. hopefully this time the payload is correct. It will do it 3 times before to report a general failure.

I am not sure I understand “I will keep the ack”.
However, 3 retries is indeed the wanted behaviour, so go ahead :slight_smile:

Release 0.4.8 is out, have a try and let me know.

Good evening !

New version is installed, thanks.
(yes, I restarted the device, and yes, feedback-module is still not checked in the config)

1 Like

Quick fix looking at the expected length of the payload. If you receive the expected length but with corrupted data, you will still be in trouble.

I will look at CRC checks for the next release

Interesting
$1CE182020000000000FFB8F2E7

1C is actually 28, the length of the payload.

Is it? What payload has length 28?

I will test further, but basically the CRC checks are working so far

Manual refresh command answer: $0512$1C059100000000000000E858B3
CRC8 match: calculated B3, expected B3

2025-03-02 22:35:24.626 DEBUG (MainThread) [custom_components.nikobus.coordinator] Refreshing data for module address: 9105
2025-03-02 22:35:24.626 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Getting output state - Address: 9105, Group: 1
2025-03-02 22:35:24.626 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Queueing command: $101205918DF2EB
2025-03-02 22:35:24.626 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Command queued: $101205918DF2EB
2025-03-02 22:35:25.327 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Dequeued command: $101205918DF2EB
2025-03-02 22:35:25.327 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Processing command: $101205918DF2EB with address: 9105
2025-03-02 22:35:25.327 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Sending command $101205918DF2EB to address 9105, waiting for answer
2025-03-02 22:35:25.327 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Prepared signals: ACK=$0512, ANSWER=$1C0591, COMMAND=$101205918DF2EB, ADDRESS=9105
2025-03-02 22:35:25.327 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Attempt 1/3 waiting for ACK: $0512, ANSWER: $1C0591
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: $0512$1C059100000000000000E858B3
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Manual refresh command answer: $0512$1C059100000000000000E858B3
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkblistener] CRC8 match: calculated B3, expected B3
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1C059100000000000000E858B3
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] ACK received
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Answer received
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Extracted state from message: 000000000000
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Received valid state from device.
2025-03-02 22:35:25.783 DEBUG (MainThread) [custom_components.nikobus.coordinator] State for group 1: 000000000000 (Address: 9105)
2025-03-02 22:35:25.784 DEBUG (MainThread) [custom_components.nikobus.coordinator] Updated module state for 9105: bytearray(b'\x00\x00\x00\x00\x00\x00')

CRC Checks are implemented: see Release Nikobus 0.4.9 · fdebrus/Nikobus-HA

1 Like

Several hours later, the CRC seems to be working.
However, I have another scenario with … issues :slight_smile:

  1. Bedroom lights are on.
  2. I press the button to turn off those lights
2025-03-04 08:11:49.082 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: #NDA0606
2025-03-04 08:11:49.083 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Button command received: #NDA0606
2025-03-04 08:11:49.083 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Handling button press for address: DA0606
2025-03-04 08:11:49.126 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: #NDA0606
2025-03-04 08:11:49.126 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Button command received: #NDA0606
2025-03-04 08:11:49.126 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Handling button press for address: DA0606
2025-03-04 08:11:49.285 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Button released for DA0606, duration: 0.20s
2025-03-04 08:11:49.285 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Discovering button at address: DA0606
2025-03-04 08:11:49.286 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Button found in config.
2025-03-04 08:11:49.286 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Processing button press for NikoKnop - Jarne - links onder with operation time: 0.00
2025-03-04 08:11:49.286 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Firing timer event nikobus_button_released for address: DA0606
2025-03-04 08:11:49.287 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Firing events nikobus_short_button_pressed for address: DA0606
  1. the lights go out in the bedroom, as expected.
  2. I wait half a second, and press another button to turn on the light in the corridor. Important remark: the lights in the bedroom are output 1, and the corridor is output 3 of the same group (1) of the same controller (91AD). Also, the first button is still linked within the nikobus controller, the second button has no function in the controller, only directly in home assistant. So the first button has (correct) impacted_module config, the second button does not. The corridor light is a zigbee bulb, so the output (3) in the controller is always ON. This is logged:
2025-03-04 08:11:49.650 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: #N5A0606
2025-03-04 08:11:49.651 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Button command received: #N5A0606
2025-03-04 08:11:49.651 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Handling button press for address: 5A0606
2025-03-04 08:11:49.694 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: #N5A0606
2025-03-04 08:11:49.694 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Button command received: #N5A0606
2025-03-04 08:11:49.695 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Handling button press for address: 5A0606
2025-03-04 08:11:49.738 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: #N5A0606
2025-03-04 08:11:49.738 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Button command received: #N5A0606
2025-03-04 08:11:49.739 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Handling button press for address: 5A0606
2025-03-04 08:11:49.787 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Getting output state - Address: 91AD, Group: 1
2025-03-04 08:11:49.788 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Queueing command: $1012AD9119251D
2025-03-04 08:11:49.788 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Command queued: $1012AD9119251D
2025-03-04 08:11:49.788 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Dequeued command: $1012AD9119251D
2025-03-04 08:11:49.788 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Processing command: $1012AD9119251D with address: 91AD
2025-03-04 08:11:49.789 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Sending command $1012AD9119251D to address 91AD, waiting for answer
2025-03-04 08:11:49.789 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Prepared signals: ACK=$0512, ANSWER=$1CAD91, COMMAND=$1012AD9119251D, ADDRESS=91AD
2025-03-04 08:11:49.789 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Attempt 1/3 waiting for ACK: $0512, ANSWER: $1CAD91
2025-03-04 08:11:49.907 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Button released for 5A0606, duration: 0.26s
2025-03-04 08:11:49.907 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Discovering button at address: 5A0606
2025-03-04 08:11:49.907 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Button found in config.
2025-03-04 08:11:49.907 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Processing button press for NikoKnop - Jarne - rechts onder with operation time: 0.00
2025-03-04 08:11:49.907 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Skipping module refresh due to missing address or group
2025-03-04 08:11:49.908 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Firing minimal event: nikobus_button_pressed with data: {'address': '5A0606'}
2025-03-04 08:11:49.908 DEBUG (MainThread) [custom_components.nikobus.binary_sensor] Button sensor 5A0606 detected a press event.
2025-03-04 08:11:49.919 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Firing timer event nikobus_button_released for address: 5A0606
2025-03-04 08:11:49.920 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Firing events nikobus_short_button_pressed for address: 5A0606
2025-03-04 08:11:49.921 INFO (MainThread) [homeassistant.components.automation.bureau_knop_start_licht_in_gang] Knop start licht in gang voor (2m): Running automation actions
2025-03-04 08:11:49.921 INFO (MainThread) [homeassistant.components.automation.bureau_knop_start_licht_in_gang] Knop start licht in gang voor (2m): Executing step call service
2025-03-04 08:11:49.922 INFO (MainThread) [homeassistant.components.script.licht_gang_voor_2min] Licht Gang Voor (2min): Running script sequence
2025-03-04 08:11:49.922 INFO (MainThread) [homeassistant.components.script.licht_gang_voor_2min] Licht Gang Voor (2min): Executing step call service
2025-03-04 08:11:49.923 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Setting output state - Address: 91AD, Channel: 3, Value: 255
2025-03-04 08:11:49.923 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Queueing command: $1E15AD91FFFFFF000000FFC3D507
2025-03-04 08:11:49.923 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Command queued: $1E15AD91FFFFFF000000FFC3D507
2025-03-04 08:11:49.923 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Command successfully queued.
2025-03-04 08:11:49.924 INFO (MainThread) [homeassistant.components.script.licht_gang_voor_2min] Licht Gang Voor (2min): Executing step call service
2025-03-04 08:11:49.969 INFO (MainThread) [homeassistant.components.script.licht_gang_voor_2min] Licht Gang Voor (2min): Executing step delay 0:02:00
2025-03-04 08:11:50.032 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: $0512$1CAD910000FFFF000000C8E594
2025-03-04 08:11:50.032 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Manual refresh command answer: $0512$1CAD910000FFFF000000C8E594
2025-03-04 08:11:50.032 DEBUG (MainThread) [custom_components.nikobus.nkblistener] CRC8 match: calculated 94, expected 94, message $1CAD910000FFFF000000C8E594
2025-03-04 08:11:50.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0512$1CAD910000FFFF000000C8E594
2025-03-04 08:11:50.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] ACK received
2025-03-04 08:11:50.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Answer received
2025-03-04 08:11:50.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Extracted state from message: 00FFFF000000
2025-03-04 08:11:50.033 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Received valid state from device.
2025-03-04 08:11:50.033 DEBUG (MainThread) [custom_components.nikobus.coordinator] Updated state for 91AD: bytearray(b'\x00\xff\xff\x00\x00\x00\xff\x00\xff\x00\x00\xff')
2025-03-04 08:11:50.034 DEBUG (MainThread) [custom_components.nikobus.nkbactuator] Firing event: nikobus_button_pressed with data: {'address': 'DA0606', 'button_operation_time': 0.0, 'impacted_module_address': '91AD', 'impacted_module_group': '1'}
2025-03-04 08:11:50.034 DEBUG (MainThread) [custom_components.nikobus.binary_sensor] Button sensor DA0606 detected a press event.
2025-03-04 08:11:50.734 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Dequeued command: $1E15AD91FFFFFF000000FFC3D507
2025-03-04 08:11:50.734 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Processing command: $1E15AD91FFFFFF000000FFC3D507 with address: 91AD
2025-03-04 08:11:50.734 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Sending command $1E15AD91FFFFFF000000FFC3D507 to address 91AD, waiting for answer
2025-03-04 08:11:50.734 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Prepared signals: ACK=$0515, ANSWER=$0EFFAD91, COMMAND=$1E15AD91FFFFFF000000FFC3D507, ADDRESS=91AD
2025-03-04 08:11:50.735 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Attempt 1/3 waiting for ACK: $0515, ANSWER: $0EFFAD91
2025-03-04 08:11:50.968 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Received message: $0515$0EFFAD91008B
2025-03-04 08:11:50.968 DEBUG (MainThread) [custom_components.nikobus.nkblistener] CRC8 match: calculated 8B, expected 8B, message $0EFFAD91008B
2025-03-04 08:11:50.968 DEBUG (MainThread) [custom_components.nikobus.nkblistener] Command acknowledged: $0515$0EFFAD91008B
2025-03-04 08:11:50.969 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Message received: $0515$0EFFAD91008B
2025-03-04 08:11:50.969 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] ACK received
2025-03-04 08:11:50.969 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Answer received
2025-03-04 08:11:50.969 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Extracted state from message: 8B
2025-03-04 08:11:50.969 DEBUG (MainThread) [custom_components.nikobus.nkbcommand] Received valid state from device.

As a result, the light in the corridor turns on (as expected) for 2 minutes, but also the lights in the bedroom turn on again (not wanted).
I see that the state response from the impacted_module request is not received yet, and I guess that’s the problem, however, shouldn’t the state of those lights/output (1) already be known without that response? After all, the lights in the bedroom turned off, so the integration has already sent the correct state towards the controller before that second button press.

Will look at, I also see that CRC and length check now report unexpected messages that were ignore before.

eg a button address #N829201 with $0512 as header, which is not supposed to happen. Well at least to my knowledge on this undocumented protocol :slight_smile:

Will fix both

First occurred: 8:09:46 AM (3 occurrences)
Last logged: 8:17:53 AM

* Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#N829201
* Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#N80DFFC
* Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#NFA93EE

Hi Frederic,

i updated to 0.4.9 and see in the system log, Home Assistant Core log these errors:

Deze fout is ontstaan door een aangepaste integratie.

Logger: custom_components.nikobus.nkblistener
Bron: custom_components/nikobus/nkblistener.py:102
integratie: Nikobus Integratie (documentatie, problemen)
Eerst voorgekomen: 3 maart 2025 om 19:58:22 (7 gebeurtenissen)
Laatst gelogd: 08:18:17

Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#NFD1182
Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#NAF5864
Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#NCF5864
Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#N84B464
Message length mismatch: got 13, expected 4 (based on length field 05). message $0512#N04F68E

Makes sense to investigate why these happen or is this only for creating visibility?

FYI

“Berging - Wasplaats doorgang #NFD1182” (Nikobus 8-button with feedback led) when this one was pushed, the feedback led did not turn on (out of sync)
“Gang boven - detectie - beweging of licht #NAF5864” - movement
“Gang boven - detectie - 3 LEDs #NCF5864” (Nikobus movent sensor) - action following the movement
“WC boven - detectie #N84B464” (Nikobus movement sensor) - movement
“Gang boven - Open #N04F68E” (Nikobus 4-button, no feedbackled) - open the roller

Does this make sense to you or do you also want debug logging?

thank you ! I will have to split the dispatch logic, may be…

A message with $0512 or $0517 as header was supposed to be a answer from a manual refresh command having the current status for a module address with group 1 data $0512 or group 2 data $0517.

We now see that it can also have a button address, question is ? when ?

As you push the button ? other ? before I alter the logic, I need to understand the when we get that button address and what to do with ? refresh data ? process ? drop ? …

More debug before fixing this logic which is working fine for data refresh.

could try with, and see result, with this Nikobus, only thing I can do is retry on error.

So a $0512#N04F68E will trigger a N04F68E button press action, which is not happening in the current code because of the $0512 header.

MANUAL_REFRESH_COMMAND: Final[tuple[str, str]] = ("$0512", "$0517")
BUTTON_COMMAND_PREFIX: Final[str] = "#N"

# Check if the message contains a button command
if BUTTON_COMMAND_PREFIX in message:
    _LOGGER.debug("Button command received: %s", message)
    # If the message starts with a refresh command, adjust the slice accordingly
    if any(message.startswith(refresh) for refresh in MANUAL_REFRESH_COMMAND):
        button_code = message[6:12]
    else:
        button_code = message[2:8]
    await self._actuator.handle_button_press(button_code)
    return

# Check if the message is a manual refresh command
if any(message.startswith(refresh) for refresh in MANUAL_REFRESH_COMMAND):
    # Example: "$0512$1C059100000000000000E858B3" (expected length: 32 characters)
    _LOGGER.debug("Manual refresh command answer: %s", message)
    if not self.validate_crc(message):
        return
    await self.response_queue.put(message)
    return

Are you sending ‘button press events’ from your homeassistant itself, to simulate a real button press and trigger the nikobus logic that way?