OpenWeave is an open-source implementation of the Weave network application layer, the secure, reliable communications backbone for Nest products. It is a versatile and lightweight solution for low-powered devices.

In this Codelab you'll use OpenWeave platform to provision a Thread device onto a Weave fabric, observe changes in the Service, then demonstrate Weave functionality between devices.

What you'll learn

What you'll need

All of the hardware and software for this Codelab has been built and pre-configured for you. At the kiosk there should be an OpenWeave House occupied by a Raspberry Pi 3B+ and three Nordic nRF52840 boards. Let's get familiar with each resident of the House.

Border Router (Raspberry Pi 3B+ and Nordic nRF52840)

These devices sit on the bottom level of the House. Together they function as an OpenThread Border Router in a Network Co-Processor (NCP) arrangement, and serve as a gateway between Thread and Wi-Fi networks.

In the NCP arrangement, Thread runs on the Nordic board while the application layer runs on the RPi3B+ (host processor). The development and testing of applications becomes independent of the OpenThread build, and allows for use of greater processing power.

Light and Button end-nodes (Nordic nRF52840 boards)

These devices sit on the top level of the House. They serve as OpenWeave end devices, connected to the Weave fabric via Thread. The one on the left, LightExample (labeled Light), is the device that publishes the LightState trait. The one on the right, ButtonExample (labeled Button), is the device that subscribes to the LightState trait on LightExample.

Weave command line tools

On the kiosk are a pre-built set of Weave command line tools, which contain the binaries used to assist in the pairing process. These tools perform the functions that the Nest app on a mobile device would when adding a new Nest device to your home and registering it to the Nest service.

The two tools you'll use in this Codelab are:

They are found in the ~/weave directory. Open a Terminal window and check to make sure they are there:

$ ls ~/weave/output/x86_64-apple-darwin/bin/weave-device-mgr
weave-device-mgr

$ ls ~/weave/src/test-apps/happy/bin/weave-register-service
weave-register-service

Nest Resource Debugger

The Nest Resource Debugger (nRD) is a web tool for real-time inspection of Weave traits in the service. This is the data model of devices in the Nest home. You'll be able to see the structure, the user, and all paired resources, along with any traits that each publishes.

Access nRD at nrd.openweave.io.

Weave in this Codelab connects to a Nest Service, and our view into that Service is available via the Nest Resource Debugger (nRD), a web tool for Weave trait inspection. The Weave Schema is the data and API model for the platform.

The Schema defines three elements:

Almost all functionality in the Nest ecosystem for everyday operation is mapped onto resources and traits.

Let's check our nRD project—one should be set up for you already.

Access nRD

Open a browser and navigate to https://nrd.openweave.io. Click the Sign In with Google button.

You will be asked to log in. Use the I/O Codelabs extension on a Chrome browser tab to get a set of credentials:

Use these devstarXXXX@iocodelabs.com credentials to log into nRD:

Create a project

Once logged in, select CREATE PROJECT to create a new project:

In the New Project window, enter the nestlabs.com account and password printed on your OpenWeave House, then select SIGN IN AND CREATE PROJECT:

When successful, the project will load a list of resources on the left side of the Resource watcher window:

Review resources

These represent our paired devices, along with the Structure and User assigned in the Service. To begin this Codelab, there should be only two NestOWP DEVICE resources:

NestOWPLinux represents the Raspberry Pi 3B+ and Nordic NCP combo that serves as a border router. The Device ID shown should match what's printed on the OpenWeave House.

NestOWPLightExample represents the Nordic board on the top left of the OpenWeave House. This resource reacts to and publishes changes to the state of the light trait.

Unpair the Button resource

You may have a third resource called NestOWPButtonExample.

If you don't have this resource, skip to the next step, Resources and traits.

If you do have this resource, this represents the Nordic board on the top right of the OpenWeave House called the ButtonExample. You will register and pair this end-node as part of the Codelab. If this device is listed, unpair it before continuing:

  1. Select the NestOWPButtonExample resource from the list
  2. Hover over the resource card for a moment, three vertical dots should appear: — select this button to open a new menu with a Copy resource id option
  3. Select Copy resource id to copy the value:

  1. In the top right corner of the nRD window is another button with three vertical dots, this one white on blue:

  1. Select this button to open the More menu
  2. Select Unpair from the More menu:

  1. In the Unpair window, select the Resource ID field and paste the Resource ID you copied earlier. Then select the checkmark in the lower right to save the Resource ID:

  1. Select the Send button to unpair :

The NestOWPButtonExample resource should disappear from the list. Refresh the web page to make sure.

