How to decommission all commissioned EnOcean switches

Hello, I'm an engineer living in Japan.

【Development environment】
"SDK:nRF Connect SDK v2.4.2"
"IDE:VSCode 1.83.1"
"PCA10040(nRF52832)" x 1 (center)
"PTM215B" EnOcean x 1 (peripheral equipment)
"PTM535BZ" + "ECO260" x 1 (peripheral equipment)

This is a question regarding decommissioning of the EnOcean switch.

We are proceeding with development based on the eneocean sample program stored in SKD.
Commissioning is fine and working fine.
However, I am having trouble decommissioning the EnOcean switch.

I previously asked a similar question on DevZone and received the following response.

Answer 1)
If you want to decommission all switches you can use bt_enocean_foreach().

Answer 2)
EnOcean switches can be decommissioned individually using bt_enocean_decommission().

I tried to delete all registered EnOcean switches based on the answer above, but I was unable to delete them.
I'm guessing that the method of specifying the arguments is probably wrong, but even when I look at the reference, I can't find any specific code, so I'm having a hard time.
I searched the internet but couldn't find any useful information.

question)
Please tell me how to delete all commissioned EnOcean switches.
It would be helpful if you could tell me with sample code.

Thank you.

Parents
  • Hi, 
    I would suggest to continue the ticket 316077 with Terje. We should avoid creating multiple questions of the same topic. 
    Please try to get familiar with bt_enocean_decommission() function and check that you can decommission one device at a time. 

    The effect of calling bt_enocean_foreach() is to loop through each of the enocean device in the database. For example if you do bt_enocean_foreach(my_function, NULL) then you will have a call to your "my_function() " function on each of the enocean device. In your my_function() you can decommision the device by calling bt_enocean_decommission().


    Please see how it's implemented in \nrf\subsys\bluetooth\mesh\vnd\silvair_enocean_srv.c


  • Thank you for your reply Hung Bui.

    >We recommend continuing ticket 316077 with Terje. Creating multiple questions on the same topic should be avoided.
    →I'm sorry. Since there was no response to ticket No. 316077 even after 5 days had passed, we decided that the ticket was invalid and started asking again. Once I reach a conclusion, I will write the answer on ticket No. 316077.

    Back to the main topic.
    The answer is a little long, but I will summarize what I confirmed below.

    I checked the operation by referring to the answer you provided and "silvair_enocean_srv.c".
    As a result, I was able to associate "bt_enocean_decommission()" with main.c "bt_enocean_foreach()" and make it work, but I was unable to decommission the EnOcean device.

    I believe that the reason is that the device information (bt_enocean_device *dev) specified in the argument of "bt_enocean_decommission()" cannot be obtained in main.c.

    Therefore, although I don't want to do this, I decided to add the "bt_enocean_all_decommission" function to "enocean.c" and call it in main.c.

    void bt_enocean_all_decommission()
    {
      for (int i = 0; i < ARRAY_SIZE(devices); ++i) {
       if (devices[i].flags & FLAG_ACTIVE) {
        bt_enocean_decommission(&devices[i]);
       }
      }
    }

    As a result, the following error occurred in "bt_enocean_decommission()" and it could not be deleted.

    Error message)
    ASSERTION FAIL @ WEST_TOPDIR/zephyr/kernel/mutex.c:101
    E: r0/a1: 0x00000004 r1/a2: 0x00000065 r2/a3: 0x00000001
    E: r3/a4: 0x0000fbc9 r12/ip: 0x00000000 r14/lr: 0x00012d17
    E: xpsr: 0x41000016
    E: Faulting instruction address (r15/pc): 0x00015982
    E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
    E: Fault during interrupt handling

    E: Current thread: 0x20001780 (unknown)
    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    I: 6 sectors of 4096 bytes
    I: alloc wra: 0, fb8
    I: data wra: 0, 44
    EnOcean Device loaded: E2:15:10:00:01:BB (random)
    EnOcean is ready!

    Based on the above results, we changed the "bt_enocean_all_decommission" function as follows.

    void bt_enocean_all_decommission()
    {
      for (int i = 0; i < ARRAY_SIZE(devices); ++i) {
       if (devices[i].flags & FLAG_ACTIVE) {
         devices[i].flags = 0;

         if (cb->decommissioned) {
          cb->decommissioned(&devices[i]);
         }
       }
      }
    }

    As a result, we were able to confirm that the EnOcean switch was deleted without any errors. Also, after the deletion, I commissioned 4 EnOcean switches and they worked fine.

    However, I am concerned about the following points.

    1. Edited "enocean.c". It is not completed within main.c.
    2. It is highly likely that the device information of the registered EnOcean switch has not been completely deleted.

    Question 1)
    Please let me know if there is a way to delete all EnOcean switches just by editing main.c.
    I would like to know in detail how to obtain device information within main.c.
    *The sample program uses EnOcean.

    Question 2)
    Please let me know if you know the cause of the error that occurred in the "bt_enocean_decommission()" function.

    Thank you.

  • Hi 輝隆,

    If you followed our suggestion and it didn't work, shouldn't you give us more information about how you implemented it and describe what didn't work ?

    Attached you will find the modified enocean sample (NCS v2.5.0) with a small change to add a decommision button that will decommision all Enocean nodes. I only have one Enocean to test but it should work for multiple nodes. 

    This has been added: 

    static void find_and_decommission(struct bt_enocean_device *dev, void *user_data)
    {
    		bt_enocean_decommission(dev);
    }
    
    static void button_changed(uint32_t button_state, uint32_t has_changed)
    {
    	uint32_t buttons = button_state & has_changed;
    	int err = 0;
    
    		if (buttons & DK_BTN1_MSK) {
    		printk("button pressed ");
    		bt_enocean_foreach(find_and_decommission, NULL);
    	}
    
    }

    When you press button 1 on the DK you will see this: 

    enocean.zip

