Zigbee end device bound to another device always issues broadcasts to resolve the short network address based on target's MAC

Hi,

I tried searching public question on the matter and wasn't able to find anything reminiscent of the problem I have.

I'm developing a presence sensor using ZigBee protocol for communications. The device is an end device. Among other things it implements a client on/off cluster

for the purposes of direct binding and sending on/off commands directly to appliances (smart lights, smart sockets, etc.).

In principle it works and in a small testing network (2 devices: the said presence sensor and a smart socket) binding my presence sensor to a smart socket works without problems.

However when I tried for testing purposes adding the presence sensor to a much bigger zigbee network (90+ devices: 37 routers, 55 end devices) the results were highly mixed.

When bound to one of smart sockets, the binding seems to work, on/off commands are issued, received and executed in a timely manner with an acceptable minimal latency.

However in another case binding to a smart bulb although succeeds in terms of a binding operation, when it comes to an actual transmission of on/off commands the outcome is highly unreliable:

it works sometimes, much more often a really big delay happens.

I've used Wireshark to sniff the traffic that's happening and was able to conclude that said delays are there due to my presence sensor sending "ZigBee Device Profile: Network Address Request" broadcast requests always to determine a short network address of the target smart bulb. Smart bulb responses with own address as requested. However shortly after (say, when 'Off' command is sent after presence is no more detected), it sends again the same set of broadcast requests to figure out the network address it literally got just half a minute ago.

This suggests that for whatever reason it doesn't store the translation for MAC->address in the address table. The only "workaround" I have at the moment is to add my presence sensor device directly via the smart bulb I want to control, so that it's a direct parent node in the mesh. Then the commands are issued with a valid short address immediately without sending tons of broadcast requests.

I've tried "turning the knobs" like:

#define ZB_CONFIG_OVERALL_NETWORK_SIZE 100 
#define ZB_CONFIG_HIGH_TRAFFIC
#define ZB_CONFIG_APPLICATION_COMPLEX

#include <zb_mem_config_common.h>

#undef ZB_CONFIG_IOBUF_POOL_SIZE
#define ZB_CONFIG_IOBUF_POOL_SIZE 128
#undef ZB_CONFIG_SCHEDULER_Q_SIZE
#define ZB_CONFIG_SCHEDULER_Q_SIZE 64
#undef ZB_CONFIG_APS_DUPS_TABLE_SIZE
#define ZB_CONFIG_APS_DUPS_TABLE_SIZE 64
#define ZB_CONFIG_NWK_DISC_TABLE_SIZE 32U

but this doesn't seem to help.

What am I missing? Is there some other setting I could tweak?

I'm using ZigBee R23 Add-on, 1.2.1

if that matters.

Thanks!  

