Complete Sample Demo for BluetoothMesh like Nordic Semiconductor "Light_Switch"


Vikrant More <vikrant8051@...>
 

Hello,

I need simple clone of of "Light_Switch" demo (part of nordic semiconductor mesh SDK) using Zephyr.
In that demo, we can control Led1 on Servers using publishing data from client. Reliability is 100% even entire demo is based on only ADV-Bearer.
They used one client & 3 Servers. Client itself acts like provisioner.

Unfortunately, Nordic uses only ADV-Bearer & so we can't use available Silicon Labs Mesh App as provisioner.

So I shift to Zephyr since at least I can test working of Mesh using Provisioner APP.

But as per my testing, zephyr publishing reliability is not good even if I call bt_mesh_model_publish() from thread which wakes up on interrupt.

I want to publish 0 and 1 (toggle) after pressing button on one device to all other available nodes in vicinity. (individually using Unicast addresses & for many using Group address  )

So please release such full working demo like Nordic using Zephyr OS.
 
Or help me in details so that I can release behalf on Zephyr Community.

Thank You!!


Johan Hedberg
 

Hi Vikrant,

On Tue, Dec 05, 2017, Vikrant More wrote:
But as per my testing, zephyr publishing reliability is not good even if I
call bt_mesh_model_publish() from thread which wakes up on interrupt.
This is not really useful information without some more details. What
Publish Retransmit and Network Transmit states does the Nordic SDK use?
What are the values of these states on the Zephyr side? There are many
parameters that can be fine-tuned which influence message delivery
reliability, and these have very little to do with the actual
implementation and a lot to do with how you've configured your nodes.
Also note that having GATT connections inevitably lowers the duty-cycle
on the advertising bearer, so your nodes are much more likely to loose
packets in that case.

Johan


Vikrant More <vikrant8051@...>
 

Currently noob like me don't known how to correctly fine tuned or configure or write code from scratch using Zephyr so that it will exactly work like Nordic Semiconductor Mesh Light_Switch Demo. 

Hence I am requesting you to provide simple demo for nrf52840-PDK board. To find out what nordic has done differently, person should have knowledge of entire stack  & currently you are only one who knows everything. 

Coding style in Zephyr Mesh & nordic Mesh SDK is not simple C. It is objective C, so very difficult to visualize everything.

Plus #NordicSemiconductor code is very complicated compare to your coding style. 

I agree with you that coexistence of GATT & ADV Bearer may be reason of less reliability of data transfer.

So currently, I can do is wait till nordic implement GATT Bearer in their Mesh SDK to check overall performance or till they release Android App with ADV-provisioner utility.


On Dec 5, 2017 9:19 PM, "Johan Hedberg" <johan.hedberg@...> wrote:
Hi Vikrant,

On Tue, Dec 05, 2017, Vikrant More wrote:
> But as per my testing, zephyr publishing reliability is not good even if I
> call bt_mesh_model_publish() from thread which wakes up on interrupt.

This is not really useful information without some more details. What
Publish Retransmit and Network Transmit states does the Nordic SDK use?
What are the values of these states on the Zephyr side? There are many
parameters that can be fine-tuned which influence message delivery
reliability, and these have very little to do with the actual
implementation and a lot to do with how you've configured your nodes.
Also note that having GATT connections inevitably lowers the duty-cycle
on the advertising bearer, so your nodes are much more likely to loose
packets in that case.

Johan


Vikrant More <vikrant8051@...>
 

I have added bt_mesh_model_publish( ) in thread which starts to execute after getting interrupt from button. But when I click button multiple times in very short period of time then only thread executes but 
bt_mesh_model_publish( ) never get called.



On Dec 5, 2017 10:32 PM, "Vikrant More" <vikrant8051@...> wrote:
Currently noob like me don't known how to correctly fine tuned or configure or write code from scratch using Zephyr so that it will exactly work like Nordic Semiconductor Mesh Light_Switch Demo. 

