BLE Mesh: Provisioner received wrong message size.

Hello, I'm working with BLE Mesh using NRF52840

- Our setup: NRF-Connect-SDK 2.1.0

- Summary of our project.

   + Provisioner node to control lightness for all nodes in the network system. Our provisioner code which I custom from an example \zephyr\samples\bluetooth\mesh_provisioner to add one client to send message to the server (on another node). 

   + Lightness node: used to control the lightness of the LED. Our lightness node code which I use from an example \nrf\samples\bluetooth\mesh\light_ctrl.

1. If I have sent a message with ack type from the provisioner node to the lightness node. 

                 if (bt_mesh_model_pub_is_unicast(light_cli[0].client.model))
                {

                        err = bt_mesh_lightness_cli_light_set(&light_cli[0].client, NULL,
                                        &set, NULL);
                        if(err)
                        {
                            LOG_INF("Client Failed to public state change: %d", err);
                        }
                        else
                        {                        
                            light_cli[0].lvl = set.lvl;
                            LOG_INF("Public address: 0x%04x - lightness %d - test idx %d", light_cli[0].client.model->pub->addr, set.lvl, test_idx++);

                            // Wait for the semaphore from server response callback about 2 seconds
                            err = k_sem_take(&sem_srv_rsp, K_MSEC(2000));

                            if (err == -EAGAIN)
                            {
                                LOG_INF("Failed to take the semaphore from light status handler, address = 0x%04x", light_cli[0].client.model->pub->addr);
                            }
                            else if(!err)
                            {
                                continue;
                            }
                        }
                    }

Then, the Provisioner node received a response (callback) in the light status function that we registered when initialing the client control. Including current value and target value 

struct bt_mesh_lightness_status {
    /** Current Lightness level. */
    uint16_t current;
    /** Target Lightness level. */
    uint16_t target;
    /**
     * Time remaining of the ongoing transition in milliseconds, or
     * @em SYS_FOREVER_MS. If there's no ongoing transition,
     * @c remaining_time is 0.
     */
    int32_t remaining_time;
}; . And the result was as I expected.
 
For instance: When the Provisioner node sends "1", then it receives "current value = 0, target value = 1",
                      When the Provisioner node sends "2", then it receives "current value =1, target value =2", etc
2. If I enable CONFIG_BOOTLOADER_MCUBOOT=y in prj.conf file of provisioner node code to add MCUBOOT and for updating firmware purposes. I run code and test and have an issue.
In particular about the issue:
+ current value = 0, target value = 1 was wrong 
+ I checked in light status function at lightness_cli.c file, it is the received handler and callback to light status function on the application. 
static int light_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
      struct net_buf_simple *buf, enum light_repr repr)
{
  LOG_INF("[Quoc] light_repr: %d", repr);

  if (buf->len != BT_MESH_LIGHTNESS_MSG_MINLEN_STATUS &&
      buf->len != BT_MESH_LIGHTNESS_MSG_MAXLEN_STATUS) {
    return -EMSGSIZE;
  }

  struct bt_mesh_lightness_cli *cli = model->user_data;
  struct bt_mesh_lightness_status status;
  struct bt_mesh_lightness_status *rsp;

  LOG_INF("[Quoc] Raw buf len: %d", buf->len);

  status.current = repr_to_light(net_buf_simple_pull_le16(buf), repr);
  if (buf->len == 3) {
    LOG_INF("[Quoc] buf->len == 3");
    status.target =
      repr_to_light(net_buf_simple_pull_le16(buf), repr);
    status.remaining_time =
      model_transition_decode(net_buf_simple_pull_u8(buf));
  } else {
    LOG_INF("[Quoc] Else: %d", buf->len);
    status.target = status.current;
    status.remaining_time = 0;
  }

  if (bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, op_get(LIGHTNESS_OP_TYPE_STATUS, repr),
              ctx->addr, (void **)&rsp)) {
    *rsp = status;
    bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
  }

  LOG_INF("[Quoc] Status - target = %d, current = %d", status.target, status.current);

  if (cli->handlers && cli->handlers->light_status) {
    cli->handlers->light_status(cli, ctx, &status);
  }

  return 0;
}
and the condition if (buf->len == 3) was wrong). The buf->len is equal to 0 and it goes to the else case and leads to the current value and target value wrong on the application.
Could you investigate and help me with this case? It seems to be related to the bt stack when I enable MCUBOOT or other reasons. 
Thank you in advance and appreciate your support.
 