Parents
  • Hello,

    Can you please share something from your application? What API do you use to send the turn on/off smart socket and light bulbs? Is it possible to share the entire application?

    Best regards,

    Edvin

  • Here's a link to the app:
    github.com/.../main
    the commit state to look at is:

    94808f4ac9585ff5bb992e38fd1471c0e311579d

    direct link to the repo state

    however it might be a little complicated to navigate.
    I'm using a self-written C++ wrapper for using ZBOSS API.
    It's heavy on templates and constexpr compile-time parts.

    The relevant part that sends the on/off command can be found here:
    src/main.cpp:320 (send_on_off)

    which at the end is 'translated' into a call at:
    submodules/nrf_zb_cpp/include/nrfzbcpp/zb_desc_helper_types_ep.hpp:300 (send_cmd)

    over to
    submodules/nrf_zb_cpp/include/nrfzbcpp/zb_desc_helper_types_cluster.hpp:270 (prepare_args)

    important pieces are:

    destination short address: 0
    destination end point: 0
    address mode used: ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT

    and finally here happens the actual command sending:
    submodules/nrf_zb_cpp/include/nrfzbcpp/zb_desc_helper_types_cluster.hpp:347 (on_out_buf_ready)

    manufacture code is ZB_ZCL_MANUF_CODE_INVALID
    frame direction: ZB_ZCL_FRAME_DIRECTION_TO_SRV
    destination address: short addr as 0
    address mode: ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT
    dst ep: 0
    profile id: ZB_AF_HA_PROFILE_ID
    cluster id: ZB_ZCL_CLUSTER_ID_ON_OFF

    What I also find important is that this code that sends commands to bound device works in principle:
    in a trivial network case, but also in this big zigbee network, however when added at a different
    physical location and when bound to a different target device (smart socket, as I also stated in the
    original description).

    Also it's important to remember that it works without problems, when the bound device is the immediate
    parent node of this end device (I was adding it via zigbee2mqtt by permitting join only for that given
    target smart bulb).

    In all of these cases exactly the same code path is used for sending commands.

    I hope this helps.
    Thanks!

    Edit:

    API used:

    zigbee_get_out_buf_delayed_ext

    zb_zcl_start_command_header

    zb_zcl_finish_and_send_packet

  • theorlangur said:
    destination address: short addr as 0
    address mode: ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT

    So these addresses are not used, even when the command works?

    If so, how do you usually set up what devices that should receive these messages? 

    Or is the command sent with a different address in the case of the smaller network when it works as intended?

    Best regards,

    Edvin

  • my intention is to use a direct binding feature of Zigbee, so that my presence sensor would be able to send commands directly to other devices and not via a coordinator.

    I have a zigbee network, based on a coordinator that is managed by a zigbee2mqtt software.

    This zigbee presence sensor is added to this zigbee network.

    Using a functionality of zigbee2mqtt I bind the endpoint 0, zigbee client On/Off cluster to a corresponding endpoint (also 0) and a zigbee server On/Off cluster of a smart bulb (and in other tests of a smart socket).

    The bind command finishes successfully.

    And so in the app on my zigbee presence sensor, when I need to send such On/Off command, I'm sending it with "ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT" as address mode with an intention to send this command to every device that is bound to this presence sensor (it could be more than one).

    And I send On/Off commands exclusively like that, there's no other code path that would send them with other address mode or some explicit destination address. The expectation being that Zigbee implementation would iterate over bound devices, endpoints and clusters, finding the ones that fit the command being sent.

    And it works. But for some reason not always, since in some cases it comes to permanent broadcast requests, as described in my original post.

    I'm not sure in what format the binding entry is stored but my guess it's using IEEE address instead of a short 16-bit one (which probably is fine in itself...). And for that to work you need an existing entry in the address translation table (I would guess) and if there is none - you need to send a broadcast request to figure out the short network address based on the IEEE one. Why wouldn't it store the received answer permanently in the translation table, locking the entry from eviction  - I don't know. I hope people working on ncs-zigbee could help me understand or fix a bug.

    All my experiments with different zigbee network sizes were using the described workflow and direct binding functionality.

  • I understand.

    You can try to increase these:
    ZB_APS_SRC_BINDING_TABLE_SIZE

    ZB_APS_DST_BINDING_TABLE_SIZE 

    And see if that helps. 

    They are by default defined in ncs-zigbee\lib\zboss\include\zb_config.h, so make sure you define them properly. I have not tested this, but it seems like you need to define ZB_CONFIGURABLE_MEM as well.

    Print the final value of ZB_APS_SRC_BINDING_TABLE_SIZE in your log to see that it is properly set. 

    Best regards,

    Edvin

  • thanks for the suggestion

    I'm looking now at defines you've suggested and the thing is: I don't see where it would make an effect.

    If I don't provide these defines, then I don't 'see' the defines in my main.cpp (they don't come from any zigbee header file). And when I do provide the defines (I changed both to 64), there's no difference in the binary size, in the occupied RAM size.

    I've found the reference to these defines in:

    ncs-zigbee/lib/zboss/src/include/zb_aps_globals.h:110 (zb_aps_binding_table_t)

    however there it seems to be used only when ZB_CONFIGURABLE_MEM is NOT defined (which it is).

    I've tried changing the defines you've suggested nevertheless. (increased them both to 64).

    And the sensor was failing as before attempting to send a command.

    I've also tried undef'ing ZB_CONFIGURABLE_MEM and it did change the binary size (made it smaller. I guess because I've cranked up various numbers previously). But alas no improvement with sending the command to a bound device.

    However this was not all in vain. Here's a new piece of information I've collected.

    Apparently physical location of where the presence sensor was added to the zigbee network doesn't matter all that much for the issue in question. I mean it gets added to a different parent node, that I can see. However it fails sending commands to the bound smart bulb regardless of the physical location.

    At the same time added at a location close to the lamp (as I tried many times before without luck), and binding it to a smart socket (it physically is located at some distance over 1 hop in the network) - this worked like a charm without a single issue! No annoying meaningless broadcast with address requests.

    I've looked closer at a wireshark sniffed data and the following stands out to me:

    4002 39.916372904 0x1af6 Broadcast ZigBee ZDP 138 Network Address Request, Address: SiliconLabor_ff:fe:74:33:11

    this is an address request for that smart bulb. It's full MAC is 04:0d:84:ff:fe:74:33:11

    the MAC of the smart socket where I don't get any issue binding and sending commands is

    70:b3:d5:2b:60:09:d8:3d

    I have tried and bound the sensor to another smart socket with MAC ec:1b:bd:ff:fe:a2:0e:a3 and I'm getting exactly the same problem with it: endless meaningless broadcast requests for an address.

    I wonder if that 'ff:fe' part of the smart bulb's MAC (and the other smart socket's MAC) which looks suspiciously like a broadcasting short address has anything to do with my problems...

    Would it be possible to verify that in ZBOSS sources for you?

Reply
  • thanks for the suggestion

    I'm looking now at defines you've suggested and the thing is: I don't see where it would make an effect.

    If I don't provide these defines, then I don't 'see' the defines in my main.cpp (they don't come from any zigbee header file). And when I do provide the defines (I changed both to 64), there's no difference in the binary size, in the occupied RAM size.

    I've found the reference to these defines in:

    ncs-zigbee/lib/zboss/src/include/zb_aps_globals.h:110 (zb_aps_binding_table_t)

    however there it seems to be used only when ZB_CONFIGURABLE_MEM is NOT defined (which it is).

    I've tried changing the defines you've suggested nevertheless. (increased them both to 64).

    And the sensor was failing as before attempting to send a command.

    I've also tried undef'ing ZB_CONFIGURABLE_MEM and it did change the binary size (made it smaller. I guess because I've cranked up various numbers previously). But alas no improvement with sending the command to a bound device.

    However this was not all in vain. Here's a new piece of information I've collected.

    Apparently physical location of where the presence sensor was added to the zigbee network doesn't matter all that much for the issue in question. I mean it gets added to a different parent node, that I can see. However it fails sending commands to the bound smart bulb regardless of the physical location.

    At the same time added at a location close to the lamp (as I tried many times before without luck), and binding it to a smart socket (it physically is located at some distance over 1 hop in the network) - this worked like a charm without a single issue! No annoying meaningless broadcast with address requests.

    I've looked closer at a wireshark sniffed data and the following stands out to me:

    4002 39.916372904 0x1af6 Broadcast ZigBee ZDP 138 Network Address Request, Address: SiliconLabor_ff:fe:74:33:11

    this is an address request for that smart bulb. It's full MAC is 04:0d:84:ff:fe:74:33:11

    the MAC of the smart socket where I don't get any issue binding and sending commands is

    70:b3:d5:2b:60:09:d8:3d

    I have tried and bound the sensor to another smart socket with MAC ec:1b:bd:ff:fe:a2:0e:a3 and I'm getting exactly the same problem with it: endless meaningless broadcast requests for an address.

    I wonder if that 'ff:fe' part of the smart bulb's MAC (and the other smart socket's MAC) which looks suspiciously like a broadcasting short address has anything to do with my problems...

    Would it be possible to verify that in ZBOSS sources for you?

Children
No Data
Related