Hence I am requesting you to provide simple demo for nrf52840-PDK board. To find out what nordic has done differently, person should have knowledge of entire stack  & currently you are only one who knows everything. 

Coding style in Zephyr Mesh & nordic Mesh SDK is not simple C. It is objective C, so very difficult to visualize everything.

Plus #NordicSemiconductor code is very complicated compare to your coding style. 

I agree with you that coexistence of GATT & ADV Bearer may be reason of less reliability of data transfer.

So currently, I can do is wait till nordic implement GATT Bearer in their Mesh SDK to check overall performance or till they release Android App with ADV-provisioner utility.


On Dec 5, 2017 9:19 PM, "Johan Hedberg" <johan.hedberg@...> wrote:
Hi Vikrant,

On Tue, Dec 05, 2017, Vikrant More wrote:
> But as per my testing, zephyr publishing reliability is not good even if I
> call bt_mesh_model_publish() from thread which wakes up on interrupt.

This is not really useful information without some more details. What
Publish Retransmit and Network Transmit states does the Nordic SDK use?
What are the values of these states on the Zephyr side? There are many
parameters that can be fine-tuned which influence message delivery
reliability, and these have very little to do with the actual
implementation and a lot to do with how you've configured your nodes.
Also note that having GATT connections inevitably lowers the duty-cycle
on the advertising bearer, so your nodes are much more likely to loose
packets in that case.

Johan



Vikrant More <vikrant8051@...>
 

Hello Sir,

I have attached my main.c with this email. (from Zephyr Mesh Demo)

This main.c is mostly inspired from information provided by Steve Brown. 

Please check it.

Here,

root_models[2] is BT_MESH_MODEL_ID_GEN_ONOFF_SRV
root_models[4] is BT_MESH_MODEL_ID_GEN_ONOFF_CLI

------------------------------------------------------------------------------------------------------------------------------------------
static void publish(struct k_work *work)
{

    static unsigned char onoff=0;
    static unsigned char tid=0;
    int err;

    struct net_buf_simple *msg = NET_BUF_SIMPLE(2+4+2);

    bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET_UNACK);
    net_buf_simple_add_u8(msg, onoff=onoff^0x01);
        net_buf_simple_add_u8(msg, tid++);

    printk("Interrupted....data_send=%u\n\r",onoff);

    root_models[2].pub->msg=msg;

    err = bt_mesh_model_publish(&root_models[2]);
    if (err) {
        printk("bt_mesh_model_publish: err: %d\n\r", err);
    }

}
-----------------------------------------------------------------------------------------------------------------------------------------

When I publish using  root_models[2] then function  bt_mesh_model_publish(struct bt_mesh_model *model) from zephyr/subsys/bluetooth/host/mesh/access.c 
execute properly after pressing the Button1 on nRF52840-PDK.

root_models[2] is server model.

Its publish address assigned by provisioner = 0xC000
It is subscribed to address = 0xC001

So all other nodes not changed their LED1 status when I pressed Button1 from any one of the Board since others are subscribed to 0xC001.

But when I hard-coded ctx.addr = 0xC001; in bt_mesh_model_publish(struct bt_mesh_model *model) then ohter boards start to toggle LED1.

I know this is wrong way to publish since we have to use client model to publish anything.
------------------------------------------------------------------------------------------------------------------------------------------

So I used root_model[4] i.e BT_MESH_MODEL_ID_GEN_ONOFF_CLI.

In this case, after pressing button, function bt_mesh_model_publish() returns error as -> bt_mesh_model_publish: err:-49

On investigating, I found that this is because of

if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
        return -EADDRNOTAVAIL;
    } 

That means Silicon Labs MESH APP does not assign any Public address to this client model.
Ideally it should be 0xC001 since other NODEs are subscribed to it. Am I right ?

--------------------------------------------------------------------------------------------------------------------------------------------

Am I on right track ?

