Reply
Posts: 38
Registered: ‎08-11-2017
Accepted Solution

Mesh Configuration: Appkey Deployment Fail

Hello,

 

I am trying to set up a light node from the soc_btmesh_light example project to act as a provisioner as described in this previous post http://community.silabs.com/t5/Bluetooth-Wi-Fi/Bluetooth-mesh-provisioning/m-p/208861.

 

The provisioner creates network and application keys once it has been initiated as a provisioner which both appear to be successful.

case gecko_evt_mesh_prov_initialized_id:
{
	struct gecko_msg_mesh_prov_initialized_evt_t *initialized_evt;
	initialized_evt = (struct gecko_msg_mesh_prov_initialized_evt_t *)&(evt->data);
	printf("gecko_evt_mesh_prov_initialized_id\r\n");

	if (initialized_evt->networks) {
		printf("Network keys already created, skipping.\r\n");
	} else {
		// create network key
		struct gecko_msg_mesh_prov_create_network_rsp_t* network_resp;
		network_resp = gecko_cmd_mesh_prov_create_network(16,network_key);
		nwkid = network_resp->network_id;
		printf("Network keys created, index %x.\r\n", nwkid);

		// create application key
		struct gecko_msg_mesh_prov_create_appkey_rsp_t* appkey_resp;
		appkey_resp = gecko_cmd_mesh_prov_create_appkey(nwkid, 16, application_key);
		
		if (appkey_resp->result == 0) {	// sucessfully created appkey
			printf("Application key created. Index: %x\r\n", appkey_resp->appkey_index);
			appid = appkey_resp->appkey_index;
		} else {
			printf("Failed to create application key - error: %x\r\n", appkey_resp->result);
		}
	}

	// start scanning for unprovisioned beacons
	struct gecko_msg_mesh_prov_scan_unprov_beacons_rsp_t *scan_init = gecko_cmd_mesh_prov_scan_unprov_beacons();

	if (scan_init->result == 0) {
		printf("Success - now scanning for unprovisioned beacons\r\n");
	} else {
		printf("Failed with code: %x\r\n", scan_init->result);
	}
	
	break;
}

 

The provisioner then provisions a node using the PB-ADV, which is successful. Upon success it attempts to deploy the appkey to the newly provisioned node using gecko_cmd_mesh_prov_appkey_add:

 

case gecko_evt_mesh_prov_device_provisioned_id:
{
	struct gecko_msg_mesh_prov_device_provisioned_evt_t *prov_evt;
	prov_evt = (struct gecko_msg_mesh_prov_device_provisioned_evt_t *)&(evt->data);

	printf("gecko_evt_mesh_prov_device_provisioned_id\r\n");
	printf("Successfully provisioned %s to address %x\r\n", UUID_Cast_ASCII(UUID_Cast_To_UUID(prov_evt->uuid.data), true) , prov_evt->address);
	UUID_List_Clear();	// TODO Better way to remove device from the UUID list than clearing list and re-populating?
	LCD_write("provisioner - added", LCD_ROW_STATUS);
	current_mode = MODE_PROVISION_SUCCESS;

	// Beginning configuration - deploying appkey to node
	struct gecko_msg_mesh_prov_appkey_add_rsp_t *appkey_deploy_evt;
	appkey_deploy_evt = gecko_cmd_mesh_prov_appkey_add(prov_evt->address, nwkid, appid);
	if (appkey_deploy_evt->result == 0) {
		printf("Appkey deployed to %x\r\n", prov_evt->address);
	} else {
		printf("Appkey deployment failed. error: %x\r\n", appkey_deploy_evt->result);
	}
	break;
}

 

When I run this I end up with error 0x180: invalid_param. 

gecko_evt_endpoint_status_id type:0
gecko_evt_endpoint_status_id type:0
gecko_evt_endpoint_status_id type:100
gecko_evt_endpoint_status_id type:10
gecko_evt_system_boot_id
Success - Initialized as provisioner
gecko_evt_mesh_prov_initialized_id
Network keys created, index 0.
Application key created. Index: 0
Success - now scanning for unprovisioned beacons
Printing UUID list. num_uuids = 1
UUID #0: SilabsDev-e3▒W
                       new: 000B579333652D7665447362616C6953
