Retrieve the Device Information from the Border Router using CoAP#

Install libcoap2-bin on the Border Router#

  • The application requires libcoap binaries to be installed on the Border Router, so install the -bin package.

  • If using CoAP notifications instead of UDP notifications, coap-server will be used, and requires the -d option to define the max number of resources the coap-server can listen to. This is only available in libcoap as from libcoap2, so install libcoap as follows:

sudo apt-get install libcoap2-bin

Check the installed binaries using:

ls -al /usr/bin/coap*

-rwxr-xr-x 1 root root 26236 Nov  9  2019 /usr/bin/coap-client
-rwxr-xr-x 1 root root 26236 Nov  9  2019 /usr/bin/coap-client-gnutls
-rwxr-xr-x 1 root root 26236 Nov  9  2019 /usr/bin/coap-client-openssl
-rwxr-xr-x 1 root root 18016 Nov  9  2019 /usr/bin/coap-rd
-rwxr-xr-x 1 root root 18016 Nov  9  2019 /usr/bin/coap-rd-gnutls
-rwxr-xr-x 1 root root 18016 Nov  9  2019 /usr/bin/coap-rd-openssl
-rwxr-xr-x 1 root root 22124 Nov  9  2019 /usr/bin/coap-server
-rwxr-xr-x 1 root root 22124 Nov  9  2019 /usr/bin/coap-server-gnutls
-rwxr-xr-x 1 root root 22124 Nov  9  2019 /usr/bin/coap-server-openssl

The example uses coap-client and optionally coap-server (if using COAP notifications).

List Connected Devices' IPv6 Addresses#

wsbrd_cli status returns the connected devices' MAC addresses, while CoAP requires the IPv6 addresses.

The dbus resources related to the Wi-SUN Border Router are available to dbus as com.silabs.Wisun.BorderRouter:

busctl introspect  SERVICE                        OBJECT                          [INTERFACE]
busctl introspect  com.silabs.Wisun.BorderRouter  /com/silabs/Wisun/BorderRouter  com.silabs.Wisun.BorderRouter
NAME                                TYPE      SIGNATURE  RESULT/VALUE                             FLAGS
com.silabs.Wisun.BorderRouter       interface -          -                                        -
.IeCustomClear                      method    -          -                                        -
.IeCustomInsert                     method    yyayay     -                                        -
.InstallGtk                         method    ay         -                                        -
.InstallLgtk                        method    ay         -                                        -
.JoinMulticastGroup                 method    ay         -                                        -
.LeaveMulticastGroup                method    ay         -                                        -
.RevokeGroupKeys                    method    ayay       -                                        -
.RevokePairwiseKeys                 method    ay         -                                        -
.SetModeSwitch                      method    ayi        -                                        -
.SetSlotAlgorithm                   method    y          -                                        -
.Gaks                               property  aay        4 16 54 182 30 129 250 196 136 180 3 24… emits-change
.Gtks                               property  aay        4 16 0 16 32 48 64 80 96 112 128 144 16… emits-change
.HwAddress                          property  ay         8 144 253 159 255 254 0 51 58            -
.Lgaks                              property  aay        3 16 159 29 31 16 211 121 13 120 93 104… emits-change
.Lgtks                              property  aay        3 16 205 198 155 180 84 17 14 130 116 6… emits-change
.Nodes                              property  a(aya{sv}) 3 8 144 253 159 255 254 0 51 58 3 "is_b… emits-invalidation"
.WisunChanPlanId                    property  u          3                                        const
.WisunClass                         property  u          0                                        const
.WisunDomain                        property  s          "BZ"                                     const
.WisunFanVersion                    property  y          2                                        const
.WisunMode                          property  u          0                                        const
.WisunNetworkName                   property  s          "Linux_BZ_3_8"                           const
.WisunPanId                         property  q          59418                                    const
.WisunPhyModeId                     property  u          8                                        const
.WisunSize                          property  s          "CERT"                                   const
org.freedesktop.DBus.Introspectable interface -          -                                        -
.Introspect                         method    -          s                                        -
org.freedesktop.DBus.Peer           interface -          -                                        -
.GetMachineId                       method    -          s                                        -
.Ping                               method    -          -                                        -
org.freedesktop.DBus.Properties     interface -          -                                        -
.Get                                method    ss         v                                        -
.GetAll                             method    s          a{sv}                                    -
.Set                                method    ssv        -                                        -
.PropertiesChanged                  signal    sa{sv}as   -                                        -

What you are looking for is the Nodes property, which you can 'get' using:

busctl introspect com.silabs.Wisun.BorderRouter /com/silabs/Wisun/BorderRouter com.silabs.Wisun.BorderRouter Nodes