This only removes the resource from the Service. We also need to unpair it from the Weave fabric. Hold down Button 4 on the ButtonExample end-node for at least 10 seconds to factory reset the device and remove its provisioning configuration.

When successful, LED1 on the device will no longer light up in response to the Button 1 press on either the LightExample or ButtonExample end-node.

Resources and traits

Now that the ButtonExample resource is gone, take another look at the resources and traits in your nRD project. Select the NestOWPLightExample resource, which has 12 published traits. The traits appear on the right side of the window:

This resource publishes the LightState trait, which reflects the state of LED1 on the LightExample end-node. Press Button 1 on the end-node a few times.

LED1 should go on and off, and the LightState trait on nRD should switch between OFF and ON while its brightness switches between 0 and 100:

Traits in Weave are defined by Weave Schema Description Language (WDL), which is a domain-specific language based on Google Protocol Buffers v3. If you're familiar with protobufs, this .proto file may look familiar:

message LightStateTrait {

  enum CircuitState {
      CIRCUIT_STATE_UNSPECIFIED = 0;
      CIRCUIT_STATE_ON = 1;
      CIRCUIT_STATE_OFF = 2;
  };

  // ----------- PROPERTIES ----------- //

  CircuitState state = 1;

  // When the state switches from 'OFF' to 'ON', it shall turn on
  // the light to the level specified in this field.
  //
  // When the state switches from 'ON' to 'OFF', it should not
  // alter this value.
  //
  // Additionally, this is a normalized field represented by an
  // 8-bit value (from 0 - 100).
  //

  uint32 brightness = 2 [uint_constraints: { width: 8, min: 0, max: 100 }];

}

It defines the two properties (state and brightness) observed for the trait in nRD, along with potential values.

A Weave fabric without any end-node subscribers to the LightState trait is no fun. Let's pair ButtonExample, which will subscribe to LightState trait and react to its change in state.

Power cycle ButtonExample

As seen in nRD, the Raspberry Pi 3B+ Border Router (NestOWPLinux) and the LightExample end-node (NestOWPLightExample) are already registered to the Service and paired to the Weave fabric. We'll now use Thread-assisted pairing via the Border Router to pair the ButtonExample end-node.

To do this, we must first set up an IPv6 tunnel from Weave Device Manager to the ButtonExample end-node via the Border Router. This tunnel is called the Remote Passive Rendezvous (RPR) tunnel.

First, power cycle the ButtonExample end-node, by flicking the Power switch on the top left of the board off and on.

When the switch is off, LED5 should be off:

When you switch it back on, LED5 blinks again:

After cycling, it should automatically start in discovery mode as a Thread node, sending out MLE (Mesh Link Establishment) beacons, which means it's ready to join a Thread network.

Generate Service credentials

To register a device to a Nest Service and observe it through nRD, we need to generate Weave credentials.

Switch to your Terminal window and run weave-register-service with the parameters in the example shown below. Use the same nestlabs.com credentials you used for the nRD project (and listed on the OpenWeave House). Replace the <ID> below with the ID of your House.

This script logs into the Service the same way the Nest mobile app would, and returns the access tokens needed to interact with the account structure (the home):

$ ~/weave/src/test-apps/happy/bin/weave-register-service \
   -t google-io-2018 -u io2018+<ID>@nestlabs.com \
   -p TestPassword123
2018-03-27 20:28:14,044 [WeaveRegisterService] get auth info for user
    io2018+<ID>@nestlabs.com
2018-03-27 20:28:14,527 [WeaveRegisterService] WeaveRegisterService:
    Authentication successful


Weave Access Token:
lQkANQEwAQhs/jVJx4yNuiQCBDcDLAEKMTUyMjE2OTUwMBgmBJqu7yImBZpXFTY3BiwBCjE1MjI
xNjk1MDAYJAcCJgglAFojMAo5BFUGYtAr1z136l8DG1APQEVaQGIxKr1mOKNdl9T08vBayYf487
5iAQqxu7REK6v1B1+UYGuGCiGbNYMpARg1gikBJAIFGDWEKQE2AgQCBAEYGDWBMAIIQugdtoGkp
9MYNYAwAghC6B22gaSn0xg1DDABHC0BcnYUGhEWP1t1ipF5S1HbARFKpgwaboU4NN8wAh0A7dHo
lYDmBXrCttNW2aH27yKS+X8p3unGdhLgjBgYNQImASUAWiMwAhwsA6QgdhyG5am/uRPdMe4LnLU
Rj8zuwM7pHVdoGBg=


