1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define __BTSTACK_FILE__ "mesh_pts.c" 39 40 #include <stdint.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 45 #include "btstack.h" 46 #include "mesh_pts.h" 47 48 // general 49 static void show_usage(void); 50 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 51 static void mesh_pts_dump_mesh_options(void); 52 53 #define MESH_BLUEKITCHEN_MODEL_ID_TEST_SERVER 0x0000u 54 55 static btstack_packet_callback_registration_t hci_event_callback_registration; 56 static int provisioned; 57 58 static mesh_model_t mesh_vendor_model; 59 60 static mesh_model_t mesh_generic_on_off_server_model; 61 static mesh_generic_on_off_state_t mesh_generic_on_off_state; 62 63 // pts add-on 64 #define PTS_DEFAULT_TTL 10 65 66 static uint16_t pts_proxy_dst; 67 static int pts_type; 68 69 const char * pts_device_uuid_string = "001BDC0810210B0E0A0C000B0E0A0C00"; 70 71 static uint8_t prov_static_oob_data[16]; 72 static const char * prov_static_oob_string = "00000000000000000102030405060708"; 73 74 static uint8_t prov_public_key_data[64]; 75 static const char * prov_public_key_string = "F465E43FF23D3F1B9DC7DFC04DA8758184DBC966204796ECCF0D6CF5E16500CC0201D048BCBBD899EEEFC424164E33C201C2B010CA6B4D43A8A155CAD8ECB279"; 76 static uint8_t prov_private_key_data[32]; 77 static const char * prov_private_key_string = "529AA0670D72CD6497502ED473502B037E8803B5C60829A5A3CAA219505530BA"; 78 79 static mesh_transport_key_t pts_application_key; 80 81 // pin entry (pts) 82 static int ui_chars_for_pin; 83 static uint8_t ui_pin[17]; 84 static int ui_pin_offset; 85 86 87 static void mesh_provisioning_dump(const mesh_provisioning_data_t * data){ 88 mesh_network_key_t * key = data->network_key; 89 printf("UnicastAddr: 0x%02x\n", data->unicast_address); 90 printf("DevKey: "); printf_hexdump(data->device_key, 16); 91 printf("Flags: 0x%02x\n", data->flags); 92 printf("NetKey: "); printf_hexdump(key->net_key, 16); 93 printf("-- Derived from NetKey --\n"); 94 printf("NID: 0x%02x\n", key->nid); 95 printf("NetworkID: "); printf_hexdump(key->network_id, 8); 96 printf("BeaconKey: "); printf_hexdump(key->beacon_key, 16); 97 printf("EncryptionKey: "); printf_hexdump(key->encryption_key, 16); 98 printf("PrivacyKey: "); printf_hexdump(key->privacy_key, 16); 99 printf("IdentityKey: "); printf_hexdump(key->identity_key, 16); 100 } 101 102 103 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 104 UNUSED(channel); 105 UNUSED(size); 106 bd_addr_t addr; 107 int i; 108 109 switch (packet_type) { 110 case HCI_EVENT_PACKET: 111 switch (hci_event_packet_get_type(packet)) { 112 case BTSTACK_EVENT_STATE: 113 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 114 // dump bd_addr in pts format 115 gap_local_bd_addr(addr); 116 printf("Local addr: %s - ", bd_addr_to_str(addr)); 117 for (i=0;i<6;i++) { 118 printf("%02x", addr[i]); 119 } 120 printf("\n"); 121 // dump PTS MeshOptions.ini 122 mesh_pts_dump_mesh_options(); 123 break; 124 default: 125 break; 126 } 127 break; 128 } 129 } 130 131 static void mesh_provisioning_message_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 132 mesh_provisioning_data_t provisioning_data; 133 134 switch(packet[0]){ 135 case HCI_EVENT_MESH_META: 136 switch(packet[2]){ 137 case MESH_SUBEVENT_PB_TRANSPORT_LINK_OPEN: 138 printf("Provisioner link opened"); 139 break; 140 case MESH_SUBEVENT_PB_TRANSPORT_LINK_CLOSED: 141 printf("Provisioner link close"); 142 break; 143 case MESH_SUBEVENT_PB_PROV_ATTENTION_TIMER: 144 printf("Attention Timer: %u\n", packet[3]); 145 break; 146 case MESH_SUBEVENT_PB_PROV_INPUT_OOB_REQUEST: 147 printf("Enter passphrase: "); 148 fflush(stdout); 149 ui_chars_for_pin = 1; 150 ui_pin_offset = 0; 151 break; 152 case MESH_SUBEVENT_PB_PROV_COMPLETE: 153 printf("Provisioning complete\n"); 154 // dump provisioning data 155 provisioning_device_data_get(&provisioning_data); 156 mesh_provisioning_dump(&provisioning_data); 157 provisioned = 1; 158 break; 159 default: 160 break; 161 } 162 break; 163 default: 164 break; 165 } 166 } 167 168 static void mesh_state_update_message_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 169 if (packet_type != HCI_EVENT_PACKET) return; 170 171 switch(packet[0]){ 172 case HCI_EVENT_MESH_META: 173 switch(packet[2]){ 174 case MESH_SUBEVENT_STATE_UPDATE_BOOL: 175 printf("State update: model identifier 0x%08x, state identifier 0x%08x, reason %u, state %u\n", 176 mesh_subevent_state_update_bool_get_model_identifier(packet), 177 mesh_subevent_state_update_bool_get_state_identifier(packet), 178 mesh_subevent_state_update_bool_get_reason(packet), 179 mesh_subevent_state_update_bool_get_value(packet)); 180 break; 181 default: 182 break; 183 } 184 break; 185 default: 186 break; 187 } 188 } 189 190 // PTS 191 192 // helper network layer, temp 193 static uint8_t mesh_network_send(uint16_t netkey_index, uint8_t ctl, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dest, const uint8_t * transport_pdu_data, uint8_t transport_pdu_len){ 194 195 // "3.4.5.2: The output filter of the interface connected to advertising or GATT bearers shall drop all messages with TTL value set to 1." 196 // if (ttl <= 1) return 0; 197 198 // TODO: check transport_pdu_len depending on ctl 199 200 // lookup network by netkey_index 201 const mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 202 if (!network_key) return 0; 203 204 // allocate network_pdu 205 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 206 if (!network_pdu) return 0; 207 208 // setup network_pdu 209 mesh_network_setup_pdu(network_pdu, netkey_index, network_key->nid, ctl, ttl, seq, src, dest, transport_pdu_data, transport_pdu_len); 210 211 // send network_pdu 212 mesh_lower_transport_send_pdu((mesh_pdu_t *) network_pdu); 213 return 0; 214 } 215 216 static void printf_hex(const uint8_t * data, uint16_t len){ 217 while (len){ 218 printf("%02x", *data); 219 data++; 220 len--; 221 } 222 printf("\n"); 223 } 224 225 static void mesh_pts_dump_mesh_options(void){ 226 printf("\nMeshOptions.ini\n"); 227 228 printf("[mesh]\n"); 229 230 printf("{IVindex}\n"); 231 printf("%08x\n", mesh_get_iv_index()); 232 233 mesh_network_key_t * network_key = mesh_network_key_list_get(0); 234 if (network_key){ 235 printf("{NetKey}\n"); 236 printf_hex(network_key->net_key, 16); 237 } 238 239 mesh_transport_key_t * transport_key = mesh_transport_key_get(0); 240 if (transport_key){ 241 printf("{AppKey}\n"); 242 printf_hex(transport_key->key, 16); 243 } 244 245 mesh_transport_key_t * device_key = mesh_transport_key_get(MESH_DEVICE_KEY_INDEX); 246 if (device_key){ 247 printf("{DevKey}\n"); 248 printf_hex(device_key->key, 16); 249 } 250 printf("\n"); 251 } 252 253 static void mesh_unprovisioned_beacon_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 254 if (packet_type != MESH_BEACON_PACKET) return; 255 uint8_t device_uuid[16]; 256 uint16_t oob; 257 memcpy(device_uuid, &packet[1], 16); 258 oob = big_endian_read_16(packet, 17); 259 printf("received unprovisioned device beacon, oob data %x, device uuid: ", oob); 260 printf_hexdump(device_uuid, 16); 261 pb_adv_create_link(device_uuid); 262 } 263 264 static int scan_hex_byte(const char * byte_string){ 265 int upper_nibble = nibble_for_char(*byte_string++); 266 if (upper_nibble < 0) return -1; 267 int lower_nibble = nibble_for_char(*byte_string); 268 if (lower_nibble < 0) return -1; 269 return (upper_nibble << 4) | lower_nibble; 270 } 271 272 static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){ 273 int i; 274 for (i = 0; i < len; i++) { 275 int single_byte = scan_hex_byte(string); 276 if (single_byte < 0) return 0; 277 string += 2; 278 buffer[i] = (uint8_t)single_byte; 279 // don't check seperator after last byte 280 if (i == len - 1) { 281 return 1; 282 } 283 // optional seperator 284 char separator = *string; 285 if (separator == ':' && separator == '-' && separator == ' ') { 286 string++; 287 } 288 } 289 return 1; 290 } 291 292 static void btstack_print_hex(const uint8_t * data, uint16_t len, char separator){ 293 int i; 294 for (i=0;i<len;i++){ 295 printf("%02x", data[i]); 296 if (separator){ 297 printf("%c", separator); 298 } 299 } 300 printf("\n"); 301 } 302 303 static void load_pts_app_key(void){ 304 // PTS app key 305 btstack_parse_hex("3216D1509884B533248541792B877F98", 16, pts_application_key.key); 306 pts_application_key.aid = 0x38; 307 pts_application_key.internal_index = mesh_transport_key_get_free_index(); 308 mesh_transport_key_add(&pts_application_key); 309 printf("PTS Application Key (AID %02x): ", 0x38); 310 printf_hexdump(pts_application_key.key, 16); 311 } 312 313 static void send_pts_network_messsage(int type){ 314 uint8_t lower_transport_pdu_data[16]; 315 316 uint16_t src = 0x0028; 317 uint16_t dst = 0x0001; 318 uint32_t seq = 0x00; 319 uint8_t ttl = 0; 320 uint8_t ctl = 0; 321 322 switch (type){ 323 case 0: 324 ttl = 0; 325 dst = 0x001; 326 printf("unicast ttl=0\n"); 327 break; 328 case 1: 329 dst = 0x001; 330 ttl = PTS_DEFAULT_TTL; 331 printf("unicast ttl=10\n"); 332 break; 333 case 2: 334 dst = 0x001; 335 ttl = 0x7f; 336 printf("unicast ttl=0x7f\n"); 337 break; 338 case 3: 339 printf("virtual\n"); 340 break; 341 case 4: 342 printf("group\n"); 343 break; 344 case 5: 345 printf("all-proxies\n"); 346 break; 347 case 6: 348 printf("all-friends\n"); 349 break; 350 case 7: 351 printf("all-relays\n"); 352 break; 353 case 8: 354 printf("all-nodes\n"); 355 break; 356 default: 357 return; 358 } 359 int lower_transport_pdu_len = 16; 360 memset(lower_transport_pdu_data, 0x55, lower_transport_pdu_len); 361 mesh_network_send(0, ctl, ttl, seq, src, dst, lower_transport_pdu_data, lower_transport_pdu_len); 362 } 363 364 static void send_pts_unsegmented_access_messsage(void){ 365 uint8_t access_pdu_data[16]; 366 367 load_pts_app_key(); 368 369 uint16_t src = mesh_node_get_primary_element_address(); 370 uint16_t dest = 0x0001; 371 uint8_t ttl = PTS_DEFAULT_TTL; 372 373 int access_pdu_len = 1; 374 memset(access_pdu_data, 0x55, access_pdu_len); 375 uint16_t netkey_index = 0; 376 uint16_t appkey_index = 0; // MESH_DEVICE_KEY_INDEX; 377 378 // send as unsegmented access pdu 379 mesh_pdu_t * pdu = (mesh_pdu_t*) mesh_network_pdu_get(); 380 int status = mesh_upper_transport_setup_access_pdu(pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 381 if (status) return; 382 mesh_upper_transport_send_access_pdu(pdu); 383 } 384 385 static void send_pts_segmented_access_messsage_unicast(void){ 386 uint8_t access_pdu_data[20]; 387 388 load_pts_app_key(); 389 390 uint16_t src = mesh_node_get_primary_element_address(); 391 uint16_t dest = 0x0001; 392 uint8_t ttl = PTS_DEFAULT_TTL; 393 394 int access_pdu_len = 20; 395 memset(access_pdu_data, 0x55, access_pdu_len); 396 uint16_t netkey_index = 0; 397 uint16_t appkey_index = 0; // MESH_DEVICE_KEY_INDEX; 398 399 // send as segmented access pdu 400 mesh_pdu_t * pdu = (mesh_pdu_t *) mesh_transport_pdu_get(); 401 int status = mesh_upper_transport_setup_access_pdu(pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 402 if (status) return; 403 mesh_upper_transport_send_access_pdu(pdu); 404 } 405 406 static void send_pts_segmented_access_messsage_group(void){ 407 uint8_t access_pdu_data[20]; 408 409 load_pts_app_key(); 410 411 uint16_t src = mesh_node_get_primary_element_address(); 412 uint16_t dest = 0xd000; 413 uint8_t ttl = PTS_DEFAULT_TTL; 414 415 int access_pdu_len = 20; 416 memset(access_pdu_data, 0x55, access_pdu_len); 417 uint16_t netkey_index = 0; 418 uint16_t appkey_index = 0; 419 420 // send as segmented access pdu 421 mesh_pdu_t * pdu = (mesh_pdu_t *) mesh_transport_pdu_get(); 422 int status = mesh_upper_transport_setup_access_pdu(pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 423 if (status) return; 424 mesh_upper_transport_send_access_pdu(pdu); 425 } 426 427 static void send_pts_segmented_access_messsage_virtual(void){ 428 uint8_t access_pdu_data[20]; 429 430 load_pts_app_key(); 431 432 uint16_t src = mesh_node_get_primary_element_address(); 433 uint16_t dest = pts_proxy_dst; 434 uint8_t ttl = PTS_DEFAULT_TTL; 435 436 int access_pdu_len = 20; 437 memset(access_pdu_data, 0x55, access_pdu_len); 438 uint16_t netkey_index = 0; 439 uint16_t appkey_index = 0; 440 441 // send as segmented access pdu 442 mesh_transport_pdu_t * transport_pdu = mesh_transport_pdu_get(); 443 int status = mesh_upper_transport_setup_access_pdu((mesh_pdu_t*) transport_pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 444 if (status) return; 445 mesh_upper_transport_send_access_pdu((mesh_pdu_t*) transport_pdu); 446 } 447 448 static void show_usage(void){ 449 bd_addr_t iut_address; 450 gap_local_bd_addr(iut_address); 451 printf("\n--- Bluetooth Mesh Console at %s ---\n", bd_addr_to_str(iut_address)); 452 printf("0 - Send Network Message\n"); 453 printf("1 - Send Unsegmented Access Message\n"); 454 printf("2 - Send Segmented Access Message - Unicast\n"); 455 printf("3 - Send Segmented Access Message - Group D000\n"); 456 printf("4 - Send Segmented Access Message - Virtual 9779\n"); 457 printf("6 - Clear Replay Protection List\n"); 458 printf("7 - Load PTS App key\n"); 459 printf("8 - Delete provisioning data\n"); 460 printf("p - Enable Public Key OOB \n"); 461 printf("o - Enable Output OOB \n"); 462 printf("i - Input Output OOB \n"); 463 printf("s - Static Output OOB \n"); 464 printf("g - Generic ON/OFF Server Toggle Value\n"); 465 printf("\n"); 466 } 467 468 static void stdin_process(char cmd){ 469 if (ui_chars_for_pin){ 470 printf("%c", cmd); 471 fflush(stdout); 472 if (cmd == '\n'){ 473 printf("\nSending Pin '%s'\n", ui_pin); 474 provisioning_device_input_oob_complete_alphanumeric(1, ui_pin, ui_pin_offset); 475 ui_chars_for_pin = 0; 476 } else { 477 ui_pin[ui_pin_offset++] = cmd; 478 } 479 return; 480 } 481 switch (cmd){ 482 case '0': 483 send_pts_network_messsage(pts_type++); 484 break; 485 case '1': 486 send_pts_unsegmented_access_messsage(); 487 break; 488 case '2': 489 send_pts_segmented_access_messsage_unicast(); 490 break; 491 case '3': 492 send_pts_segmented_access_messsage_group(); 493 break; 494 case '4': 495 send_pts_segmented_access_messsage_virtual(); 496 break; 497 case '6': 498 printf("Clearing Replay Protection List\n"); 499 mesh_seq_auth_reset(); 500 break; 501 case '7': 502 load_pts_app_key(); 503 break; 504 case '8': 505 mesh_node_reset(); 506 printf("Mesh Node Reset!\n"); 507 mesh_proxy_start_advertising_unprovisioned_device(); 508 break; 509 case 'p': 510 printf("+ Public Key OOB Enabled\n"); 511 btstack_parse_hex(prov_public_key_string, 64, prov_public_key_data); 512 btstack_parse_hex(prov_private_key_string, 32, prov_private_key_data); 513 provisioning_device_set_public_key_oob(prov_public_key_data, prov_private_key_data); 514 break; 515 case 'o': 516 printf("+ Output OOB Enabled\n"); 517 provisioning_device_set_output_oob_actions(0x08, 0x08); 518 break; 519 case 'i': 520 printf("+ Input OOB Enabled\n"); 521 provisioning_device_set_input_oob_actions(0x08, 0x08); 522 break; 523 case 's': 524 printf("+ Static OOB Enabled\n"); 525 btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data); 526 provisioning_device_set_static_oob(16, prov_static_oob_data); 527 break; 528 case 'g': 529 printf("Generic ON/OFF Server Toggle Value\n"); 530 mesh_generic_on_off_server_set(&mesh_generic_on_off_server_model, 1-mesh_generic_on_off_server_get(&mesh_generic_on_off_server_model), 0, 0); 531 break; 532 case ' ': 533 show_usage(); 534 break; 535 default: 536 printf("Command: '%c' not implemented\n", cmd); 537 show_usage(); 538 break; 539 } 540 } 541 542 int btstack_main(void); 543 int btstack_main(void) 544 { 545 // console 546 btstack_stdin_setup(stdin_process); 547 548 // crypto 549 btstack_crypto_init(); 550 551 // l2cap 552 l2cap_init(); 553 554 // setup le device db 555 le_device_db_init(); 556 557 // setup ATT server 558 att_server_init(profile_data, NULL, NULL); 559 560 // 561 sm_init(); 562 563 564 // mesh 565 mesh_init(); 566 567 // setup connectable advertisments 568 bd_addr_t null_addr; 569 memset(null_addr, 0, 6); 570 uint8_t adv_type = 0; // AFV_IND 571 uint16_t adv_int_min = 0x0030; 572 uint16_t adv_int_max = 0x0030; 573 adv_bearer_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); 574 575 // Provisioning in device role 576 mesh_register_provisioning_device_packet_handler(&mesh_provisioning_message_handler); 577 578 // Loc - bottom - https://www.bluetooth.com/specifications/assigned-numbers/gatt-namespace-descriptors 579 mesh_node_set_element_location(mesh_node_get_primary_element(), 0x103); 580 581 // Setup Generic On/Off model 582 mesh_generic_on_off_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_GENERIC_ON_OFF_SERVER); 583 mesh_generic_on_off_server_model.operations = mesh_generic_on_off_server_get_operations(); 584 mesh_generic_on_off_server_model.model_data = (void *) &mesh_generic_on_off_state; 585 mesh_generic_on_off_server_register_packet_handler(&mesh_generic_on_off_server_model, &mesh_state_update_message_handler); 586 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_generic_on_off_server_model); 587 588 // Setup our custom model 589 mesh_vendor_model.model_identifier = mesh_model_get_model_identifier(BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, MESH_BLUEKITCHEN_MODEL_ID_TEST_SERVER); 590 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_vendor_model); 591 592 // Enable PROXY 593 mesh_foundation_gatt_proxy_set(1); 594 595 // register for HCI events 596 hci_event_callback_registration.callback = &packet_handler; 597 hci_add_event_handler(&hci_event_callback_registration); 598 599 #if defined(ENABLE_MESH_ADV_BEARER) 600 // setup scanning when supporting ADV Bearer 601 gap_set_scan_parameters(0, 0x300, 0x300); 602 gap_start_scan(); 603 #endif 604 605 // PTS add-on 606 607 #ifdef ENABLE_MESH_ADV_BEARER 608 // Register for Unprovisioned Device Beacons provisioner 609 beacon_register_for_unprovisioned_device_beacons(&mesh_unprovisioned_beacon_handler); 610 #endif 611 612 // Set PTS Device UUID 613 uint8_t pts_device_uuid[16]; 614 btstack_parse_hex(pts_device_uuid_string, 16, pts_device_uuid); 615 mesh_node_set_device_uuid(pts_device_uuid); 616 btstack_print_hex(pts_device_uuid, 16, 0); 617 618 // PTS Virtual Address Label UUID - without Config Model, PTS uses our device uuid 619 uint8_t label_uuid[16]; 620 btstack_parse_hex("001BDC0810210B0E0A0C000B0E0A0C00", 16, label_uuid); 621 mesh_virtual_address_t * virtual_addresss = mesh_virtual_address_register(label_uuid, 0x9779); 622 pts_proxy_dst = virtual_addresss->pseudo_dst; 623 624 // turn on! 625 hci_power_control(HCI_POWER_ON); 626 627 return 0; 628 } 629 /* EXAMPLE_END */ 630