main.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /* main.c - Application main entry point */
  2. /*
  3. * Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "esp_log.h"
  10. #include "nvs_flash.h"
  11. #include "esp_ble_mesh_defs.h"
  12. #include "esp_ble_mesh_common_api.h"
  13. #include "esp_ble_mesh_provisioning_api.h"
  14. #include "esp_ble_mesh_networking_api.h"
  15. #include "esp_ble_mesh_config_model_api.h"
  16. #include "esp_ble_mesh_generic_model_api.h"
  17. #include "ble_mesh_example_init.h"
  18. #define TAG "EXAMPLE"
  19. #define LED_OFF 0x0
  20. #define LED_ON 0x1
  21. #define CID_ESP 0x02E5
  22. #define PROV_OWN_ADDR 0x0001
  23. #define MSG_SEND_TTL 3
  24. #define MSG_SEND_REL false
  25. #define MSG_TIMEOUT 0
  26. #define MSG_ROLE ROLE_PROVISIONER
  27. #define COMP_DATA_PAGE_0 0x00
  28. #define APP_KEY_IDX 0x0000
  29. #define APP_KEY_OCTET 0x12
  30. static uint8_t dev_uuid[16];
  31. typedef struct {
  32. uint8_t uuid[16];
  33. uint16_t unicast;
  34. uint8_t elem_num;
  35. uint8_t onoff;
  36. } esp_ble_mesh_node_info_t;
  37. static esp_ble_mesh_node_info_t nodes[CONFIG_BLE_MESH_MAX_PROV_NODES] = {
  38. [0 ... (CONFIG_BLE_MESH_MAX_PROV_NODES - 1)] = {
  39. .unicast = ESP_BLE_MESH_ADDR_UNASSIGNED,
  40. .elem_num = 0,
  41. .onoff = LED_OFF,
  42. }
  43. };
  44. static struct esp_ble_mesh_key {
  45. uint16_t net_idx;
  46. uint16_t app_idx;
  47. uint8_t app_key[16];
  48. } prov_key;
  49. static esp_ble_mesh_client_t config_client;
  50. static esp_ble_mesh_client_t onoff_client;
  51. static esp_ble_mesh_cfg_srv_t config_server = {
  52. .relay = ESP_BLE_MESH_RELAY_DISABLED,
  53. .beacon = ESP_BLE_MESH_BEACON_ENABLED,
  54. #if defined(CONFIG_BLE_MESH_FRIEND)
  55. .friend_state = ESP_BLE_MESH_FRIEND_ENABLED,
  56. #else
  57. .friend_state = ESP_BLE_MESH_FRIEND_NOT_SUPPORTED,
  58. #endif
  59. #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
  60. .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_ENABLED,
  61. #else
  62. .gatt_proxy = ESP_BLE_MESH_GATT_PROXY_NOT_SUPPORTED,
  63. #endif
  64. .default_ttl = 7,
  65. /* 3 transmissions with 20ms interval */
  66. .net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20),
  67. .relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20),
  68. };
  69. static esp_ble_mesh_model_t root_models[] = {
  70. ESP_BLE_MESH_MODEL_CFG_SRV(&config_server),
  71. ESP_BLE_MESH_MODEL_CFG_CLI(&config_client),
  72. ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI(NULL, &onoff_client),
  73. };
  74. static esp_ble_mesh_elem_t elements[] = {
  75. ESP_BLE_MESH_ELEMENT(0, root_models, ESP_BLE_MESH_MODEL_NONE),
  76. };
  77. static esp_ble_mesh_comp_t composition = {
  78. .cid = CID_ESP,
  79. .elements = elements,
  80. .element_count = ARRAY_SIZE(elements),
  81. };
  82. static esp_ble_mesh_prov_t provision = {
  83. .prov_uuid = dev_uuid,
  84. .prov_unicast_addr = PROV_OWN_ADDR,
  85. .prov_start_address = 0x0005,
  86. .prov_attention = 0x00,
  87. .prov_algorithm = 0x00,
  88. .prov_pub_key_oob = 0x00,
  89. .prov_static_oob_val = NULL,
  90. .prov_static_oob_len = 0x00,
  91. .flags = 0x00,
  92. .iv_index = 0x00,
  93. };
  94. static esp_err_t example_ble_mesh_store_node_info(const uint8_t uuid[16], uint16_t unicast,
  95. uint8_t elem_num, uint8_t onoff_state)
  96. {
  97. int i;
  98. if (!uuid || !ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
  99. return ESP_ERR_INVALID_ARG;
  100. }
  101. /* Judge if the device has been provisioned before */
  102. for (i = 0; i < ARRAY_SIZE(nodes); i++) {
  103. if (!memcmp(nodes[i].uuid, uuid, 16)) {
  104. ESP_LOGW(TAG, "%s: reprovisioned device 0x%04x", __func__, unicast);
  105. nodes[i].unicast = unicast;
  106. nodes[i].elem_num = elem_num;
  107. nodes[i].onoff = onoff_state;
  108. return ESP_OK;
  109. }
  110. }
  111. for (i = 0; i < ARRAY_SIZE(nodes); i++) {
  112. if (nodes[i].unicast == ESP_BLE_MESH_ADDR_UNASSIGNED) {
  113. memcpy(nodes[i].uuid, uuid, 16);
  114. nodes[i].unicast = unicast;
  115. nodes[i].elem_num = elem_num;
  116. nodes[i].onoff = onoff_state;
  117. return ESP_OK;
  118. }
  119. }
  120. return ESP_FAIL;
  121. }
  122. static esp_ble_mesh_node_info_t *example_ble_mesh_get_node_info(uint16_t unicast)
  123. {
  124. int i;
  125. if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast)) {
  126. return NULL;
  127. }
  128. for (i = 0; i < ARRAY_SIZE(nodes); i++) {
  129. if (nodes[i].unicast <= unicast &&
  130. nodes[i].unicast + nodes[i].elem_num > unicast) {
  131. return &nodes[i];
  132. }
  133. }
  134. return NULL;
  135. }
  136. static esp_err_t example_ble_mesh_set_msg_common(esp_ble_mesh_client_common_param_t *common,
  137. esp_ble_mesh_node_info_t *node,
  138. esp_ble_mesh_model_t *model, uint32_t opcode)
  139. {
  140. if (!common || !node || !model) {
  141. return ESP_ERR_INVALID_ARG;
  142. }
  143. common->opcode = opcode;
  144. common->model = model;
  145. common->ctx.net_idx = prov_key.net_idx;
  146. common->ctx.app_idx = prov_key.app_idx;
  147. common->ctx.addr = node->unicast;
  148. common->ctx.send_ttl = MSG_SEND_TTL;
  149. common->ctx.send_rel = MSG_SEND_REL;
  150. common->msg_timeout = MSG_TIMEOUT;
  151. common->msg_role = MSG_ROLE;
  152. return ESP_OK;
  153. }
  154. static esp_err_t prov_complete(int node_idx, const esp_ble_mesh_octet16_t uuid,
  155. uint16_t unicast, uint8_t elem_num, uint16_t net_idx)
  156. {
  157. esp_ble_mesh_client_common_param_t common = {0};
  158. esp_ble_mesh_cfg_client_get_state_t get_state = {0};
  159. esp_ble_mesh_node_info_t *node = NULL;
  160. char name[11] = {0};
  161. int err;
  162. ESP_LOGI(TAG, "node index: 0x%x, unicast address: 0x%02x, element num: %d, netkey index: 0x%02x",
  163. node_idx, unicast, elem_num, net_idx);
  164. ESP_LOGI(TAG, "device uuid: %s", bt_hex(uuid, 16));
  165. sprintf(name, "%s%d", "NODE-", node_idx);
  166. err = esp_ble_mesh_provisioner_set_node_name(node_idx, name);
  167. if (err) {
  168. ESP_LOGE(TAG, "%s: Set node name failed", __func__);
  169. return ESP_FAIL;
  170. }
  171. err = example_ble_mesh_store_node_info(uuid, unicast, elem_num, LED_OFF);
  172. if (err) {
  173. ESP_LOGE(TAG, "%s: Store node info failed", __func__);
  174. return ESP_FAIL;
  175. }
  176. node = example_ble_mesh_get_node_info(unicast);
  177. if (!node) {
  178. ESP_LOGE(TAG, "%s: Get node info failed", __func__);
  179. return ESP_FAIL;
  180. }
  181. example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
  182. get_state.comp_data_get.page = COMP_DATA_PAGE_0;
  183. err = esp_ble_mesh_config_client_get_state(&common, &get_state);
  184. if (err) {
  185. ESP_LOGE(TAG, "%s: Send config comp data get failed", __func__);
  186. return ESP_FAIL;
  187. }
  188. return ESP_OK;
  189. }
  190. static void prov_link_open(esp_ble_mesh_prov_bearer_t bearer)
  191. {
  192. ESP_LOGI(TAG, "%s link open", bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT");
  193. }
  194. static void prov_link_close(esp_ble_mesh_prov_bearer_t bearer, uint8_t reason)
  195. {
  196. ESP_LOGI(TAG, "%s link close, reason 0x%02x",
  197. bearer == ESP_BLE_MESH_PROV_ADV ? "PB-ADV" : "PB-GATT", reason);
  198. }
  199. static void recv_unprov_adv_pkt(uint8_t dev_uuid[16], uint8_t addr[BD_ADDR_LEN],
  200. esp_ble_mesh_addr_type_t addr_type, uint16_t oob_info,
  201. uint8_t adv_type, esp_ble_mesh_prov_bearer_t bearer)
  202. {
  203. esp_ble_mesh_unprov_dev_add_t add_dev = {0};
  204. int err;
  205. /* Due to the API esp_ble_mesh_provisioner_set_dev_uuid_match, Provisioner will only
  206. * use this callback to report the devices, whose device UUID starts with 0xdd & 0xdd,
  207. * to the application layer.
  208. */
  209. ESP_LOGI(TAG, "address: %s, address type: %d, adv type: %d", bt_hex(addr, BD_ADDR_LEN), addr_type, adv_type);
  210. ESP_LOGI(TAG, "device uuid: %s", bt_hex(dev_uuid, 16));
  211. ESP_LOGI(TAG, "oob info: %d, bearer: %s", oob_info, (bearer & ESP_BLE_MESH_PROV_ADV) ? "PB-ADV" : "PB-GATT");
  212. memcpy(add_dev.addr, addr, BD_ADDR_LEN);
  213. add_dev.addr_type = (uint8_t)addr_type;
  214. memcpy(add_dev.uuid, dev_uuid, 16);
  215. add_dev.oob_info = oob_info;
  216. add_dev.bearer = (uint8_t)bearer;
  217. /* Note: If unprovisioned device adv packets have not been received, we should not add
  218. device with ADD_DEV_START_PROV_NOW_FLAG set. */
  219. err = esp_ble_mesh_provisioner_add_unprov_dev(&add_dev,
  220. ADD_DEV_RM_AFTER_PROV_FLAG | ADD_DEV_START_PROV_NOW_FLAG | ADD_DEV_FLUSHABLE_DEV_FLAG);
  221. if (err) {
  222. ESP_LOGE(TAG, "%s: Add unprovisioned device into queue failed", __func__);
  223. }
  224. return;
  225. }
  226. static void example_ble_mesh_provisioning_cb(esp_ble_mesh_prov_cb_event_t event,
  227. esp_ble_mesh_prov_cb_param_t *param)
  228. {
  229. switch (event) {
  230. case ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT:
  231. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_ENABLE_COMP_EVT, err_code %d", param->provisioner_prov_enable_comp.err_code);
  232. break;
  233. case ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT:
  234. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_PROV_DISABLE_COMP_EVT, err_code %d", param->provisioner_prov_disable_comp.err_code);
  235. break;
  236. case ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT:
  237. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT");
  238. recv_unprov_adv_pkt(param->provisioner_recv_unprov_adv_pkt.dev_uuid, param->provisioner_recv_unprov_adv_pkt.addr,
  239. param->provisioner_recv_unprov_adv_pkt.addr_type, param->provisioner_recv_unprov_adv_pkt.oob_info,
  240. param->provisioner_recv_unprov_adv_pkt.adv_type, param->provisioner_recv_unprov_adv_pkt.bearer);
  241. break;
  242. case ESP_BLE_MESH_PROVISIONER_PROV_LINK_OPEN_EVT:
  243. prov_link_open(param->provisioner_prov_link_open.bearer);
  244. break;
  245. case ESP_BLE_MESH_PROVISIONER_PROV_LINK_CLOSE_EVT:
  246. prov_link_close(param->provisioner_prov_link_close.bearer, param->provisioner_prov_link_close.reason);
  247. break;
  248. case ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT:
  249. prov_complete(param->provisioner_prov_complete.node_idx, param->provisioner_prov_complete.device_uuid,
  250. param->provisioner_prov_complete.unicast_addr, param->provisioner_prov_complete.element_num,
  251. param->provisioner_prov_complete.netkey_idx);
  252. break;
  253. case ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT:
  254. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_UNPROV_DEV_COMP_EVT, err_code %d", param->provisioner_add_unprov_dev_comp.err_code);
  255. break;
  256. case ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT:
  257. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_DEV_UUID_MATCH_COMP_EVT, err_code %d", param->provisioner_set_dev_uuid_match_comp.err_code);
  258. break;
  259. case ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT: {
  260. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_SET_NODE_NAME_COMP_EVT, err_code %d", param->provisioner_set_node_name_comp.err_code);
  261. if (param->provisioner_set_node_name_comp.err_code == ESP_OK) {
  262. const char *name = NULL;
  263. name = esp_ble_mesh_provisioner_get_node_name(param->provisioner_set_node_name_comp.node_index);
  264. if (!name) {
  265. ESP_LOGE(TAG, "Get node name failed");
  266. return;
  267. }
  268. ESP_LOGI(TAG, "Node %d name is: %s", param->provisioner_set_node_name_comp.node_index, name);
  269. }
  270. break;
  271. }
  272. case ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT: {
  273. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT, err_code %d", param->provisioner_add_app_key_comp.err_code);
  274. if (param->provisioner_add_app_key_comp.err_code == ESP_OK) {
  275. esp_err_t err = 0;
  276. prov_key.app_idx = param->provisioner_add_app_key_comp.app_idx;
  277. err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(PROV_OWN_ADDR, prov_key.app_idx,
  278. ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI, ESP_BLE_MESH_CID_NVAL);
  279. if (err != ESP_OK) {
  280. ESP_LOGE(TAG, "Provisioner bind local model appkey failed");
  281. return;
  282. }
  283. }
  284. break;
  285. }
  286. case ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT:
  287. ESP_LOGI(TAG, "ESP_BLE_MESH_PROVISIONER_BIND_APP_KEY_TO_MODEL_COMP_EVT, err_code %d", param->provisioner_bind_app_key_to_model_comp.err_code);
  288. break;
  289. default:
  290. break;
  291. }
  292. return;
  293. }
  294. static void example_ble_mesh_config_client_cb(esp_ble_mesh_cfg_client_cb_event_t event,
  295. esp_ble_mesh_cfg_client_cb_param_t *param)
  296. {
  297. esp_ble_mesh_client_common_param_t common = {0};
  298. esp_ble_mesh_node_info_t *node = NULL;
  299. uint32_t opcode;
  300. uint16_t addr;
  301. int err;
  302. opcode = param->params->opcode;
  303. addr = param->params->ctx.addr;
  304. ESP_LOGI(TAG, "%s, error_code = 0x%02x, event = 0x%02x, addr: 0x%04x, opcode: 0x%04x",
  305. __func__, param->error_code, event, param->params->ctx.addr, opcode);
  306. if (param->error_code) {
  307. ESP_LOGE(TAG, "Send config client message failed, opcode 0x%04x", opcode);
  308. return;
  309. }
  310. node = example_ble_mesh_get_node_info(addr);
  311. if (!node) {
  312. ESP_LOGE(TAG, "%s: Get node info failed", __func__);
  313. return;
  314. }
  315. switch (event) {
  316. case ESP_BLE_MESH_CFG_CLIENT_GET_STATE_EVT:
  317. switch (opcode) {
  318. case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
  319. ESP_LOGI(TAG, "composition data %s", bt_hex(param->status_cb.comp_data_status.composition_data->data,
  320. param->status_cb.comp_data_status.composition_data->len));
  321. esp_ble_mesh_cfg_client_set_state_t set_state = {0};
  322. example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
  323. set_state.app_key_add.net_idx = prov_key.net_idx;
  324. set_state.app_key_add.app_idx = prov_key.app_idx;
  325. memcpy(set_state.app_key_add.app_key, prov_key.app_key, 16);
  326. err = esp_ble_mesh_config_client_set_state(&common, &set_state);
  327. if (err) {
  328. ESP_LOGE(TAG, "%s: Config AppKey Add failed", __func__);
  329. return;
  330. }
  331. break;
  332. }
  333. default:
  334. break;
  335. }
  336. break;
  337. case ESP_BLE_MESH_CFG_CLIENT_SET_STATE_EVT:
  338. switch (opcode) {
  339. case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
  340. esp_ble_mesh_cfg_client_set_state_t set_state = {0};
  341. example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
  342. set_state.model_app_bind.element_addr = node->unicast;
  343. set_state.model_app_bind.model_app_idx = prov_key.app_idx;
  344. set_state.model_app_bind.model_id = ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV;
  345. set_state.model_app_bind.company_id = ESP_BLE_MESH_CID_NVAL;
  346. err = esp_ble_mesh_config_client_set_state(&common, &set_state);
  347. if (err) {
  348. ESP_LOGE(TAG, "%s: Config Model App Bind failed", __func__);
  349. return;
  350. }
  351. break;
  352. }
  353. case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
  354. esp_ble_mesh_generic_client_get_state_t get_state = {0};
  355. example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET);
  356. err = esp_ble_mesh_generic_client_get_state(&common, &get_state);
  357. if (err) {
  358. ESP_LOGE(TAG, "%s: Generic OnOff Get failed", __func__);
  359. return;
  360. }
  361. break;
  362. }
  363. default:
  364. break;
  365. }
  366. break;
  367. case ESP_BLE_MESH_CFG_CLIENT_PUBLISH_EVT:
  368. switch (opcode) {
  369. case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_STATUS:
  370. ESP_LOG_BUFFER_HEX("composition data %s", param->status_cb.comp_data_status.composition_data->data,
  371. param->status_cb.comp_data_status.composition_data->len);
  372. break;
  373. case ESP_BLE_MESH_MODEL_OP_APP_KEY_STATUS:
  374. break;
  375. default:
  376. break;
  377. }
  378. break;
  379. case ESP_BLE_MESH_CFG_CLIENT_TIMEOUT_EVT:
  380. switch (opcode) {
  381. case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET: {
  382. esp_ble_mesh_cfg_client_get_state_t get_state = {0};
  383. example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET);
  384. get_state.comp_data_get.page = COMP_DATA_PAGE_0;
  385. err = esp_ble_mesh_config_client_get_state(&common, &get_state);
  386. if (err) {
  387. ESP_LOGE(TAG, "%s: Config Composition Data Get failed", __func__);
  388. return;
  389. }
  390. break;
  391. }
  392. case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD: {
  393. esp_ble_mesh_cfg_client_set_state_t set_state = {0};
  394. example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD);
  395. set_state.app_key_add.net_idx = prov_key.net_idx;
  396. set_state.app_key_add.app_idx = prov_key.app_idx;
  397. memcpy(set_state.app_key_add.app_key, prov_key.app_key, 16);
  398. err = esp_ble_mesh_config_client_set_state(&common, &set_state);
  399. if (err) {
  400. ESP_LOGE(TAG, "%s: Config AppKey Add failed", __func__);
  401. return;
  402. }
  403. break;
  404. }
  405. case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND: {
  406. esp_ble_mesh_cfg_client_set_state_t set_state = {0};
  407. example_ble_mesh_set_msg_common(&common, node, config_client.model, ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND);
  408. set_state.model_app_bind.element_addr = node->unicast;
  409. set_state.model_app_bind.model_app_idx = prov_key.app_idx;
  410. set_state.model_app_bind.model_id = ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_SRV;
  411. set_state.model_app_bind.company_id = ESP_BLE_MESH_CID_NVAL;
  412. err = esp_ble_mesh_config_client_set_state(&common, &set_state);
  413. if (err) {
  414. ESP_LOGE(TAG, "%s: Config Model App Bind failed", __func__);
  415. return;
  416. }
  417. break;
  418. }
  419. default:
  420. break;
  421. }
  422. break;
  423. default:
  424. ESP_LOGE(TAG, "Not a config client status message event");
  425. break;
  426. }
  427. }
  428. static void example_ble_mesh_generic_client_cb(esp_ble_mesh_generic_client_cb_event_t event,
  429. esp_ble_mesh_generic_client_cb_param_t *param)
  430. {
  431. esp_ble_mesh_client_common_param_t common = {0};
  432. esp_ble_mesh_node_info_t *node = NULL;
  433. uint32_t opcode;
  434. uint16_t addr;
  435. int err;
  436. opcode = param->params->opcode;
  437. addr = param->params->ctx.addr;
  438. ESP_LOGI(TAG, "%s, error_code = 0x%02x, event = 0x%02x, addr: 0x%04x, opcode: 0x%04x",
  439. __func__, param->error_code, event, param->params->ctx.addr, opcode);
  440. if (param->error_code) {
  441. ESP_LOGE(TAG, "Send generic client message failed, opcode 0x%04x", opcode);
  442. return;
  443. }
  444. node = example_ble_mesh_get_node_info(addr);
  445. if (!node) {
  446. ESP_LOGE(TAG, "%s: Get node info failed", __func__);
  447. return;
  448. }
  449. switch (event) {
  450. case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT:
  451. switch (opcode) {
  452. case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: {
  453. esp_ble_mesh_generic_client_set_state_t set_state = {0};
  454. node->onoff = param->status_cb.onoff_status.present_onoff;
  455. ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET onoff: 0x%02x", node->onoff);
  456. /* After Generic OnOff Status for Generic OnOff Get is received, Generic OnOff Set will be sent */
  457. example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);
  458. set_state.onoff_set.op_en = false;
  459. set_state.onoff_set.onoff = !node->onoff;
  460. set_state.onoff_set.tid = 0;
  461. err = esp_ble_mesh_generic_client_set_state(&common, &set_state);
  462. if (err) {
  463. ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);
  464. return;
  465. }
  466. break;
  467. }
  468. default:
  469. break;
  470. }
  471. break;
  472. case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT:
  473. switch (opcode) {
  474. case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET:
  475. node->onoff = param->status_cb.onoff_status.present_onoff;
  476. ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET onoff: 0x%02x", node->onoff);
  477. break;
  478. default:
  479. break;
  480. }
  481. break;
  482. case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT:
  483. break;
  484. case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT:
  485. /* If failed to receive the responses, these messages will be resend */
  486. switch (opcode) {
  487. case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET: {
  488. esp_ble_mesh_generic_client_get_state_t get_state = {0};
  489. example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET);
  490. err = esp_ble_mesh_generic_client_get_state(&common, &get_state);
  491. if (err) {
  492. ESP_LOGE(TAG, "%s: Generic OnOff Get failed", __func__);
  493. return;
  494. }
  495. break;
  496. }
  497. case ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET: {
  498. esp_ble_mesh_generic_client_set_state_t set_state = {0};
  499. node->onoff = param->status_cb.onoff_status.present_onoff;
  500. ESP_LOGI(TAG, "ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET onoff: 0x%02x", node->onoff);
  501. example_ble_mesh_set_msg_common(&common, node, onoff_client.model, ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET);
  502. set_state.onoff_set.op_en = false;
  503. set_state.onoff_set.onoff = !node->onoff;
  504. set_state.onoff_set.tid = 0;
  505. err = esp_ble_mesh_generic_client_set_state(&common, &set_state);
  506. if (err) {
  507. ESP_LOGE(TAG, "%s: Generic OnOff Set failed", __func__);
  508. return;
  509. }
  510. break;
  511. }
  512. default:
  513. break;
  514. }
  515. break;
  516. default:
  517. ESP_LOGE(TAG, "Not a generic client status message event");
  518. break;
  519. }
  520. }
  521. static esp_err_t ble_mesh_init(void)
  522. {
  523. uint8_t match[2] = {0xdd, 0xdd};
  524. esp_err_t err = ESP_OK;
  525. prov_key.net_idx = ESP_BLE_MESH_KEY_PRIMARY;
  526. prov_key.app_idx = APP_KEY_IDX;
  527. memset(prov_key.app_key, APP_KEY_OCTET, sizeof(prov_key.app_key));
  528. esp_ble_mesh_register_prov_callback(example_ble_mesh_provisioning_cb);
  529. esp_ble_mesh_register_config_client_callback(example_ble_mesh_config_client_cb);
  530. esp_ble_mesh_register_generic_client_callback(example_ble_mesh_generic_client_cb);
  531. err = esp_ble_mesh_init(&provision, &composition);
  532. if (err != ESP_OK) {
  533. ESP_LOGE(TAG, "Failed to initialize mesh stack (err %d)", err);
  534. return err;
  535. }
  536. err = esp_ble_mesh_provisioner_set_dev_uuid_match(match, sizeof(match), 0x0, false);
  537. if (err != ESP_OK) {
  538. ESP_LOGE(TAG, "Failed to set matching device uuid (err %d)", err);
  539. return err;
  540. }
  541. err = esp_ble_mesh_provisioner_prov_enable(ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT);
  542. if (err != ESP_OK) {
  543. ESP_LOGE(TAG, "Failed to enable mesh provisioner (err %d)", err);
  544. return err;
  545. }
  546. err = esp_ble_mesh_provisioner_add_local_app_key(prov_key.app_key, prov_key.net_idx, prov_key.app_idx);
  547. if (err != ESP_OK) {
  548. ESP_LOGE(TAG, "Failed to add local AppKey (err %d)", err);
  549. return err;
  550. }
  551. ESP_LOGI(TAG, "BLE Mesh Provisioner initialized");
  552. return err;
  553. }
  554. void app_main(void)
  555. {
  556. esp_err_t err;
  557. ESP_LOGI(TAG, "Initializing...");
  558. err = nvs_flash_init();
  559. if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
  560. ESP_ERROR_CHECK(nvs_flash_erase());
  561. err = nvs_flash_init();
  562. }
  563. ESP_ERROR_CHECK(err);
  564. err = bluetooth_init();
  565. if (err) {
  566. ESP_LOGE(TAG, "esp32_bluetooth_init failed (err %d)", err);
  567. return;
  568. }
  569. ble_mesh_get_dev_uuid(dev_uuid);
  570. /* Initialize the Bluetooth Mesh Subsystem */
  571. err = ble_mesh_init();
  572. if (err) {
  573. ESP_LOGE(TAG, "Bluetooth mesh init failed (err %d)", err);
  574. }
  575. }