Ready to send provisioning request by ADV. Sending to UUID SilabsDev-e3▒W

------------------------------------------------------------------------------------
Beginning to provision node.
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
evt:gecko_evt_le_gap_adv_timeout_id
gecko_evt_mesh_prov_device_provisioned_id
Successfully provisioned 000B579333652D7665447362616C6953 to address 1
Appkey deployment failed. error: 180
evt:gecko_evt_le_gap_adv_timeout_id

 

This seems like the problem is with the arguments to gecko_cmd_mesh_prov_appkey_add(),  however, I've spent a fair bit of time looking at the API and haven't been able find where I went wrong here.

 

1) What am I doing to cause the 0x180 error? Am I doing something out of sequence? The sequence of calls I expect to make are:

Initialize provisioner - gecko_cmd_mesh_prov_init()

a) Create network key - gecko_cmd_mesh_prov_create_network()

b) Create application key - gecko_cmd_mesh_prov_create_appkey()

c) Scan for beacons - gecko_cmd_mesh_prov_scan_unprov_beacons()

d) Provision node - gecko_cmd_mesh_prov_provision_device()

e) Deploy appkey to node - gecko_cmd_mesh_prov_appkey_add()

f) Bind model to appkey - gecko_cmd_mesh_prov_model_app_bind()

g) Add subscription address - gecko_cmd_mesh_prov_model_sub_add()

h) Set model publication parameters - gecko_cmd_mesh_prov_model_pub_set()

Looping back to step d for each additional node to be provisioned.

 

2) The provisioning node will have a touchscreen display and will act as a controller for a group of devices, I would like to use it to provision the network and then reboot and be able to communicate as a node of the network. I don't see a way for the provisioner to configure the models for itself, when it is set up as a provisioner it can't use the configuration functions as it can't communicate with itself and unless I am mistaken there are no functions set up for a node to configure itself. Is there a method I could use to get the node configured?

 

In case it might help I've attached my modified copy of main.c, which is from the soc_btmesh_light example project, I'm afraid it's a bit rough as I'm just trying to get something working to understand how the provisioning process works before I write the actual application code.

 

Thanks in advance,

Rob

Posts: 38
Registered: ‎08-11-2017

Re: Mesh Configuration: Appkey Deployment Fail

I still haven't been able to get past this.

I've tried hard coding the values for the appkey deployment, both the network and application key indexes are 0 and the assigned mesh addressing always seems to start at 1 so I've tried calling gecko_cmd_mesh_prov_appkey_add() like this:

 

appkey_deploy_evt = gecko_cmd_mesh_prov_appkey_add((uint16)1, (uint16)0, (uint16)0);

  Which results the same 0x180 error code for both of the devices I provision (I have three SLWSTK6020 kits available).

 

If I send bogus values (such as (2, 2, 2)) the response is 0x0C02: does_not_exist which makes sense as there are not addresses or key ids to match these values.

Other arguments I've tried include:

(1,0,1)  -  Error 0xC02

(14,0,0)  -  Error 0xC02

(2,0,0) - Error 0xC02 for the first device and then error 0x180 for the second once address 2 has been assigned.

 

I've tried provisioning with both the GATT and ADV bearers which hasn't appeared to make a difference here.

 

If anyone has ideas, even something far-fetched I would be glad to have some feedback.

 

Thanks,

Rob

 

Posts: 38
Registered: ‎08-11-2017

Re: Mesh Configuration: Appkey Deployment Fail

I stumbled onto a solution for this problem.

 

When the node was provisioned the netkey is assigned to the node, however, before the appkey can be deployed the netkey must be deployed again to prevent error 0x180 even though it already has been deployed. This is against what is written in rev 2.3 of the Bluetooth Mesh Software API Reference Manual on page 165 where it says:


The selected network key must exist on the Provisioner (see create network key command) and must have been deployed on the node prior to this command (either during provisioning or with an add network key command).