a(aya{sv}) 3 8 144 253 159 255 254 0 51 58 3 "is_border_router" b true "node_role" y 0 "ipv6" aay 2 16 254 128 0 0 0 0 0 0 146 253 159 255 254 0 51 58 16 253 0 97 114 109 0 0 0 146 253 159 255 254 0 51 58 8 96 164 35 255 254 55 168 255 8 "is_authenticated" b true "node_role" y 1 "parent" ay 8 144 253 159 255 254 0 51 58 "is_neighbor" b true "rssi" i -46 "rsl" i -41 "rsl_adv" i -37 "ipv6" aay 2 16 254 128 0 0 0 0 0 0 96 164 35 255 254 55 168 255 16 253 0 97 114 109 0 0 0 98 164 35 255 254 55 168 255 8 96 164 35 255 254 55 169 1 4 "is_authenticated" b true "node_role" y 1 "parent" ay 8 96 164 35 255 254 55 165 29 "ipv6" aay 2 16 254 128 0 0 0 0 0 0 96 164 35 255 254 55 169 1 16 253 0 97 114 109 0 0 0 98 164 35 255 254 55 169 1

The underlying structure is detailed in wsbrd-br-linux/DBUS.md:

- `ay`: EUI64
- `a{sv}`: list of properties identified by a string, as described in the
  following table. Not all properties are guaranteed to be present per node
  (ex: a node without parent has no `parent` field)

| Key              |Signature| Comment                                                                  |
|------------------|---------|--------------------------------------------------------------------------|
|`is_border_router`|`b`      |Deprecated. Use `node_role` instead.                                      |
|`node_role`       |`y`      |Semantics from Wi-SUN (`0`: BR, `1`: FFN-FAN1.1, `2`: LFN, none: FFN-FAN1.0)|
|`ipv6`            |`aay`    |Array of IPv6 addresses (usually link-local and GUA)                      |
|`parent`          |`ay`     |EUI-64 of the preferred parent                                            |
|`is_authenticated`|`b`      |                                                                          |
|`is_neighbor`     |`b`      |Only nodes that use direct unicast traffic to the border router are listed|
|`rssi`            |`i`      |Received Signal Strength Indication (RSSI) of the last packet received in dBm (neighbor only)|
|`rsl`             |`i`      |Exponentially Weighted Moving Average (EWMA) of the Received Signal Level (RSL) in dBm (neighbor only)|
|`rsl_adv`         |`i`      |EWMA of the RSL in dBm advertised by the node in RSL-IE (neighbor only)   |

Although it's possible, using the above to retrieve IPv6 addresses is quite complex, and is better done using the pydbus Python package and a short script.

Install pydbus Python Package#

pip3 install pydbus

get_nodes_ipv6_address.py Python Script#

from pydbus import SystemBus
import re

"""
get_nodes_ipv6_address.py
Prints the IPv6 address of each node connected to the running WSBRD instance.

USAGE:
    python3 get_nodes_ipv6_address.py

NOTES:
    - This script can only be used with the WSBRD + RCP setup and must be executed on the host.
"""

bus = SystemBus()
proxy = bus.get("com.silabs.Wisun.BorderRouter", "/com/silabs/Wisun/BorderRouter")
nodes = proxy.Nodes


def sliceIPv6(source):
    return [source[i : i + 4] for i in range(0, len(source), 4)]


for node in nodes:
    if len(node[1]["ipv6"]) != 2:
        continue
    if "parent" not in node[1] and (
        "node_role" not in node[1] or node[1]["node_role"] != 2
    ):
        continue

    ipv6 = bytes(node[1]["ipv6"][1]).hex()
    ipv6 = ":".join(sliceIPv6(ipv6))
    ipv6 = re.sub("0000:", ":", ipv6)
    ipv6 = re.sub(":{2,}", "::", ipv6)
    print(ipv6)

For a more convenient use from bash, this Python script can be called from the ipv6s bash script.

#!/bin/bash
# usage: listing IPv6 addresses of all nodes currently connected
# ./ipv6s

ipv6s=$(python /home/pi/get_nodes_ipv6_address.py)
for ipv6 in $ipv6s
do
    echo $ipv6
done

This script needs to be set as an executable using chmod a+x ipv6s.

Use ipv6s#

./ipv6s

fd00:6172:6d00::62a4:23ff:fe37:a8ff
fd00:6172:6d00::62a4:23ff:fe37:a901

NOTE: The IPv6 addresses obtained from wsbrd via DBus reflect the vision of the network from wsbrd.

It takes a while for a device lifetime to expire, so even after a device is switched off, it may still appear as part of the network from wsbrd's perspective. If a device is off for a while and then turned on in a relatively short term, it may even reconnect before wsbrd considers it as disconnected. With the initial connection message in the demonstration application, you will know this because:

  • You will receive a notification when the device will reconnect.

  • You can ask via CoAP for the device status and statistics, which will tell you when the reconnection occurred.