weave-register-service generated the service registration command:
register-service  --account-id USER_016317D573022C1C --pairing-token 
wu.G61srTmUdZglG7i+i8AcoUj6OfOhn5f5xFbE6qFqiQBXpCvgXpVKcNXYMUJxiTcGPsCvXRVd
P7hMgkU+ecs1XXnpKxE= --service-config 1QAADwABADYBFTABCQCoNCLp2XXkVSQCBDcDJ
xMBAADu7jC0GBgmBJUjqRkmBRXB0iw3BicTAQAA7u4wtBgYJAcCJggVAFojMAoxBHhS4pySunAZ
WEZtrhhySvtDDfYHKTMNYVXlZUaOug2lP7UXwEdkRAIYT6gRJFDUezWDKQEpAhg1gikBJAJgGDW
BMAIIQgys9rRkceYYNYAwAghCDKz2tGRx5hg1DDABGQC+DtqhY1qO8VIXRYC93JQS1MwcLDNOKd
wwAhkAi+fuLhEXFK6S2is7bS/XXZ5fzbi6L2V2GBgVMAEIbP41SceMjbokAgQ3AywBCjE1MjIxN
jk1MDAYJgSaru8iJgWaVxU2NwYsAQoxNTIyMTY5NTAwGCQHAiYIJQBaIzAKOQRVBmLQK9c9d+pf
AxtQD0BFWkBiMSq9ZjijXZfU9PLwWsmH+PO+YgEKsbu0RCur9QdflGBrhgohmzWDKQEYNYIpASQ
CBRg1hCkBNgIEAgQBGBg1gTACCELoHbaBpKfTGDWAMAIIQugdtoGkp9MYNQwwARwtAXJ2FBoRFj
9bdYqReUtR2wERSqYMGm6FODTfMAIdAO3R6JWA5gV6wrbTVtmh9u8ikvl/Kd7pxnYS4IwYGBg1A
icBAQAAAAIwtBg2AhUsAR5wZW5qYS1pby51bnN0YWJsZS5uZXN0bGFicy5jb20lAp9RGBgYGA==
--init-data '{"where_id": 
"00000000-0000-0000-0000-000100000010", "structure_id": 
"STRUCTURE_016317D573022C1D", "spoken_where_id": 
"00000000-0000-0000-0000-000100000010"}'

Make a copy of your specific output! It contains your unique Access Token and Service Registration command for a later step.

Start Weave Device Manager

In the Terminal window, open a second tab with Shell > New Tab > Basic. In this new tab, start Weave Device Manager:

$ ~/weave/output/x86_64-apple-darwin/bin/weave-device-mgr
WEAVE:ML: Binding general purpose IPv4 UDP endpoint to [::]:11095
WEAVE:IN: IPV6_PKTINFO: 22
WEAVE:ML: Listening on general purpose IPv4 UDP endpoint
WEAVE:ML: Binding general purpose IPv6 UDP endpoint to [::]:11095 ()
WEAVE:IN: IP_PKTINFO: 22
WEAVE:ML: Listening on general purpose IPv6 UDP endpoint
Weave Device Manager Shell

weave-device-mgr >

Rendezvous with the Border Router

To use Device Manager, you have to connect it to a device.

Let's start by making a "rendezvous" with the Border Router. A rendezvous uses the Weave CASE (Certificate-assisted session establishment) protocol to create a secure connection over Wi-Fi to the Border Router. This connection uses the Weave Access Token you received from the register-service command in the previous step. Once you have initiated a secure session, you can send Weave commands to the device.

Use the Node ID for the Border Router (printed on the OpenWeave House) preceded by 0x for target-device and your Weave Access Token for access-token.

For example, if the Node ID is 18B430AA00030001, use 0x18B430AA00030001 in the command.

There will be a lot of output for the rendezvous command:

weave-device-mgr > rendezvous --target-device 0x18B430AA00030001
   --access-token lQkANQEwAQhs/jVJx4yNuiQCBDcDLAEKMTUyMjE2OTUwMBgmBJqu7yImB