Once I change the device provisioned handler to deploy the netkey to the node again
case gecko_evt_mesh_prov_device_provisioned_id:
{
	struct gecko_msg_mesh_prov_device_provisioned_evt_t *prov_evt;
	prov_evt = (struct gecko_msg_mesh_prov_device_provisioned_evt_t *)&(evt->data);

	printf("gecko_evt_mesh_prov_device_provisioned_id\r\n");
	printf("Successfully provisioned %s to address %x\r\n", UUID_Cast_ASCII(UUID_Cast_To_UUID(prov_evt->uuid.data), true) , prov_evt->address);
	mesh_address = prov_evt->address;
	UUID_List_Clear();	// TODO Better way to remove device from the UUID list than clearing list and re-populating?
	LCD_write("provisioner - added", LCD_ROW_STATUS);
	current_mode = MODE_PROVISION_SUCCESS;

	// deploy netkey to node
	struct gecko_msg_mesh_prov_network_add_rsp_t *netkey_add_resp;
	netkey_add_resp = gecko_cmd_mesh_prov_network_add(mesh_address, nwkid);
	if (netkey_add_resp->result == 0) {
		printf("Successfully deployed netkey to %x\r\n", mesh_address);
		current_mode = MODE_PROVISION_NETKEY;
	} else {
		printf("Error deploying netkey: %x", netkey_add_resp->result);
	}

	break;
}

and add a config status handler to deploy the appkey once the response event from deploying the netkey occurs

case gecko_evt_mesh_prov_config_status_id:
{
	printf("gecko_evt_mesh_prov_config_status_id\r\n");

	if (current_mode == MODE_PROVISION_NETKEY) {
		// Beginning configuration - deploying appkey to node
		struct gecko_msg_mesh_prov_appkey_add_rsp_t *appkey_deploy_evt;
		appkey_deploy_evt = gecko_cmd_mesh_prov_appkey_add(mesh_address, nwkid, appid);
		if (appkey_deploy_evt->result == 0) {
			printf("Appkey deployed to %x\r\n", mesh_address);
			current_mode = MODE_PROVISION_APPKEY;
		} else {
			printf("Appkey deployment failed. error: %x\r\n", appkey_deploy_evt->result);
		}
	} else if (current_mode == MODE_PROVISION_APPKEY) {
		// TODO Bind appkey to model
		current_mode = MODE_PROVISION_BIND_MODEL;
	}else if (current_mode == MODE_PROVISION_BIND_MODEL) {
		// TODO Set model subscriptions
		current_mode = MODE_PROVISION_MODEL_SUBSCRIPTION;
	}else if (current_mode == MODE_PROVISION_MODEL_SUBSCRIPTION) {
		// TODO Set model publications
		current_mode = MODE_PROVISION_MODEL_PUBLICATION;
	}else if (current_mode == MODE_PROVISION_MODEL_PUBLICATION) {
		// TODO cleanup variables?
		current_mode = MODE_PROVISION_SUCCESS;
	}

	break;
}

the appkey can be deployed successfully.

Beginning to provision node.
gecko_evt_mesh_prov_device_provisioned_id
Successfully provisioned 000B579333652D7665447362616C6953 to address 2
Successfully deployed netkey to 2
gecko_evt_mesh_prov_config_status_id
Appkey deployed to 2
gecko_evt_mesh_prov_config_status_id

 

Cheers,

Rob

Highlighted
Posts: 38
Registered: ‎08-11-2017

Re: Mesh Configuration: Appkey Deployment Fail

A quick update on this - it looks like I was mistaken and the actual fix was hidden behind another change that I had made.

 

For development I had initialized the appkey and netkeys to 0, which after talking with @JaakkoV in a support ticket appears to be an invalid key value for the Silabs mesh stack. The functions to create the keys didn't raise an error and it wasn't until I attempted to send the appkey that an error was raised. When I set both the keys to a non-zero value the application was able to send the appkey as expected without the added function call described in my previous post to deploy the network key a second time.

 

Also, if anyone uses the code I've attached nkwid and appid are initialized in handle_gecko_event and will be overwritten every time an event occurs: you should either make them static or move them out of the function as global variables.

 

Regards,

Rob