Reply
  • Hi 輝隆,

    If you followed our suggestion and it didn't work, shouldn't you give us more information about how you implemented it and describe what didn't work ?

    Attached you will find the modified enocean sample (NCS v2.5.0) with a small change to add a decommision button that will decommision all Enocean nodes. I only have one Enocean to test but it should work for multiple nodes. 

    This has been added: 

    static void find_and_decommission(struct bt_enocean_device *dev, void *user_data)
    {
    		bt_enocean_decommission(dev);
    }
    
    static void button_changed(uint32_t button_state, uint32_t has_changed)
    {
    	uint32_t buttons = button_state & has_changed;
    	int err = 0;
    
    		if (buttons & DK_BTN1_MSK) {
    		printk("button pressed ");
    		bt_enocean_foreach(find_and_decommission, NULL);
    	}
    
    }

    When you press button 1 on the DK you will see this: 

    enocean.zip

Children
  • Thank you for your reply, Funbui.
    Also, thank you for providing the sample program.

    In conclusion, I was able to successfully decommission the EnOcean switch just by editing "main.c".
    Therefore, editing "enocean.c" is no longer necessary.

    There was no problem with the following description given in the previous answer.

    ■Delete all EnOcean switches (described in main.c)
    static void find_and_decommission(struct bt_enocean_device *dev, void *user_data)
    {
      bt_enocean_decommission(dev);
    }
    bt_enocean_foreach(find_and_decommission, NULL);

    As a result of analysis, the cause of the failure was not the decommissioning of the EnOcean switch, but the button interrupt processing.
    The button interrupt processing was based on the code of a sample program called "button", but that seems to have been the problem.

    By changing the interrupt processing to the code shown below in the sample code, I was able to get it to work without any problems.

    ■Button interrupt processing code
    static void button_changed(uint32_t button_state, uint32_t has_changed)
    {
    Processing content…
    }
    err = dk_buttons_init(button_changed);

    I'm not sure why, but if I don't change the interrupt handling, the error message I answered last time is displayed and the decommissioning process fails.

    Thank you for your cooperation.

Related