When I follow Steve's code & increase .net_transmit = BT_MESH_TRANSMIT(5, 20) upto 5, then reliability is almost 100%.

Plus THREAD calls bt_mesh_model_publish( ) on every click even if I pressed button multiple times
in short period of time.

I will appreciate your suggestions if there are any. Please guide me what to do next.
I thoroughly want to understand everything before building my final application.

Thank You for your support !!


On Tue, Dec 5, 2017 at 11:09 PM, Vikrant More <vikrant8051@...> wrote:
I have added bt_mesh_model_publish( ) in thread which starts to execute after getting interrupt from button. But when I click button multiple times in very short period of time then only thread executes but 
bt_mesh_model_publish( ) never get called.



On Dec 5, 2017 10:32 PM, "Vikrant More" <vikrant8051@...> wrote:
Currently noob like me don't known how to correctly fine tuned or configure or write code from scratch using Zephyr so that it will exactly work like Nordic Semiconductor Mesh Light_Switch Demo. 

Hence I am requesting you to provide simple demo for nrf52840-PDK board. To find out what nordic has done differently, person should have knowledge of entire stack  & currently you are only one who knows everything. 

Coding style in Zephyr Mesh & nordic Mesh SDK is not simple C. It is objective C, so very difficult to visualize everything.

Plus #NordicSemiconductor code is very complicated compare to your coding style. 

I agree with you that coexistence of GATT & ADV Bearer may be reason of less reliability of data transfer.

So currently, I can do is wait till nordic implement GATT Bearer in their Mesh SDK to check overall performance or till they release Android App with ADV-provisioner utility.


On Dec 5, 2017 9:19 PM, "Johan Hedberg" <johan.hedberg@...> wrote:
Hi Vikrant,

On Tue, Dec 05, 2017, Vikrant More wrote:
> But as per my testing, zephyr publishing reliability is not good even if I
> call bt_mesh_model_publish() from thread which wakes up on interrupt.

This is not really useful information without some more details. What
Publish Retransmit and Network Transmit states does the Nordic SDK use?
What are the values of these states on the Zephyr side? There are many
parameters that can be fine-tuned which influence message delivery
reliability, and these have very little to do with the actual
implementation and a lot to do with how you've configured your nodes.
Also note that having GATT connections inevitably lowers the duty-cycle
on the advertising bearer, so your nodes are much more likely to loose
packets in that case.

Johan




Johan Hedberg
 

Hi Vikrant,

On Wed, Dec 06, 2017, Vikrant More wrote:
static void publish(struct k_work *work)
{

static unsigned char onoff=0;
static unsigned char tid=0;
int err;

struct net_buf_simple *msg = NET_BUF_SIMPLE(2+4+2);

bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET_UNACK);
net_buf_simple_add_u8(msg, onoff=onoff^0x01);
net_buf_simple_add_u8(msg, tid++);

printk("Interrupted....data_send=%u\n\r",onoff);

*root_models[2]*.pub->msg=msg;
This is not safe since the publishing buffer is not expected to be
allocated on the stack. It will cause a crash as soon as the Publish
Retransmit state is set to a non-zero value. I pointed this out earlier
to Steve and also tried to document it better:

https://lists.zephyrproject.org/pipermail/zephyr-devel/2017-November/008457.html

So in your case you'd want to create the buffer when you define the
publication struct, i.e. something like:

static struct bt_mesh_model_pub pub = {
.msg = NET_BUF_SIMPLE(2+4+2),
};

And then before publishing you'd do the same bt_mesh_model_msg_init()
and net_buf_simple_add_u8() calls as you do now.

When I publish using *root_models[2] *then function
bt_mesh_model_publish(struct bt_mesh_model *model) from
zephyr/subsys/bluetooth/host/mesh/access.c
execute properly after pressing the Button1 on nRF52840-PDK.

root_models[2] is server model.

Its publish address assigned by provisioner = 0xC000
It is subscribed to address = 0xC001