ZpXFTY3BiwBCjE1MjIxNjk1MDAYJAcCJgglAFojMAo5BFUGYtAr1z136l8DG1APQEVaQGIxKr1m
OKNdl9T08vBayYf4875iAQqxu7REK6v1B1+UYGuGCiGbNYMpARg1gikBJAIFGDWEKQE2AgQCBAE
YGDWBMAIIQugdtoGkp9MYNYAwAghC6B22gaSn0xg1DDABHC0BcnYUGhEWP1t1ipF5S1HbARFKpg
waboU4NN8wAh0A7dHolYDmBXrCttNW2aH27yKS+X8p3unGdhLgjBgYNQImASUAWiMwAhwsA6Qgd
hyG5am/uRPdMe4LnLURj8zuwM7pHVdoGBg=
WEAVE:DM: Initiating connection to device
WEAVE:ML: Binding general purpose IPv4 UDP endpoint to [::]:11095
WEAVE:IN: IPV6_PKTINFO: 22
WEAVE:ML: Listening on general purpose IPv4 UDP endpoint
WEAVE:ML: Binding general purpose IPv6 UDP endpoint to [::]:11095 ()
WEAVE:IN: IP_PKTINFO: 22
WEAVE:ML: Listening on general purpose IPv6 UDP endpoint
WEAVE:ML: Adding lo0 to interface table
WEAVE:ML: Adding en0 to interface table
WEAVE:ML: Adding awdl0 to interface table
WEAVE:ML: Adding utun0 to interface table
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:DM: Sending IdentifyRequest to locate device
WEAVE:EM: Msg sent 0000000E:1 16 18B430AA00030001 0000 ACEC 0 MsgId:3AF141A8
WEAVE:EM: Msg rcvd 0000000E:2 86 18B430AA00030001 0000 ACEC 0 MsgId:75720437
WEAVE:DM: Received identify response from device 18B430AA00030001 ([fe80::d01f:9453:8c51:b521]:11095%en0)
WEAVE:DM: Initiating weave connection to device 18B430AA00030001 (fe80::d01f:9453:8c51:b521)
WEAVE:ML: Con start 9BE0 18B430AA00030001 0001
WEAVE:ML: TCP con start 9BE0 fe80::d01f:9453:8c51:b521 11095
WEAVE:ML: TCP con complete 9BE0 0
WEAVE:ML: Con complete 9BE0
WEAVE:DM: Connected to device
WEAVE:DM: Initiating CASE session
WEAVE:EM: ec id: 1, AppState: 0x96be9e8
WEAVE:SM: CASE:GenerateBeginSessionRequest
WEAVE:SM: CASE:AppendNewECDHKey
WEAVE:SM: CASE:AppendCertInfo
WEAVE:SM: CASE:AppendPayload
WEAVE:SM: CASE:AppendSignature
WEAVE:SM: CASE:GetNodePrivateKey
WEAVE:SM: CASE:GenerateECDSASignature
WEAVE:SM: CASE:EncodeWeaveECDSASignature
WEAVE:EM: Msg sent 00000004:10 408 18B430AA00030001 9BE0 ACED 0 MsgId:0000000A
WEAVE:SM: StartSessionTimer
WEAVE:EM: Msg rcvd 00000004:13 8 18B430AA00030001 9BE0 ACED 0 MsgId:0000010A
WEAVE:SM: CASE:ProcessReconfigure
WEAVE:EM: ec id: 2, AppState: 0x96be9e8
WEAVE:SM: CASE:GenerateBeginSessionRequest
WEAVE:SM: CASE:AppendNewECDHKey
WEAVE:SM: CASE:AppendCertInfo
WEAVE:SM: CASE:AppendPayload
WEAVE:SM: CASE:AppendSignature
WEAVE:SM: CASE:GetNodePrivateKey
WEAVE:SM: CASE:GenerateECDSASignature
WEAVE:SM: CASE:EncodeWeaveECDSASignature
WEAVE:EM: Msg sent 00000004:10 406 18B430AA00030001 9BE0 ACEE 0 MsgId:0000000B
WEAVE:SM: StartSessionTimer
WEAVE:EM: Msg rcvd 00000004:11 399 18B430AA00030001 9BE0 ACEE 0 MsgId:0000010B
WEAVE:SM: CASE:ProcessBeginSessionResponse
WEAVE:SM: CASE:VerifySignature
WEAVE:SM: CASE:DecodeCertificateInfo
WEAVE:SM: CASE:ValidateCert
WEAVE:SM: CASE:DecodeWeaveECDSASignature
WEAVE:SM: CASE:VerifyECDSASignature
WEAVE:SM: CASE:DeriveSessionKeys
WEAVE:EM: Msg sent 00000004:12 32 18B430AA00030001 9BE0 ACEE 0 MsgId:0000000C
WEAVE:SM: CancelSessionTimer
WEAVE:DM: Secure session established
Connected to device 18B430AA00030001 at fe80::d01f:9453:8c51:b521
weave-device-mgr (18B430AA00030001 @ fe80::d01f:9453:8c51:b521) >

The Device Manager prompt now shows the resource we're connected to (18B430AA00030001), along with the Weave IPv6 address endpoint (fe80::d01f:9453:8c51:b521).

Now let's get some information about the existing configuration. Get the device's network configuration by running the get-networks command:

weave-device-mgr (18B430AA00030001 @ fe80::d01f:9453:8c51:b521) > get-networks 
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 00000003:11 1 18B430AA00030001 9BE0 ACEF 0 MsgId:00000000
WEAVE:EM: Msg rcvd 00000003:12 196 18B430AA00030001 9BE0 ACEF 0 MsgId:00000000
Get networks complete, 2 network(s) returned
  Network 1
    Network Type: WiFi
    Network Id: 3641817723
    WiFi SSID: "#codelabs"
    WiFi Mode: Managed
    WiFi Role: Station
    WiFi Security Type: WPA2Mixed
    WiFi Key: gcod3lab!
    Wireless Signal Strength: 0
  Network 2
    Network Type: Thread
    Network Id: 2324941915
    Thread Network Name: "NEST-PAN-4D48"
    Thread Extended PAN Id: 82e358cedf7d9b85
    Thread Network Key: 6766884a951535cd8d9b9d66ad832a05
    Thread PAN Id: 336e
    Thread Channel: 26
    Wireless Signal Strength: 0

You should see two networks: one Wi-Fi and one Thread. The Thread network connects the Border Router and the LightExample end-node.

Make note of the below Thread network values in your output, you'll need them for a later command. In the example above, the values are:

Let's also get the Weave fabric configuration, so the ButtonExample end-node can join the Weave fabric:

weave-device-mgr (18B430AA00030001 @ fe80::d01f:9453:8c51:b521) > get-fabric-config 
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 00000005:3 0 18B430AA00030001 9BE0 ACF0 0 MsgId:00000001
WEAVE:EM: Msg rcvd 00000005:4 78 18B430AA00030001 9BE0 ACF0 0 MsgId:00000001
Get fabric config complete
Fabric configuration: 1QAABQABACcBSE2Ig9jkRLE2AhUlAQEQJAIBMAMQfJfkLWr5G3a4RiG64GAB3zA
EFOs1UHniaVx3qsYpchK2fT0dtrjfJAUAJAYAGBgY

Make note of the Fabric configuration value at the end of the output. In the example above, it's:

1QAABQABACcBSE2Ig9jkRLE2AhUlAQEQJAIBMAMQfJfkLWr5G3a4RiG64GAB3zAEFOs1UHniaVx3qsYpchK2fT0dtrjfJAUAJAYAGBgY

Construct the pairing commands

Before initiating the RPR tunnel, it's a good idea to construct all the commands you need ahead of time, so you can easily copy-paste them into Weave Device Manager. The pairing must be done within 30 seconds (for security purposes), so if you don't have the commands on hand and ready to go, the pairing process may time out and you'll have to do it again.

Open the Sublime Text application on the kiosk:

It opens to a blank text file. Construct each of the commands below in this empty file, in order.

The commands you'll need are:

1. Create the RPR tunnel. Use the pairing code for the ButtonExample end-node as labeled on the OpenWeave House.

The parameters in this command are:

We'll set the timeouts to 300 seconds (5 minutes) each. This won't have an effect on the pairing process, as it will still timeout within 30 seconds, but the parameters are currently required for this command.

remote-passive-rendezvous -r 300 -i 300 -p <pairing code>

2. Add Thread network credentials (from the get-networks command) to the end-node, so it knows what Thread network to join.

The parameters in this command are (from the example output in the previous step):

add-thread-network "NEST-PAN-4D48" 82e358cedf7d9b85 6766884a951535cd8d9b9d66ad832a05

3. Enable the Thread network on the end-node, using the network id value output in the previous command (add-thread-network):

enable-network <network id>

For example, the add-thread-network command gives the following output:

weave-device-mgr (18B430AA00050001 @ ::) > add-thread-network "NEST-PAN-4D48" 
82e358cedf7d9b85 6766884a951535cd8d9b9d66ad832a05
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 00000003:3 77 18B430AA00050001 9BE0 ACF4 0 MsgId:00000000
WEAVE:EM: Msg rcvd 00000003:4 4 18B430AA00050001 9BE0 ACF4 0 MsgId:00000000
Add thread network complete (network id = 2324941915)

The network id is at the end. That value is used in the enable-network command, like so:

enable-network 2324941915

4. Join the Weave fabric using the fabric configuration value output from the earlier get-fabric-config command:

join-existing-fabric "1QAABQABACcBQPDdp+WGB6w2AhUlAQEQJAIBMAMQ5N2Iuk5Mgh2GsMnwQDNwRDAEFGXiClD
Ut+7bEObb7/ZeXlWoVkDwJAUAJAYAGBgY"

5. Register the device to the Service with the register-service command generated at the very beginning of this step. Remember, this command is used to register a new device with the Service:

register-service  --account-id USER_016317D573022C1C 
   --pairing-token wu.G61srTmUdZglG7i+i8AcoUj6OfOhn5f5xFbE6qFqiQBX
pCvgXpVKcNXYMUJxiTcGPsCvXRVdP7hMgkU+ecs1XXnpKxE= 
   --service-config 1QAADwABADYBFTABCQCoNCLp2XXkVSQCBDcDJxMBAADu7j
C0GBgmBJUjqRkmBRXB0iw3BicTAQAA7u4wtBgYJAcCJggVAFojMAoxBHhS4pySunAZ
WEZtrhhySvtDDfYHKTMNYVXlZUaOug2lP7UXwEdkRAIYT6gRJFDUezWDKQEpAhg1gi
kBJAJgGDWBMAIIQgys9rRkceYYNYAwAghCDKz2tGRx5hg1DDABGQC+DtqhY1qO8VIX
RYC93JQS1MwcLDNOKdwwAhkAi+fuLhEXFK6S2is7bS/XXZ5fzbi6L2V2GBgVMAEIbP
41SceMjbokAgQ3AywBCjE1MjIxNjk1MDAYJgSaru8iJgWaVxU2NwYsAQoxNTIyMTY5
NTAwGCQHAiYIJQBaIzAKOQRVBmLQK9c9d+pfAxtQD0BFWkBiMSq9ZjijXZfU9PLwWs
mH+PO+YgEKsbu0RCur9QdflGBrhgohmzWDKQEYNYIpASQCBRg1hCkBNgIEAgQBGBg1
gTACCELoHbaBpKfTGDWAMAIIQugdtoGkp9MYNQwwARwtAXJ2FBoRFj9bdYqReUtR2w
ERSqYMGm6FODTfMAIdAO3R6JWA5gV6wrbTVtmh9u8ikvl/Kd7pxnYS4IwYGBg1AicB
AQAAAAIwtBg2AhUsAR5wZW5qYS1pby51bnN0YWJsZS5uZXN0bGFicy5jb20lAp9RGB
gYGA== 
   --init-data '{"where_id": "00000000-0000-0000-0000-000100000010", 
"structure_id": "STRUCTURE_016317D573022C1D", "spoken_where_id": 
"00000000-0000-0000-0000-000100000010"}'

Alright, you should now have a Sublime Text file with all five commands tailored to the values for your kiosk and session, ready for copying. Like so:

Remember, enable-network won't have a network id yet, you'll get that when you run add-thread-network.

Ok, time to pair!

Passive rendezvous with ButtonExample

To pair the ButtonExample end-node, let's talk to it with the remote-passive-rendezvous command. This command initiates a PASE (Password-assisted session establishment) session with ButtonExample.

PASE uses the device pairing code for authentication, unlike CASE, which uses the Weave certificate for authentication.

Command 1:

Use the remote-passive-rendezvous command you constructed in the previous step to initiate the RPR tunnel:

weave-device-mgr (18B430AA00030001 @ fe80::d01f:9453:8c51:b521) > 
   remote-passive-rendezvous -r 300 -i 300 -p W9DDSW
WEAVE:DM: RemotePassiveRendezvous (
WEAVE:DM:    rendezvousDeviceAddr = ::,
WEAVE:DM:    rendezvousTimeoutSec   = 300,
WEAVE:DM:    inactivityTimeoutSec   = 500 )
WEAVE:DM: Sending RPR request...
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 00000006:6 20 18B430AA00030001 9BE0 ACF1 0 MsgId:00000002
WEAVE:EM: Msg rcvd 00000000:1 6 18B430AA00030001 9BE0 ACF1 0 MsgId:00000002
WEAVE:DM: Entering HandleDeviceControlReponse
WEAVE:DM: RemotePassiveRendezvousRequest succeeded
WEAVE:DM: Waiting for RemoteConnectionComplete...
WEAVE:EM: Msg rcvd 00000006:7 0 18B430AA00030001 9BE0 ACF1 0 MsgId:00000003
WEAVE:DM: Entering HandleRemotePassiveRendezvousComplete
WEAVE:DM: Received RemoteConnectionComplete
WEAVE:EM: ec id: 2, AppState: 0x9e01ac00
WEAVE:DM: Sending RPR IdentifyRequest to remote device
WEAVE:EM: Msg sent 0000000E:1 16 FFFFFFFFFFFFFFFF 9BE0 ACF2 0 MsgId:0000000D
WEAVE:DM: Sent IdentifyRequest successfully
WEAVE:EM: Msg rcvd 00000006:10 0 18B430AA00050001 9BE0 0707 0 MsgId:00000000
WEAVE:EM: Msg rcvd 0000000E:2 74 18B430AA00050001 9BE0 ACF2 0 MsgId:00000001
WEAVE:DM: Received RPR identify response from device 18B430AA00050001 ([fe80::d01f:9453:8c51:b521]:11095, con 9BE0)
WEAVE:DM: Setting mDeviceCon source node ID = 18B430AA00050001
WEAVE:DM: Initiating PASE session
WEAVE:EM: ec id: 1, AppState: 0x96be9e8
WEAVE:EM: Msg sent 00000004:1 296 18B430AA00050001 9BE0 ACF3 0 MsgId:0000000E
WEAVE:SM: StartSessionTimer
WEAVE:EM: Msg rcvd 00000004:2 284 18B430AA00050001 9BE0 ACF3 0 MsgId:00000002
WEAVE:EM: Msg rcvd 00000004:3 144 18B430AA00050001 9BE0 ACF3 0 MsgId:00000003
WEAVE:EM: Msg sent 00000004:4 176 18B430AA00050001 9BE0 ACF3 0 MsgId:0000000F
WEAVE:EM: Msg rcvd 00000004:5 32 18B430AA00050001 9BE0 ACF3 0 MsgId:00000004
WEAVE:SM: CancelSessionTimer
WEAVE:DM: Secure session established
WEAVE:DM: Successfully authenticated remote device.
Successfully connected to remote device 18B430AA00050001
weave-device-mgr (18B430AA00050001 @ ::) >