Typical CoAP 'get' Request#

coap-client uses port 5683 by default. This is the default CoAP UDP port, and is set in the application code.

An abstract of coap-client --help with the options used in the example is:

coap-client v4.2.1 -- a small CoAP implementation
Copyright (C) 2010-2019 Olaf Bergmann <bergmann@tzi.org> and others

TLS Library: None

Usage: coap-client [-e text] [-m method] [-N]  [-B seconds] URI

        URI can be an absolute URI or a URI prefixed with scheme and host

General Options
        -e text         Include text as payload (use percent-encoding for non-ASCII characters)
        -m method       Request method (get|put|post|delete|fetch|patch|ipatch), default is 'get'
        -N              Send NON-confirmable message
        -B seconds      Break operation after waiting given seconds (default is 90)

The typical coap-client request for the example application takes the following form:

coap-client -m get -N -B 3 coap://[<IPV6>]:5683<COAP_URI> [-e <PAYLOAD>]

where COAP_URI is the CoAP resource, starting with /

Discover CoAP Resources#

When a device supports CoAP, it generally supports discovery using the /.well-known/core URI:

coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a901]:5683/.well-known/core

</settings>;ct=40,</statistics>;ct=40,</status>;ct=40,</info>;ct=40,</settings/auto_send>;rt="sec";if="settings",</statistics/stack/regulation>;rt="json";if="regulation",</statistics/stack/network>;rt="json";if="network",</statistics/stack/wisun>;rt="json";if="wisun",</statistics/stack/fhss>;rt="json";if="fhss",</statistics/stack/mac>;rt="json";if="mac",</statistics/stack/phy>;rt="json";if="phy",</history>;rt="text";if="node",</statistics/app/availability>;rt="ratio";if="node",</statistics/app/connected_total>;rt="dhms";if="node",</statistics/app/connections>;rt="int";if="node",</statistics/app/disconnected_total>;rt="dhms";if="node",</statistics/app/join_states_sec>;rt="array";if="node",</statistics/app/all>;rt="json";if="node",</status/connected>;rt="dhms";if="node",</status/neighbor>;rt="json";if="node",</status/parent>;rt="tag";if="node",</status/running>;rt="dhms";if="node",</status/all>;rt="json";if="node",</info/version>;rt="text";if="node",</info/application>;rt="text";if="node",</info/chip>;rt="tag";if="node",</info/device>;rt="tag";if="node",</info/all>;rt="json";if="node"

The above shows four groups of resources (splitting on ,, with ct=40):

</settings>;ct=40,
</statistics>;ct=40,
</status>;ct=40,
</info>;ct=40,

And the resources you can access for each group (splitting the remaining text on ,):

</settings/auto_send>;rt="sec";if="settings",
</statistics/stack/regulation>;rt="json";if="regulation",
</statistics/stack/network>;rt="json";if="network",
</statistics/stack/wisun>;rt="json";if="wisun",
</statistics/stack/fhss>;rt="json";if="fhss",
</statistics/stack/mac>;rt="json";if="mac",
</statistics/stack/phy>;rt="json";if="phy",
</history>;rt="text";if="node",
</statistics/app/availability>;rt="ratio";if="node",
</statistics/app/connected_total>;rt="dhms";if="node",
</statistics/app/connections>;rt="int";if="node",
</statistics/app/disconnected_total>;rt="dhms";if="node",
</statistics/app/join_states_sec>;rt="array";if="node",
</statistics/app/all>;rt="json";if="node",
</status/connected>;rt="dhms";if="node",
</status/neighbor>;rt="json";if="node",
</status/parent>;rt="tag";if="node",
</status/running>;rt="dhms";if="node",
</status/all>;rt="json";if="node",
</info/version>;rt="text";if="node",
</info/application>;rt="text";if="node",
</info/chip>;rt="tag";if="node",
</info/device>;rt="tag";if="node",
</info/all>;rt="json";if="node"

These match what the application provides, since it's filled by the CoAP Resource Manager based on registered CoAP resources.

Send a CoAP Request to All Connected Devices#

The coap_all bash script can be used to send the same request to all devices. It uses get_nodes_ipv6_addresses.py to get the IPv6 addresses and traces the CoAP command, such that you can easily copy/paste it for a specific device if needed.

./coap_all /settings/auto_send
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51c]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51d]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a527]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a8ff]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a901]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2191]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2527]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2853]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8486]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8493]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8503]:5683/settings/auto_send : auto_send_sec: 60

Based on the coap_callback_auto_send() implementation in the Wi-SUN device, coap_all can also be used to change the auto_send period for all nodes in a row:

./coap_all /settings/auto_send -e 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51c]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51d]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a527]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a8ff]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a901]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2191]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2527]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2853]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8486]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8493]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8503]:5683/settings/auto_send -e 120 : auto_send_sec: 120