So all other nodes not changed their LED1 status when I pressed Button1
from any one of the Board since others are subscribed to 0xC001.

But when I hard-coded ctx.addr = 0xC001; in bt_mesh_model_publish(struct
bt_mesh_model *model) then ohter boards start to toggle LED1.
This looks like an issue with the provisioner (or how you use it) since
it seems it should also be setting the publication address to 0xc0001.

So I used root_model[4] i.e BT_MESH_MODEL_ID_GEN_ONOFF_CLI.

In this case, after pressing button, function bt_mesh_model_publish() returns
error as -> bt_mesh_model_publish: err:-49

On investigating, I found that this is because of

if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
return -EADDRNOTAVAIL;
}

That means Silicon Labs MESH APP does not assign any Public address to this
client model.
Ideally it should be 0xC001 since other NODEs are subscribed to it. Am I
right ?
Yes, sounds correct to me, i.e. this is an issue on the
provisioner/configuration client side.

Johan


Vikrant More <vikrant8051@...>
 

Thank you for the clarification. 

Could you please tell me, what should I do next ?

I need agenda to deeply understand concept of #BluetoothMesh.



On Dec 6, 2017 6:56 PM, "Johan Hedberg" <johan.hedberg@...> wrote:
Hi Vikrant,

On Wed, Dec 06, 2017, Vikrant More wrote:
> static void publish(struct k_work *work)
> {
>
>     static unsigned char onoff=0;
>     static unsigned char tid=0;
>     int err;
>
>     struct net_buf_simple *msg = NET_BUF_SIMPLE(2+4+2);
>
>     bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET_UNACK);
>     net_buf_simple_add_u8(msg, onoff=onoff^0x01);
>         net_buf_simple_add_u8(msg, tid++);
>
>     printk("Interrupted....data_send=%u\n\r",onoff);
>
>     *root_models[2]*.pub->msg=msg;

This is not safe since the publishing buffer is not expected to be
allocated on the stack. It will cause a crash as soon as the Publish
Retransmit state is set to a non-zero value. I pointed this out earlier
to Steve and also tried to document it better:

https://lists.zephyrproject.org/pipermail/zephyr-devel/2017-November/008457.html

So in your case you'd want to create the buffer when you define the
publication struct, i.e. something like:

static struct bt_mesh_model_pub pub = {
        .msg = NET_BUF_SIMPLE(2+4+2),
};

And then before publishing you'd do the same bt_mesh_model_msg_init()
and net_buf_simple_add_u8() calls as you do now.

> When I publish using  *root_models[2] *then function
> bt_mesh_model_publish(struct bt_mesh_model *model) from
> zephyr/subsys/bluetooth/host/mesh/access.c
> execute properly after pressing the Button1 on nRF52840-PDK.
>
> root_models[2] is server model.
>
> Its publish address assigned by provisioner = 0xC000
> It is subscribed to address = 0xC001
>
> So all other nodes not changed their LED1 status when I pressed Button1
> from any one of the Board since others are subscribed to 0xC001.
>
> But when I hard-coded ctx.addr = 0xC001; in bt_mesh_model_publish(struct
> bt_mesh_model *model) then ohter boards start to toggle LED1.

This looks like an issue with the provisioner (or how you use it) since
it seems it should also be setting the publication address to 0xc0001.

> So I used root_model[4] i.e BT_MESH_MODEL_ID_GEN_ONOFF_CLI.
>
> In this case, after pressing button, function bt_mesh_model_publish() returns
> error as -> bt_mesh_model_publish: err:-49
>
> On investigating, I found that this is because of
>
> if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
>         return -EADDRNOTAVAIL;
>     }
>
> That means Silicon Labs MESH APP does not assign any Public address to this
> client model.
> Ideally it should be 0xC001 since other NODEs are subscribed to it. Am I
> right ?

Yes, sounds correct to me, i.e. this is an issue on the
provisioner/configuration client side.

Johan