We've now set up the full PASE-secured IPv6 tunnel between the Device Manager and the ButtonExample end-node, by way of the Border Router:

With the RPR tunnel active, we can finally pair the ButtonExample end-node and register it to the Service.

Join the Thread network

Command 2:

Add the Thread network credentials, so it knows what Thread network to join:

weave-device-mgr (18B430AA00050001 @ ::) > add-thread-network "NEST-PAN-4D48" 
82e358cedf7d9b85 6766884a951535cd8d9b9d66ad832a05
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 00000003:3 77 18B430AA00050001 9BE0 ACF4 0 MsgId:00000000
WEAVE:EM: Msg rcvd 00000003:4 4 18B430AA00050001 9BE0 ACF4 0 MsgId:00000000
Add thread network complete (network id = 2324941915)

Command 3:

Note the network id value in the last line of the add-thread-network output. In the example above it's 2324941915. Copy it and use it in the next command, enable-network. This joins the ButtonExample end-node to that Thread network:

weave-device-mgr (18B430AA00050001 @ ::) > enable-network 2324941915
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 00000003:7 4 18B430AA00050001 9BE0 ACF5 0 MsgId:00000001
WEAVE:EM: Msg rcvd 00000000:1 6 18B430AA00050001 9BE0 ACF5 0 MsgId:00000001
Enable network complete

Join the Weave fabric

Command 4:

Now we can join the ButtonExample end-node to the Weave fabric:

weave-device-mgr (18B430AA00050001 @ ::) > join-existing-fabric
   "1QAABQABACcBSE2Ig9jkRLE2AhUlAQEQJAIBMAMQfJfkLWr5G3a4RiG64GAB3zAEFOs1UHn
   iaVx3qsYpchK2fT0dtrjfJAUAJAYAGBgY"
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 00000005:5 78 18B430AA00050001 9BE0 ACF6 0 MsgId:00000002
WEAVE:EM: Msg rcvd 00000000:1 6 18B430AA00050001 9BE0 ACF6 0 MsgId:00000002
Join existing fabric complete

Register with the Service

Command 5:

Almost there! Finally, register the end-node with the Service, using that long register-service command we generated earlier:

weave-device-mgr (18B430AA00050001 @ ::) > register-service  
   --account-id USER_016317D573022C1C 
   --pairing-token wu.dgpmwQjSMiJlGilrwhrBuT7zqtTjKkzo3v8ERWJ6ESUmOOYMnruNB
NRkjBsbUVq8hsi8Cg7NposyvZNQObL50gCvyQE= 
   --service-config 1QAADwABADYBFTABCQCoNCLp2XXkVSQCBDcDJxMBAADu7jC0GBgmBJU