Tôi đã kiểm tra
Parents
  • Hi,

    For instance: When the Provisioner node sends "1", then it receives "current value = 0, target value = 1",
                          When the Provisioner node sends "2", then it receives "current value =1, target value =2", etc

    To me it looks like this is working.

    1. Before you send the signal, the light has both current value 0 and target value 0.
    2. When you send the signal "1", the light has still brightness value 0, but its target is set to 1
    3. When you send the signal "2" after the light has changed its brightness to 1, its current brightness is 1 with a new target brightness = 2
    + current value = 0, target value = 1 was wrong 

    Could you also elaborate on what you expect to see as a received value? What do you mean by 

    2. If I enable CONFIG_BOOTLOADER_MCUBOOT=y in prj.conf file of provisioner node code to add MCUBOOT and for updating firmware purposes.

    We could use some more information from you to determine the issue. Could you provide us with

    1. A full log from the device when the issue is present
    2. A full log from the device 
    3. Your enabled settings in the project config file

    Also make sure that you do a full erase between each time you program the DK to ensure that no artifacts from the previous build still present. In especially Mesh, there are some configuration settings that are stored in flash.

    Also, if you could insert large logs and/or code snippets in the code box tool (shown in the image below), it makes it easier to navigate the case in the future! :) 

    In general for adding firmware upgrade support, I typically recommend reading this guide written by my colleague. Here you will also find a sample + information about how to create upgradable bootloader + DFU support for the nRF5340

    Kind regards,
    Andreas

  • Thanks for your reply: 

    1. 

    To me it looks like this is working.

    1. Before you send the signal, the light has both current value 0 and target value 0.
    2. When you send the signal "1", the light has still brightness value 0, but its target is set to 1
    3. When you send the signal "2" after the light has changed its brightness to 1, its current brightness is 1 with a new target brightness = 2
    + current value = 0, target value = 1 was wrong 

    Could you also elaborate on what you expect to see as a received value? What do you mean by 

    Yes, this is working normally as I expected and the same as you mentioned above. But the issue actually occurs when I enable the CONFIG_BOOTLOADER_MCUBOOT=y setting and leads to "current value and target value was wrong ".

     

    00> I: Provisioning I: Public address: 0x0002 - lightness 2 - test idx 2
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 7: 824e0100020001
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 5
    00> I: [Quoc] buf->len == 3
    00> I: [Quoc] Status - target = 2, current = 1
    00> I: Light control client Received response: 1 2 100 from address 0x0002
    - The log above is as I expected, "Raw buf len = 5" and "Status - target = 2, current = 1"
     
    00> I: Public address: 0x0002 - lightness 2 - test idx 2
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0100
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 1, current = 1
    00> I: Light control client Received response: 1 1 0 from address 0x0002
    - The log above is as unexpected, "Raw buf len = 2" and "Status - target = 1, current = 1" -> The size is wrong. I only enable CONFIG_BOOTLOADER_MCUBOOT=y on prj.conf file. All of the remaining configurations are still original
     
     
    2. I attached a log in case the message size is right, or message size is wrong, prj.conf file, and the code that I send and received a message on below:
     
    00> *** Booting Zephyr OS build be360e7db2db  ***
    00> I: build time: Nov  8 2022 22:21:24
    00> 
    00> I: Initializing all threads in the application!
    00> I: The second firmware
    00> I: Initializing hw comm parse thread successful
    00> I: Initialize hardware parse thread!
    00> I: Initializing...
    00> I: 8 Sectors of 4096 bytes
    00> I: alloc wra: 0, e30
    00> I: data wra: 0, 2ec
    00> I: SoftDevice Controller build revision: 
    00> I: 33 78 2a 18 20 f5 61 61 |3x*. .aa
    00> I: a6 8b 77 60 62 83 39 2a |..w`b.9*
    00> I: 7c f1 14 e4             ||...    
    00> I: HW Platform: Nordic Semiconductor (0x0002)
    00> I: HW Variant: nRF52x (0x0002)
    00> I: Firmware: Standard Bluetooth controller (0x00) Version 51.10872 Build 1643454488
    00> I: No ID address. App must call settings_load()
    00> I: Bluetooth initialized
    00> I: Loading stored settings
    00> I: Identity: F7:E3:F6:38:F0:3B (random)
    00> I: HCI: version 5.3 (0x0c) revision 0x1136, manufacturer 0x0059
    00> I: LMP: version 5.3 (0x0c) subver 0x1136
    00> I: Mesh initialized
    00> I: Using stored CDB
    00> I: Primary Element: 0x0001
    00> I: Using stored settings
    00> I: Add public address: 0x0002
    00> I: Provisioning I: Public address: 0x0002 - lightness 0 - test idx 0
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e3c00
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 60, current = 60
    00> I: Light control client Received response: 60 60 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 1 - test idx 1
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0000
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 0, current = 0
    00> I: Light control client Received response: 0 0 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 2 - test idx 2
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0100
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 1, current = 1
    00> I: Light control client Received response: 1 1 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 3 - test idx 3
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0200
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 2, current = 2
    00> I: Light control client Received response: 2 2 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 4 - test idx 4
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0300
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 3, current = 3
    00> I: Light control client Received response: 3 3 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 5 - test idx 5
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0400
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 4, current = 4
    00> I: Light control client Received response: 4 4 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 6 - test idx 6
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0500
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 5, current = 5
    00> I: Light control client Received response: 5 5 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 7 - test idx 7
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0600
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 6, current = 6
    00> I: Light control client Received response: 6 6 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 8 - test idx 8
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0700
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 7, current = 7
    00> I: Light control client Received response: 7 7 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 9 - test idx 9
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0800
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 8, current = 8
    00> I: Light control client Received response: 8 8 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 10 - test idx 10
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0900
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 9, current = 9
    00> I: Light control client Received response: 9 9 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 11 - test idx 11
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0a00
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 10, current = 10
    00> I: Light control client Received response: 10 10 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 12 - test idx 12
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0b00
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 11, current = 11
    00> I: Light control client Received response: 11 11 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 13 - test idx 13
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0c00
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 12, current = 12
    00> I: Light control client Received response: 12 12 0 from address 0x0002
    00> I: Public address: 0x0002 - lightness 14 - test idx 14
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 4: 824e0d00
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 2
    00> I: [Quoc] Else: 0
    00> I: [Quoc] Status - target = 13, current = 13
    00> I: Light control client Received response: 13 13 0 from address 0x0002
    (Connection lost)
    00> *** Booting Zephyr OS build be360e7db2db  ***
    00> I: build time: Nov  8 2022 22:18:52
    00> 
    00> I: Initializing all threads in the application!
    00> I: The second firmware
    00> I: Initializing hw comm parse thread successful
    00> I: Initialize hardware parse thread!
    00> I: Initializing...
    00> I: 8 Sectors of 4096 bytes
    00> I: alloc wra: 0, e40
    00> I: data wra: 0, 2d8
    00> I: SoftDevice Controller build revision: 
    00> I: 33 78 2a 18 20 f5 61 61 |3x*. .aa
    00> I: a6 8b 77 60 62 83 39 2a |..w`b.9*
    00> I: 7c f1 14 e4             ||...    
    00> I: HW Platform: Nordic Semiconductor (0x0002)
    00> I: HW Variant: nRF52x (0x0002)
    00> I: Firmware: Standard Bluetooth controller (0x00) Version 51.10872 Build 1643454488
    00> I: No ID address. App must call settings_load()
    00> I: Bluetooth initialized
    00> I: Loading stored settings
    00> I: Identity: F7:E3:F6:38:F0:3B (random)
    00> I: HCI: version 5.3 (0x0c) revision 0x1136, manufacturer 0x0059
    00> I: LMP: version 5.3 (0x0c) subver 0x1136
    00> I: Mesh initialized
    00> I: Using stored CDB
    00> I: Primary Element: 0x0001
    00> I: Using stored settings
    00> I: Add public address: 0x0002
    00> I: Provisioning I: Public address: 0x0002 - lightness 2 - test idx 2
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 7: 824e0100020001
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 5
    00> I: [Quoc] buf->len == 3
    00> I: [Quoc] Status - target = 2, current = 1
    00> I: Light control client Received response: 1 2 100 from address 0x0002
    00> I: Public address: 0x0002 - lightness 3 - test idx 3
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 7: 824e0200030001
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 5
    00> I: [Quoc] buf->len == 3
    00> I: [Quoc] Status - target = 3, current = 2
    00> I: Light control client Received response: 2 3 100 from address 0x0002
    00> I: Public address: 0x0002 - lightness 4 - test idx 4
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 7: 824e0300040001
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 5
    00> I: [Quoc] buf->len == 3
    00> I: [Quoc] Status - target = 4, current = 3
    00> I: Light control client Received response: 3 4 100 from address 0x0002
    00> I: Public address: 0x0002 - lightness 5 - test idx 5
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 7: 824e0400050001
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 5
    00> I: [Quoc] buf->len == 3
    00> I: [Quoc] Status - target = 5, current = 4
    00> I: Light control client Received response: 4 5 100 from address 0x0002
    00> I: Public address: 0x0002 - lightness 6 - test idx 6
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 7: 824e0500060001
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 5
    00> I: [Quoc] buf->len == 3
    00> I: [Quoc] Status - target = 6, current = 5
    00> I: Light control client Received response: 5 6 100 from address 0x0002
    00> I: Public address: 0x0002 - lightness 7 - test idx 7
    00> I: [Quoc]app_idx 0x0000 src 0x0002 dst 0x0001
    00> I: [Quoc]len 7: 824e0600070001
    00> I: [Quoc]OpCode 0x0000824e
    00> I: [Quoc] light_repr: 0
    00> I: [Quoc] Raw buf len: 5
    00> I: [Quoc] buf->len == 3
    00> I: [Quoc] Status - target = 7, current = 6
    00> I: Light control client Received response: 6 7 100 from address 0x0002
    
    # Logging stopped @ 08 Nov 2022 22:19:44
    
    # CONFIG_INIT_STACKS=y
    CONFIG_ASSERT=y
    CONFIG_HEAP_MEM_POOL_SIZE=8192
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
    # The Bluetooth API should not be used from a preemptive thread:
    CONFIG_MAIN_THREAD_PRIORITY=-2
    CONFIG_BT_MESH_TX_SEG_MSG_COUNT=5 
    CONFIG_STACK_SENTINEL=y
    CONFIG_THREAD_NAME=y
    CONFIG_EXCEPTION_STACK_TRACE=y
    
    # Bluetooth configuration
    CONFIG_BT=y
    CONFIG_BT_TINYCRYPT_ECC=y
    CONFIG_BT_L2CAP_TX_BUF_COUNT=32
    CONFIG_BT_OBSERVER=y
    CONFIG_BT_BROADCASTER=y
    
    # Disable unused Bluetooth features
    CONFIG_BT_CTLR_DUP_FILTER_LEN=0
    CONFIG_BT_CTLR_LE_ENC=n
    CONFIG_BT_DATA_LEN_UPDATE=n
    CONFIG_BT_PHY_UPDATE=n
    CONFIG_BT_CTLR_CHAN_SEL_2=n
    CONFIG_BT_CTLR_MIN_USED_CHAN=n
    CONFIG_BT_CTLR_PRIVACY=n
    
    # Bluetooth mesh configuration
    CONFIG_BT_MESH=y
    CONFIG_BT_MESH_SUBNET_COUNT=1
    CONFIG_BT_MESH_APP_KEY_COUNT=1
    # CONFIG_BT_MESH_ADV_BUF_COUNT=10
    CONFIG_BT_MESH_TX_SEG_MSG_COUNT=3
    CONFIG_BT_MESH_RX_SEG_MAX=32
    CONFIG_BT_MESH_MODEL_GROUP_COUNT=3
    CONFIG_BT_MESH_LABEL_COUNT=0
    CONFIG_BT_MESH_CFG_CLI=y
    CONFIG_BT_MESH_HEALTH_CLI=y
    CONFIG_BT_MESH_BEACON_ENABLED=n
    CONFIG_BT_MESH_RELAY=y
    CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT=3
    
    CONFIG_BT_MESH_PROVISIONER=y
    CONFIG_BT_MESH_PROV_DEVICE=n
    CONFIG_BT_MESH_CDB=y
    CONFIG_BT_MESH_CDB_NODE_COUNT=16
    CONFIG_BT_MESH_CDB_SUBNET_COUNT=3
    CONFIG_BT_MESH_CDB_APP_KEY_COUNT=3
    
    CONFIG_BT_MESH_FRIEND=y
    CONFIG_BT_MESH_ADV_BUF_COUNT=64
    CONFIG_BT_MESH_TX_SEG_MAX=32
    CONFIG_BT_MESH_PB_GATT=y
    CONFIG_BT_MESH_GATT_PROXY=y
    CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME=y
    
    CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600
    
    # CONFIG_BT_MESH_DEBUG=y
    # CONFIG_BT_MESH_DEBUG_SETTINGS=y
    # CONFIG_BT_MESH_DEBUG_NET=y
    # CONFIG_BT_MESH_DEBUG_MODEL=y
    # CONFIG_BT_MESH_DEBUG_TRANS=y
    # CONFIG_BT_MESH_DEBUG_ACCESS=y
    
    # CONFIG_BT_MESH_LOW_POWER=y
    # CONFIG_BT_MESH_DEBUG_PROV=y
    # CONFIG_BT_MESH_DEBUG_LOW_POWER=y
    # CONFIG_BT_MESH_DEBUG_BEACON=y
    # CONFIG_BT_MESH_DEBUG_CRYPTO=y
    # CONFIG_BT_MESH_DEBUG_ADV=y
    
    # Bluetooth mesh models
    CONFIG_BT_MESH_ONOFF_CLI=y
    CONFIG_BT_MESH_LIGHTNESS_CLI=y
    
    CONFIG_LOG=y
    CONFIG_LOG_TIMESTAMP_64BIT=y
    CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP=y
    CONFIG_BT_DEBUG_LOG=y
    
    
    ###################### Violated RENODE/REAL HW configs ######################
    
    ### ENABLE all configs below for RENODE testing as RENODE does not support CC3XX crypto hardware
    # CONFIG_HW_CC3XX=n
    # CONFIG_NRF_CC3XX_PLATFORM=y
    # CONFIG_NRF_SECURITY=n
    
    ### DISABLE all configs below for RENODE testing as RENODE does not support flash driver
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    
    ### DISABLE all configs below for RENODE testing as RENODE does not support BT settings
    CONFIG_BT_SETTINGS=y
    CONFIG_SETTINGS=y
    
    ### DISABLE all configs below for RENODE testing as RENODE does not support physical UART/RTT console
    CONFIG_UART_CONSOLE=n
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_RTT_CONSOLE=y 
    CONFIG_LOG_BACKEND_RTT=y
    
    ### DISABLE all configs below for RENODE testing as RENODE that only  performance testing purpose of BLE mesh
    # CONFIG_BLE_MESH_TESTING=y
    
    ### DISABLE all configs below for RENODE testing as RENODE does not support physical file system
    CONFIG_FILE_SYSTEM=y
    CONFIG_FILE_SYSTEM_LITTLEFS=y
    
    ### DISABLE all configs below for RENODE testing as RENODE does not support hardware log
    # CONFIG_HW_LOG=y
    # CONFIG_MAIN_STACK_SIZE=2048
    # CONFIG_DEBUG=y
    
    
    ### DISABLE all configs below for RENODE testing as RENODE does not support hardware test
    # CONFIG_HW_TEST=y
    # CONFIG_SERIAL=y
    # CONFIG_UART_INTERRUPT_DRIVEN=y
    
    
    ### DISABLE all configs below for RENODE testing as RENODE does not support uart command
    # CONFIG_CTRL_LIGHT_VIA_UART=y
    
    ### DISABLE all configs below for RENODE testing as RENODE that define the number of nodes to stored in internal flash
    CONFIG_BT_MESH_CDB_NODE_COUNT=8
    CONFIG_BT_MAX_EXTERNAL_PROVSIONED_NODES=1
    
    
    # CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    # General configuration
    CONFIG_FLASH=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_HWINFO=y
    CONFIG_DK_LIBRARY=y
    CONFIG_PARTITION_MANAGER_ENABLED=y
    CONFIG_PM_SINGLE_IMAGE=y
    CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000
    
    # Bluetooth configuration
    CONFIG_BT=y
    CONFIG_BT_COMPANY_ID=0x0059
    CONFIG_BT_DEVICE_NAME="Mesh and Peripheral Coex"
    CONFIG_BT_L2CAP_TX_MTU=69
    CONFIG_BT_L2CAP_TX_BUF_COUNT=8
    CONFIG_BT_OBSERVER=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_SETTINGS=y
    
    CONFIG_BT_EXT_ADV=y
    CONFIG_BT_EXT_ADV_MAX_ADV_SET=2
    CONFIG_BT_MAX_CONN=3
    
    # Disable unused Bluetooth features
    CONFIG_BT_CTLR_DUP_FILTER_LEN=0
    CONFIG_BT_CTLR_LE_ENC=n
    CONFIG_BT_DATA_LEN_UPDATE=n
    CONFIG_BT_PHY_UPDATE=n
    CONFIG_BT_CTLR_CHAN_SEL_2=n
    CONFIG_BT_CTLR_MIN_USED_CHAN=n
    CONFIG_BT_CTLR_PRIVACY=n
    
    # Bluetooth mesh configuration
    CONFIG_BT_MESH=y
    CONFIG_BT_MESH_RELAY=y
    CONFIG_BT_MESH_FRIEND=y
    CONFIG_BT_MESH_ADV_BUF_COUNT=13
    CONFIG_BT_MESH_TX_SEG_MAX=10
    CONFIG_BT_MESH_PB_GATT=y
    CONFIG_BT_MESH_GATT_PROXY=y
    CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME=y
    CONFIG_BT_MESH_DK_PROV=y
    
    # Bluetooth mesh models
    CONFIG_BT_MESH_ONOFF_SRV=y
    
    # Enable the LBS service
    CONFIG_BT_LBS=y
    CONFIG_BT_LBS_POLL_BUTTON=y
    
    CONFIG_BOOTLOADER_MCUBOOT=y
    
    # Enable mcumgr.
    CONFIG_MCUMGR=y
    
    # Enable most core commands.
    # CONFIG_MCUMGR_CMD_IMG_MGMT=y
    # CONFIG_MCUMGR_CMD_OS_MGMT=y
    
    # Allow for large Bluetooth data packets.
    CONFIG_BT_L2CAP_TX_MTU=252
    CONFIG_BT_BUF_ACL_RX_SIZE=256
    
    # Enable the Bluetooth (unauthenticated) and shell mcumgr transports.
    CONFIG_MCUMGR_SMP_BT=y
    CONFIG_MCUMGR_SMP_BT_AUTHEN=n
    
    # Some command handlers require a large stack.
    
    
    
    # CONFIG_BUILD_OUTPUT_META=n
    /******************************************************************************
     * INCLUDES
     *******************************************************************************/
    #include "model_handler.h"
    #include "lb_service_handler.h"
    
    /******************************************************************************
     * CONFIGURATION CONSTANTS
     *******************************************************************************/
    #define BT_MESH_PROVISIONER_THREAD_NAME             ("bt_mesh_provisioner_thread")
    #define BT_MESH_PROVISIONER_THREAD_STACK_SIZE       (2048) // Bytes
    #define BT_MESH_PROVISIONER_THREAD_PRIORITY         (0)
    
    #define BT_MESH_LIGHTNESS_CLI_THREAD_NAME           ("bt_mesh_lightness_cli_thread")
    #define BT_MESH_LIGHTNESS_CLI_THREAD_STACK_SIZE     (2048) // Bytes
    #define BT_MESH_LIGHTNESS_CLI_THREAD_PRIORITY       (1)
    
    // Set log level for model_handler.c
    LOG_MODULE_REGISTER(provisioner_module, LOG_LEVEL_INF);
    
    #define BT_MESH_LIGHTNESS_MAX_RANGE                 (65535)
    
    /******************************************************************************
     * CONFIGURATION MACROS
     *******************************************************************************/
    
    
    /******************************************************************************
     * TYPEDEFS
     *******************************************************************************/
    /** Context for a single light switch. */
    struct light_cli_t {
    	struct bt_mesh_lightness_cli client;
    	struct k_work_delayable work;
    	uint16_t lvl;
    
    	uint16_t target_lvl;
    	uint16_t current_lvl;
    	uint32_t time_per;
    	uint32_t rem_time;
    
        uint8_t node_idx;
        uint16_t pub_addr[BT_MAX_EXTERNAL_PROVSIONED_NODES];
    };
    
    
    /******************************************************************************
     * FUNCTION PROTOTYPES
     *******************************************************************************/
    static void light_status( struct bt_mesh_lightness_cli *cli, struct bt_mesh_msg_ctx *ctx,
    		const struct bt_mesh_lightness_status *status);
    
    static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
    				  uint8_t test_id, uint16_t cid, uint8_t *faults,
    				  size_t fault_count);
    static void health_attention_status(struct bt_mesh_health_cli *cli, uint16_t addr,
    				 uint8_t attention);
    
    static void restore_nodes_after_power_off(void);
    static void setup_cdb(void);
    static void configure_self(struct bt_mesh_cdb_node *self);
    static void configure_node(struct bt_mesh_cdb_node *node);
    static void unprovisioned_beacon(uint8_t uuid[16],
    				 bt_mesh_prov_oob_info_t oob_info,
    				 uint32_t *uri_hash);
    static void node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr, uint8_t num_elem);
    static int bt_ready(void);
    static uint8_t check_unconfigured(struct bt_mesh_cdb_node *node, void *data);
    static void bt_mesh_provisioner_thread_entry(void *argument_1, void *argument_2, void *argument_3);
    static void bt_mesh_lightness_cli_thread_entry(void *argument_1, void *argument_2, void *argument_3);
    
    /******************************************************************************
     * VARIABLE DEFINITIONS
     *******************************************************************************/
    static bool is_send_message = false;
    
    static const struct bt_mesh_lightness_cli_handlers lightness_cli_handlers = {
    	.light_status = light_status,
    };
    
    
    static struct light_cli_t light_cli[] = {
    	{ .client = BT_MESH_LIGHTNESS_CLI_INIT(&lightness_cli_handlers) },
    };
    
    K_SEM_DEFINE(sem_srv_rsp, 0, 1);
    
    /* Set up a repeating delayed work to blink the DK's LEDs when attention is
     * requested.
     */
    static struct bt_mesh_cfg_cli cfg_cli = {
    };
    
    static struct bt_mesh_health_cli health_cli = {
    	.current_status = health_current_status,
    	.attention_status = health_attention_status,
    };
    
    static struct bt_mesh_elem elements[] = {
    	BT_MESH_ELEM(
    		1, BT_MESH_MODEL_LIST(
    			BT_MESH_MODEL_CFG_SRV,
    	        BT_MESH_MODEL_CFG_CLI(&cfg_cli),
                BT_MESH_MODEL_HEALTH_CLI(&health_cli),
    			BT_MESH_MODEL_LIGHTNESS_CLI(&light_cli[0].client)),
    		BT_MESH_MODEL_NONE),
    };
    
    static const struct bt_mesh_comp comp = {
    	.cid = BT_COMP_ID_LF,
    	.elem = elements,
    	.elem_count = ARRAY_SIZE(elements),
    };
    
    static const uint16_t net_idx;
    static const uint16_t app_idx;
    static uint16_t self_addr = 1, node_addr;
    static const uint8_t dev_uuid[16] = { 0xdd, 0xdd };
    static uint8_t node_uuid[16];
    static uint8_t node_provisioned_idx = 0;
    
    extern struct bt_mesh_cdb bt_mesh_cdb;
    
    K_SEM_DEFINE(sem_unprov_beacon, 0, 1);
    K_SEM_DEFINE(sem_node_added, 0, 1);
    
    static const struct bt_mesh_prov prov = {
    	.uuid = dev_uuid,
    	.unprovisioned_beacon = unprovisioned_beacon,
    	.node_added = node_added,
    };
    
    K_THREAD_STACK_DEFINE(bt_mesh_provisioner_stack_area, BT_MESH_PROVISIONER_THREAD_STACK_SIZE);
    K_THREAD_STACK_DEFINE(bt_mesh_lightness_cli_stack_area, BT_MESH_LIGHTNESS_CLI_THREAD_STACK_SIZE);
    static struct k_thread bt_mesh_provisioner_thread;
    static struct k_thread bt_mesh_lightness_cli_thread;
    static k_tid_t bt_mesh_provisioner_thread_tid;
    static k_tid_t bt_mesh_lightness_cli_thread_tid;
    
    
    #if defined(CONFIG_BLE_MESH_TESTING)
    	static uint32_t start_time = 0;
    	static uint32_t prev_time = 0;
    	static uint32_t time_offset = 0;
    #endif
    
    #if defined(CONFIG_CTRL_LIGHT_VIA_UART)
    volatile uint16_t light_respond_value = 0;
    #endif
    
    /******************************************************************************
     * PUBLIC FUNCTIONS
     *******************************************************************************/
    /******************************************************************************
    * Function : model_light_start
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    void model_light_start(void)
    {
        is_send_message = true;
    }
    
    /******************************************************************************
    * Function : model_light_stop
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    void model_light_stop(void)
    {
        is_send_message = false;
    }
    
    /******************************************************************************
    * Function : model_light_add_pub_addr
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    void model_light_add_pub_addr(uint16_t addr)
    {
        // Temporarily store all values of public addresses to client 0 buffer
        for(uint8_t idx=0; idx<light_cli[0].node_idx; idx++)
        {
            if(light_cli[0].pub_addr[idx] == addr)
            {
                // Discard this public address
                LOG_INF("Addr 0x%04x has been already provisioned", addr);
                return;
            }
        }
    
    	if(node_provisioned_idx < BT_MAX_EXTERNAL_PROVSIONED_NODES)
    	{
    		node_provisioned_idx++;
    	}
    
        // TODO: Check node down here to increase the node index and 
        // replace the public address properly
        LOG_INF("Add public address: 0x%04x", addr);
        light_cli[0].pub_addr[light_cli[0].node_idx++] = addr;
    }
    
    	
    #if defined(CONFIG_CTRL_LIGHT_VIA_UART)
    int control_lightness_of_node(uint8_t node_idx, uint16_t lightness_value, uint16_t *respond_value)
    {
    	int err;
    	int rc = 0;
    
    	if(is_send_message)
    	{
    		if (!bt_mesh_is_provisioned()) 
    		{
    			rc = -1;
    			// TODO: Check index of node at here
    		    LOG_INF("Client %d has not been provisioned yet", 1);
    		}
    		else 
    		{            
    		    // Setup on/off state and transition parameters - need to define locally like that to avoid dynamic conflic
    			// Please refer this link for detail
    			// https://devzone.nordicsemi.com/f/nordic-q-a/90840/not-able-to-receive-status-messages-published-by-onoff-server-using-message-context-instead-of-default-publish-parameters-set-by-provisioner
    			// struct bt_mesh_onoff_set set = {
    			// 	.on_off = !light_cli[0].status,
    			// };
    
    			struct bt_mesh_lightness_set set = {
    				// Spcify the scale of lightness level of max range of uint16_t
    				// min step = max_scale(uint16_t)
    				.lvl =  lightness_value,
    			};
    
    			struct bt_mesh_model_transition *tmp = (struct bt_mesh_model_transition *)&set.transition;
    			tmp->time = BT_MAX_TRANSITION_TIME_MS;
    			tmp->delay = BT_MAX_TRANSITION_DELAY_MS;
    
    			/* As we can't know how many nodes are in a group, it doesn't
    			* make sense to send acknowledged messages to group addresses -
    			* we won't be able to make use of the responses anyway.
    			*/
    
    			light_cli[0].client.model->pub->addr = light_cli[0].pub_addr[node_idx];
    			light_cli[0].client.pub.addr = light_cli[0].pub_addr[node_idx];
    
    			if (bt_mesh_model_pub_is_unicast(light_cli[0].client.model)) 
    			{
    				err = bt_mesh_lightness_cli_light_set(&light_cli[0].client, NULL,
    								&set, NULL);
    				
    				if(err)
    				{
    					rc = -1;
    					LOG_INF("Client Failed to public state change: %d", err);
    				}
    				else
    				{                        
    					light_cli[0].lvl = set.lvl;
    					// Wait for the semaphore from server response callback
    					err = k_sem_take(&sem_srv_rsp, K_MSEC(2000));
    
    					if (err == -EAGAIN) 
    					{
    						rc = -1;
    						LOG_INF("Failed to take the semaphore from light status handler");
    					}
    					else if(err < 0)
    					{
    						rc = -1;
    					}
    					else
    					{
    						*respond_value = light_respond_value;
    					}
    				}
    			} 
    
    			if (err)           
    			{
    				rc = -1;
    				LOG_INF("Client Light Lightness %d set failed: %d", light_cli[0].client.model->pub->addr, err);
    			}
    		}
    	}
    	else
    	{
    		rc = -1;
    	}
    
    	return rc;
    }
    #endif
    
    
    /******************************************************************************
    * Function : model_handler_init
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    const struct bt_mesh_comp *model_handler_init(void)
    {
    	return &comp;
    }
    
    /******************************************************************************
    * Function : get_number_provisioned_nodes
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    #if defined(CONFIG_CTRL_LIGHT_VIA_UART)
    uint8_t get_number_provisioned_nodes(void)
    {
    	return node_provisioned_idx;
    }
    #endif
    
    /******************************************************************************
    * Function : bt_mesh_thread_init
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    void bt_mesh_thread_init(void)
    {
        bt_mesh_provisioner_thread_tid = k_thread_create(&bt_mesh_provisioner_thread, bt_mesh_provisioner_stack_area,
                                        K_THREAD_STACK_SIZEOF(bt_mesh_provisioner_stack_area),
                                        bt_mesh_provisioner_thread_entry,
                                        NULL, NULL, NULL,
                                        BT_MESH_PROVISIONER_THREAD_PRIORITY, K_USER, K_NO_WAIT);
    	k_thread_name_set(&bt_mesh_provisioner_thread, BT_MESH_PROVISIONER_THREAD_NAME);
        if(bt_mesh_provisioner_thread_tid == NULL)
        {
            LOG_INF("Failed to initializing provisioner thread");
            return;
        }
    
        bt_mesh_lightness_cli_thread_tid = k_thread_create(&bt_mesh_lightness_cli_thread, bt_mesh_lightness_cli_stack_area,
                                        K_THREAD_STACK_SIZEOF(bt_mesh_lightness_cli_stack_area),
                                        bt_mesh_lightness_cli_thread_entry,
                                        NULL, NULL, NULL,
                                        BT_MESH_LIGHTNESS_CLI_THREAD_PRIORITY, K_USER, K_NO_WAIT);
    	k_thread_name_set(&bt_mesh_lightness_cli_thread, BT_MESH_LIGHTNESS_CLI_THREAD_NAME);
        if(bt_mesh_lightness_cli_thread_tid == NULL)
        {
            LOG_INF("Failed to initializing Lightness client thread");
        }
    }
    
    /******************************************************************************
     * STATIC FUNCTIONS
     *******************************************************************************/
    /******************************************************************************
    * Function : light_status
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void light_status( struct bt_mesh_lightness_cli *cli, struct bt_mesh_msg_ctx *ctx,
    		const struct bt_mesh_lightness_status *status)
    {
    	// struct light_cli_t *p_light_cli =
    	// 	CONTAINER_OF(cli, struct light_cli_t, client);
    
    #if defined(CONFIG_BLE_MESH_TESTING)
    	LOG_INF("Light control client Received response: index = %d, time offfset = %d, %d from address 0x%04x",
    	status->current, time_offset, status->remaining_time, cli->model->pub->addr);
    #else
    	LOG_INF("Light control client Received response: %d %d %d from address 0x%04x",
    	       status->current, status->target, status->remaining_time, cli->model->pub->addr);
    #endif
    
        // Release the semaphore here
    #if defined(CONFIG_CTRL_LIGHT_VIA_UART)
    	light_respond_value = status->target;
    #endif
    	k_sem_give(&sem_srv_rsp);
    }
    
    /******************************************************************************
    * Function : health_current_status
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
    				  uint8_t test_id, uint16_t cid, uint8_t *faults,
    				  size_t fault_count)
    {
    	size_t i;
    
    	LOG_INF("Health Current Status from 0x%04x", addr);
    
    	if (!fault_count) {
    		LOG_INF("Health Test ID 0x%02x Company ID 0x%04x: no faults",
    		       test_id, cid);
    		return;
    	}
    
    	LOG_INF("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu:",
    	       test_id, cid, fault_count);
    
    	for (i = 0; i < fault_count; i++) {
    		LOG_INF("\t0x%02x", faults[i]);
    	}
    }
    
    /******************************************************************************
    * Function : health_attention_status
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void health_attention_status(struct bt_mesh_health_cli *cli, uint16_t addr,
    				 uint8_t attention)
    {
    	LOG_INF("Health Attention remaining timeout of ADDR 0x%04x - %d", addr, attention);
    }
    
    /******************************************************************************
    * Function : setup_cdb
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void setup_cdb(void)
    {
    	struct bt_mesh_cdb_app_key *key;
    
    	key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
    	if (key == NULL) {
    		LOG_INF("Failed to allocate app-key 0x%04x", app_idx);
    		return;
    	}
    
    	bt_rand(key->keys[0].app_key, 16);
    
    	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
    		bt_mesh_cdb_app_key_store(key);
    	}
    }
    
    /******************************************************************************
    * Function : configure_self
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void configure_self(struct bt_mesh_cdb_node *self)
    {
    	struct bt_mesh_cdb_app_key *key;
    	uint8_t status = 0;
    	int err;
    
    	LOG_INF("Configuring self...");
    
    	key = bt_mesh_cdb_app_key_get(app_idx);
    	if (key == NULL) {
    		LOG_INF("No app-key 0x%04x", app_idx);
    		return;
    	}
    
    	/* Add Application Key */
    	err = bt_mesh_cfg_app_key_add(self->net_idx, self->addr, self->net_idx,
    				      app_idx, key->keys[0].app_key, &status);
    	if (err || status) {
    		LOG_INF("Failed to add app-key (err %d, status %d)", err,
    		       status);
    		return;
    	}
    
    	err = bt_mesh_cfg_mod_app_bind(self->net_idx, self->addr, self->addr,
    				       app_idx, BT_MESH_MODEL_ID_HEALTH_CLI,
    				       &status);
    	if (err || status) {
    		LOG_INF("Failed to bind app-key (err %d, status %d)", err,
    		       status);
    		return;
    	}
    
    	err = bt_mesh_cfg_mod_app_bind(self->net_idx, self->addr, self->addr,
    				       app_idx, BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI,
    				       &status);
    	if (err || status) {
    		LOG_INF("Failed to bind app-key (err %d, status %d)", err,
    		       status);
    		return;
    	}
    
    	atomic_set_bit(self->flags, BT_MESH_CDB_NODE_CONFIGURED);
    
    	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
    		bt_mesh_cdb_node_store(self);
    	}
    
    	LOG_INF("Configuration complete");
    }
    
    /******************************************************************************
    * Function : configure_node
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void configure_node(struct bt_mesh_cdb_node *node)
    {
    	NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_RX_SDU_MAX);
    	struct bt_mesh_comp_p0_elem elem;
    	struct bt_mesh_cdb_app_key *key;
    	struct bt_mesh_comp_p0 comp;
    	uint8_t status;
    	int err, elem_addr;
    
    	LOG_INF("Configuring node 0x%04x...", node->addr);
    
    	key = bt_mesh_cdb_app_key_get(app_idx);
    	if (key == NULL) {
    		LOG_INF("No app-key 0x%04x", app_idx);
    		return;
    	}
    
    	/* Add Application Key */
    	err = bt_mesh_cfg_app_key_add(net_idx, node->addr, net_idx, app_idx,
    				      key->keys[0].app_key, &status);
    	if (err || status) {
    		LOG_INF("Failed to add app-key (err %d status %d)", err, status);
    		return;
    	}
    
    	/* Get the node's composition data and bind all models to the appkey */
    	err = bt_mesh_cfg_comp_data_get(net_idx, node->addr, 0, &status, &buf);
    	if (err || status) {
    		LOG_INF("Failed to get Composition data (err %d, status: %d)",
    		       err, status);
    		return;
    	}
    
    	err = bt_mesh_comp_p0_get(&comp, &buf);
    	if (err) {
    		LOG_INF("Unable to parse composition data (err: %d)", err);
    		return;
    	}
    
    	elem_addr = node->addr;
    	while (bt_mesh_comp_p0_elem_pull(&comp, &elem)) {
    		LOG_INF("Element @ 0x%04x: %u + %u models", elem_addr,
    		       elem.nsig, elem.nvnd);
    		for (int i = 0; i < elem.nsig; i++) {
    			uint16_t id = bt_mesh_comp_p0_elem_mod(&elem, i);
    
    			if (id == BT_MESH_MODEL_ID_CFG_CLI ||
    			    id == BT_MESH_MODEL_ID_CFG_SRV) {
    				continue;
    			}
    			LOG_INF("Binding AppKey to model 0x%03x:%04x",
    			       elem_addr, id);
    
    			err = bt_mesh_cfg_mod_app_bind(net_idx, node->addr,
    							elem_addr, app_idx, id,
    							&status);
    
    			if (err || status) {
    				LOG_INF("Failed (err: %d, status: %d)", err,
    				       status);
    			}
    		}
    
    		for (int i = 0; i < elem.nvnd; i++) {
    			struct bt_mesh_mod_id_vnd id =
    				bt_mesh_comp_p0_elem_mod_vnd(&elem, i);
    
    			LOG_INF("Binding AppKey to model 0x%03x:%04x:%04x",
    			       elem_addr, id.company, id.id);
    
    			err = bt_mesh_cfg_mod_app_bind_vnd(net_idx, node->addr,
    							   elem_addr, app_idx,
    							   id.id, id.company,
    							   &status);
    			if (err || status) {
    				LOG_INF("Failed (err: %d, status: %d)", err,
    				       status);
    			}
    		}
    
    		elem_addr++;
    	}
    
    	atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);
    
    	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
    		bt_mesh_cdb_node_store(node);
    	}
    
    	// Blink in 5 secs to notify that this device has been provisioned
    	int att_err = bt_mesh_health_attention_set(node->addr, app_idx, BT_ATTENTION_TIMEOUT_SEC, NULL);
    	if(att_err)
    	{
    		LOG_INF("Failed to set attention on node: 0x%3x", node->addr);
    	}
    	else
    	{
    		// Set public address for the model due to node address
    		model_light_add_pub_addr(node->addr);
    		LOG_INF("Configuration complete address: 0x%03x", node->addr);
    	}
    }
    
    /******************************************************************************
    * Function : unprovisioned_beacon
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void unprovisioned_beacon(uint8_t uuid[16],
    				 bt_mesh_prov_oob_info_t oob_info,
    				 uint32_t *uri_hash)
    {
    	memcpy(node_uuid, uuid, 16);
    	k_sem_give(&sem_unprov_beacon);
    }
    
    /******************************************************************************
    * Function : node_added
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr, uint8_t num_elem)
    {
    	node_addr = addr;
    	k_sem_give(&sem_node_added);
    }
    
    /******************************************************************************
    * Function : bt_ready
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static int bt_ready(void)
    {
    	uint8_t net_key[16], dev_key[16];
    	int err;
    
    	// Random the UUID address
    	uint8_t * p_tmp = (uint8_t *)dev_uuid;
    	bt_rand(p_tmp, 16);
    	err = bt_mesh_init(&prov, model_handler_init());
    	if (err) {
    		LOG_INF("Initializing mesh failed (err %d)", err);
    		return err;
    	}
    
    	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
    		LOG_INF("Loading stored settings");
    		settings_load();
    	}
    
    	LOG_INF("Mesh initialized");
    	// lbs_handler_init();
    
    	bt_rand(net_key, 16);
    
    	err = bt_mesh_cdb_create(net_key);
    	if (err == -EALREADY) {
    		LOG_INF("Using stored CDB");
    	} else if (err) {
    		LOG_INF("Failed to create CDB (err %d)", err);
    		return err;
    	} else {
    		LOG_INF("Created CDB");
    		setup_cdb();
    	}
    
    	bt_rand(dev_key, 16);
    
    	err = bt_mesh_provision(net_key, BT_MESH_NET_PRIMARY, 0, 0, self_addr,
    				dev_key);
    	if (err == -EALREADY) {
    		LOG_INF("Using stored settings");
    	} else if (err) {
    		LOG_INF("Provisioning failed (err %d)", err);
    		return err;
    	} else {
    		LOG_INF("Provisioning completed");
    	}
    
    	return 0;
    }
    
    /******************************************************************************
    * Function : check_unconfigured
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static uint8_t check_unconfigured(struct bt_mesh_cdb_node *node, void *data)
    {
    	if (!atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
    		if (node->addr == self_addr) {
    			configure_self(node);
    		} else {
    			configure_node(node);
    		}
    	}
    
    	return BT_MESH_CDB_ITER_CONTINUE;
    }
    
    /******************************************************************************
    * Function : bt_mesh_provisioner_thread_entry
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void bt_mesh_provisioner_thread_entry(void *argument_1, void *argument_2, void *argument_3)
    {
    	char uuid_hex_str[32 + 1];
    	int err;
    
    	LOG_INF("Initializing...");
    
    	/* Initialize the Bluetooth Subsystem */
    	err = bt_enable(NULL);
    	if (err) {
    		LOG_INF("Bluetooth init failed (err %d)", err);
    		return;
    	}
    
    	LOG_INF("Bluetooth initialized");
    	bt_ready();
    
    	restore_nodes_after_power_off();
    
        while(1)
        {
    		k_sem_reset(&sem_unprov_beacon);
    		k_sem_reset(&sem_node_added);
    		bt_mesh_cdb_node_foreach(check_unconfigured, NULL);
    
    		if(node_provisioned_idx == BT_MAX_EXTERNAL_PROVSIONED_NODES)
    		{
    			LOG_INF("Provisioning enough nodes: %d", node_provisioned_idx);
    
                // Temprorarily start the ON/OFF model here for testing
    			model_light_start();
    		}
    
    		LOG_INF("Waiting for unprovisioned beacon...");
    		// err = k_sem_take(&sem_unprov_beacon, K_SECONDS(10));
    		err = k_sem_take(&sem_unprov_beacon, K_FOREVER);
    		if (err == -EAGAIN) 
    		{
    			continue;
    		}
    
    		bin2hex(node_uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
    
    		LOG_INF("Provisioning %s", uuid_hex_str);
    		err = bt_mesh_provision_adv(node_uuid, net_idx, 0, 0);
    		if (err < 0) 
    		{
    			LOG_INF("Provisioning failed (err %d)", err);
    			continue;
    		}
    
    		LOG_INF("Waiting for node to be added...");
    		err = k_sem_take(&sem_node_added, K_SECONDS(10));
    		if (err == -EAGAIN) 
    		{
    			LOG_INF("Timeout waiting for node to be added");
    			continue;
    		}
    
    		LOG_INF("Added node 0x%04x", node_addr);
        }
    }
    
    /******************************************************************************
    * Function : bt_mesh_lightness_cli_thread_entry
    * Brief    : TBD
    * Input    : None.
    * Output   : None.
    * Return   : None.
    *******************************************************************************/
    static void bt_mesh_lightness_cli_thread_entry(void *argument_1, void *argument_2, void *argument_3)
    {
        int err;
        uint32_t test_idx = 0;
    	uint8_t count = 0;
    
        while(1)
        {
            if(is_send_message)
            {
    		#if defined(CONFIG_CTRL_LIGHT_VIA_UART)
    			// Do nothing
    		#else
                if (!bt_mesh_is_provisioned()) 
                {
    				// TODO: Check index of node at here
                    LOG_INF("Client %d has not been provisioned yet", 1);
                }
                else 
                {            
                    // Setup on/off state and transition parameters - need to define locally like that to avoid dynamic conflic
    				// Please refer this link for detail
    				// https://devzone.nordicsemi.com/f/nordic-q-a/90840/not-able-to-receive-status-messages-published-by-onoff-server-using-message-context-instead-of-default-publish-parameters-set-by-provisioner
    				// struct bt_mesh_onoff_set set = {
    				// 	.on_off = !light_cli[0].status,
    				// };
    
    				struct bt_mesh_lightness_set set = {
    					// Spcify the scale of lightness level of max range of uint16_t
    					// min step = max_scale(uint16_t)
    					// .lvl =  ((light_cli[0].lvl >= (BT_MESH_LIGHTNESS_MAX_RANGE - BT_MESH_LIGHTNESS_MAX_RANGE/20)) ? 0 : (light_cli[0].lvl + BT_MESH_LIGHTNESS_MAX_RANGE/20)),
    					.lvl =  count++,
    				};
    
    				struct bt_mesh_model_transition *tmp = (struct bt_mesh_model_transition *)&set.transition;
    				tmp->time = BT_MAX_TRANSITION_TIME_MS;
    				tmp->delay = BT_MAX_TRANSITION_DELAY_MS;
    
                    // Edit BT_MAX_EXTERNAL_PROVSIONED_NODES to expected number of nodes in the network except for provisioner
                    for(uint8_t idx =0; idx<BT_MAX_EXTERNAL_PROVSIONED_NODES; idx++)
                    {
                        /* As we can't know how many nodes are in a group, it doesn't
                        * make sense to send acknowledged messages to group addresses -
                        * we won't be able to make use of the responses anyway.
                        */
    
                        light_cli[0].client.model->pub->addr = light_cli[0].pub_addr[idx];
                        light_cli[0].client.pub.addr = light_cli[0].pub_addr[idx];
    
                        if (bt_mesh_model_pub_is_unicast(light_cli[0].client.model)) 
                        {
                            // k_sem_reset(&sem_srv_rsp);
                            // err = bt_mesh_onoff_cli_set(&light_cli[0].client, NULL,
                            //                 &set, NULL);
    
                            err = bt_mesh_lightness_cli_light_set(&light_cli[0].client, NULL,
                                            &set, NULL);
    
    					#if defined(CONFIG_BLE_MESH_TESTING)
    						start_time = k_uptime_get();
    					#endif
    						
                            if(err)
                            {
                                LOG_INF("Client Failed to public state change: %d", err);
                            }
                            else
                            {                        
                                light_cli[0].lvl = set.lvl;
                                LOG_INF("Public address: 0x%04x - lightness %d - test idx %d", light_cli[0].client.model->pub->addr, set.lvl, test_idx++);
    
                                // Wait for the semaphore from server response callback about 2 seconds
                                err = k_sem_take(&sem_srv_rsp, K_MSEC(2000));
    
    					#if defined(CONFIG_BLE_MESH_TESTING)
    						time_offset = start_time - prev_time;
    						prev_time = start_time;
    					#endif			
                                if (err == -EAGAIN) 
                                {
                                    LOG_INF("Failed to take the semaphore from light status handler, address = 0x%04x", light_cli[0].client.model->pub->addr);
                                }
                                else if(!err)
                                {
                                    continue;
                                }
                            }
                        } 
                        else 
                        {
    						LOG_INF("bt_mesh_lightness_cli_light_set_unack");
                            err = bt_mesh_lightness_cli_light_set_unack(&light_cli[0].client, 
                                            NULL, &set);
                            if (!err) 
                            {
                                /* There'll be no response status for the
                                * unacked message. Set the state immediately.
                                */
                                LOG_INF("Set light status to group address");
                            }
                        }
    
                        if (err)           
                        {
                            LOG_INF("Client Light Lightness %d set failed: %d", light_cli[0].client.model->pub->addr, err);
                        }
                    }
                }
    		#endif
            }
    
    	#if defined(CONFIG_BLE_MESH_TESTING)
    		k_sleep(K_MSEC(100));
    	#else	
    		k_sleep(K_MSEC(3000));
    	#endif		
        }
    }
    
    static void restore_nodes_after_power_off(void)
    {
    	int i;
    
    	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
    		if ((bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) || (bt_mesh_cdb.nodes[i].addr == self_addr)) {
    			// LOG_INF("Unassigned address or self address -> continue: %d", bt_mesh_cdb.nodes[i].addr);
    			continue;
    		}
    		model_light_add_pub_addr(bt_mesh_cdb.nodes[i].addr);
    	}
    }
    Also make sure that you do a full erase between each time you program the DK to ensure that no artifacts from the previous build are still present. In especially Mesh, there are some configuration settings that are stored in flash.
    - I confirm that I erased the chip when I reprogrammed it.
    In general for adding firmware upgrade support, I typically recommend reading this guide written by my colleague. Here you will also find a sample + information about how to create an upgradable bootloader + DFU support for the nRF5340
    - I also checked it but enabling CONFIG_BOOTLOADER_MCUBOOT=y caused my issue. I need to resolve it and execute the next steps.
    I look forward to receiving your response. Thanks.
  • Hi,

    Quoc Bui said:
    Yes, this is working normally as I expected and the same as you mentioned above. But the issue actually occurs when I enable the CONFIG_BOOTLOADER_MCUBOOT=y setting and leads to "current value and target value was wrong ".

    Thank you for clarifying!

    I will have a look at the files you supplied and return to you with an answer and/or follow up questions

    Kind regards,
    Andreas

Reply
  • Hi,

    Quoc Bui said:
    Yes, this is working normally as I expected and the same as you mentioned above. But the issue actually occurs when I enable the CONFIG_BOOTLOADER_MCUBOOT=y setting and leads to "current value and target value was wrong ".

    Thank you for clarifying!

    I will have a look at the files you supplied and return to you with an answer and/or follow up questions

    Kind regards,
    Andreas

Children
  • Hi , my college has found the root cause of this issue, the code below still does not allocate for the transition pointer

    struct bt_mesh_model_transition *tmp = (struct bt_mesh_model_transition *)&set.transition;
    tmp->time = BT_MAX_TRANSITION_TIME_MS;
    tmp->delay = BT_MAX_TRANSITION_DELAY_MS

    and we only found this issue when we enable MCUBOOT. Thanks for your reply and please help me close my ticket. 

  • Hi,

    I've been out of office due to a fever since last week so I've just gotten back to have a look at your issue, but I'm glad you've figured it out and thank you for telling me! I'll verify the answer and close your ticket. 

    Please feel free to raise new tickets in the future at Devzone if you need help with anything else

    Kind regards,
    Andreas

Related