jqRkmBRXB0iw3BicTAQAA7u4wtBgYJAcCJggVAFojMAoxBHhS4pySunAZWEZtrhhySvtDDfYHKT
MNYVXlZUaOug2lP7UXwEdkRAIYT6gRJFDUezWDKQEpAhg1gikBJAJgGDWBMAIIQgys9rRkceYYN
YAwAghCDKz2tGRx5hg1DDABGQC+DtqhY1qO8VIXRYC93JQS1MwcLDNOKdwwAhkAi+fuLhEXFK6S
2is7bS/XXZ5fzbi6L2V2GBgVMAEID1WTVDRbqrMkAgQ3AywBCjE1MjIxNjk1MDUYJgQ4su8iJgU
4WxU2NwYsAQoxNTIyMTY5NTA1GCQHAiYIJQBaIzAKOQSc40urGf9CjKfevJOUYStUFPKYFMdv5i
0vrDM0iCno34MbDNv3UWiUiC5ENi+nJY2c2t9PqEldxTWDKQEYNYIpASQCBRg1hCkBNgIEAgQBG
Bg1gTACCEAp7cHfN/oPGDWAMAIIQCntwd83+g8YNQwwARw4iFZlw7gpGaJB11IFAQe6g6jIIaBa
t1vP/2CjMAIdAKZmwVBZ6QyCfi+IbHfv3D4xzhOejiQuDi7DN9EYGBg1AicBAQAAAAIwtBg2AhU
sAR5wZW5qYS1pby51bnN0YWJsZS5uZXN0bGFicy5jb20lAp9RGBgYGA== 
   --init-data '{"where_id": "00000000-0000-0000-0000-000100000010", 
"structure_id": "STRUCTURE_016317D573022C1D", "spoken_where_id": 
"00000000-0000-0000-0000-000100000010"}'
WEAVE:EM: ec id: 1, AppState: 0x9e01ac00
WEAVE:EM: Msg sent 0000000F:1 821 18B430AA00050001 9BE0 ACEB 0 MsgId:00000004
WEAVE:EM: Msg rcvd 00000000:1 6 18B430AA00050001 9BE0 ACEB 0 MsgId:00000004
Register service complete

The device should now be paired and registered. Switch to nRD and refresh the project page. There should be a new resource in the Resource Watcher called NestOWPButtonExample. This is your newly paired ButtonExample end-node!

Back in Weave Device Manager, close the connection to the device:

weave-device-mgr (18B430AA00050001 @ ::) > close
WEAVE:DM: Closing connection to device
WEAVE:ML: Closing endpoints

Exit Device Manager now that everything is paired:

weave-device-mgr > exit

Before continuing, ensure the ButtonExample end-node has properly subscribed to published Weave traits. Power cycle it by turning the Power switch OFF and ON again.

In Weave, the LightExample and ButtonExample end-nodes both monitor the LightState trait, but LightExample serves as the trait publisher, while ButtonExample serves as a subscriber to that trait.

Change the trait state

Press Button 1 on either end-node and observe how LED1 on each device changes.

LED1 on LightExample should change first, regardless of which end-node you press the button on. That's because the LightExample resource is the trait publisher. LED1 on ButtonExample should reflect the state of LED1 on LightExample because ButtonExample is a subscriber of the trait.

Check nRD

Still pressing Button 1 on either end-node, observe the changes that occur on nRD. You should have noticed that only the LightExample resource updates (the resource and trait cards flash). The ButtonExample resource never updates, even when you press Button 1 on that end-node.

Even though all devices in our fabric are tracking the LightState trait, nRD only displays the traits that a device publishes. That's why only the LightExample resource updates.

Publisher vs subscriber

Clearly, both end-nodes respond to a single press of Button 1 on either end-node. When you press Button 1 on ButtonExample (subscriber), it sends a Weave command to LightExample (publisher) to update the state of the LightState trait. LightExample then notifies all subscribers to that trait of the updated state:

When you press Button 1 on LightExample, it starts at step 3 in the above diagram: turn on LED1 and notify all other subscribers of the LightState trait update.

Demonstrate resubscription

The benefit of Weave is its reliability when it comes to subscriptions. Let's demonstrate this by power cycling the ButtonExample end-node and observing its behavior after rebooting.

  1. Press Button 1 on LightExample until LED1 is off for both end-nodes
  2. Power down the ButtonExample end-node by setting its Power switch to OFF
  3. Press Button 1 on LightExample to turn on its LED1
  4. Switch the Power on ButtonExample to ON
  5. After a few seconds, LED1 on ButtonExample should light to sync its LightState trait to LightExample!

You might have expected ButtonExample to have retained its last known state (LED1 is off). But upon rebooting, it rejoins the Thread network and Weave fabric, resubscribes to the LightState on the LightExample, and retrieves the most up-to-date copy of the data.

Factory reset the ButtonExample end-node

Let's prep the House for the next user. Remove the fabric configuration for ButtonExample end-node by performing a factory reset:

  1. Press Button 1 on ButtonExample to turn on LED1
  2. Press and hold Button 4 on ButtonExample until LED1 turns off (approximately 10 seconds)

You now know:

Further reading

Check openweave.io and openthread.io for a variety of references.