app_mesh.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. #include "esp_log.h"
  20. #include "nvs_flash.h"
  21. #include "freertos/FreeRTOSConfig.h"
  22. /* BLE */
  23. #include "esp_nimble_hci.h"
  24. #include "nimble/nimble_port.h"
  25. #include "nimble/nimble_port_freertos.h"
  26. #include "host/ble_hs.h"
  27. #include "host/util/util.h"
  28. #include "console/console.h"
  29. #include "services/gap/ble_svc_gap.h"
  30. #include "services/gatt/ble_svc_gatt.h"
  31. #include "mesh/mesh.h"
  32. static const char *tag = "NimBLE_MESH";
  33. void ble_store_config_init(void);
  34. #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
  35. /* Company ID */
  36. #define CID_VENDOR 0x05C3
  37. #define STANDARD_TEST_ID 0x00
  38. #define TEST_ID 0x01
  39. static int recent_test_id = STANDARD_TEST_ID;
  40. #define FAULT_ARR_SIZE 2
  41. static bool has_reg_fault = true;
  42. static struct bt_mesh_cfg_srv cfg_srv = {
  43. .relay = BT_MESH_RELAY_DISABLED,
  44. .beacon = BT_MESH_BEACON_ENABLED,
  45. #if MYNEWT_VAL(BLE_MESH_FRIEND)
  46. .frnd = BT_MESH_FRIEND_ENABLED,
  47. #endif
  48. #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
  49. .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
  50. #else
  51. .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
  52. #endif
  53. .default_ttl = 7,
  54. /* 3 transmissions with 20ms interval */
  55. .net_transmit = BT_MESH_TRANSMIT(2, 20),
  56. .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
  57. };
  58. static int
  59. fault_get_cur(struct bt_mesh_model *model,
  60. uint8_t *test_id,
  61. uint16_t *company_id,
  62. uint8_t *faults,
  63. uint8_t *fault_count)
  64. {
  65. uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE - 1] = 0xff };
  66. ESP_LOGI(tag, "fault_get_cur() has_reg_fault %u\n", has_reg_fault);
  67. *test_id = recent_test_id;
  68. *company_id = CID_VENDOR;
  69. *fault_count = min(*fault_count, sizeof(reg_faults));
  70. memcpy(faults, reg_faults, *fault_count);
  71. return 0;
  72. }
  73. static int
  74. fault_get_reg(struct bt_mesh_model *model,
  75. uint16_t company_id,
  76. uint8_t *test_id,
  77. uint8_t *faults,
  78. uint8_t *fault_count)
  79. {
  80. if (company_id != CID_VENDOR) {
  81. return -BLE_HS_EINVAL;
  82. }
  83. ESP_LOGI(tag, "fault_get_reg() has_reg_fault %u\n", has_reg_fault);
  84. *test_id = recent_test_id;
  85. if (has_reg_fault) {
  86. uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE - 1] = 0xff };
  87. *fault_count = min(*fault_count, sizeof(reg_faults));
  88. memcpy(faults, reg_faults, *fault_count);
  89. } else {
  90. *fault_count = 0;
  91. }
  92. return 0;
  93. }
  94. static int
  95. fault_clear(struct bt_mesh_model *model, uint16_t company_id)
  96. {
  97. if (company_id != CID_VENDOR) {
  98. return -BLE_HS_EINVAL;
  99. }
  100. has_reg_fault = false;
  101. return 0;
  102. }
  103. static int
  104. fault_test(struct bt_mesh_model *model, uint8_t test_id, uint16_t company_id)
  105. {
  106. if (company_id != CID_VENDOR) {
  107. return -BLE_HS_EINVAL;
  108. }
  109. if (test_id != STANDARD_TEST_ID && test_id != TEST_ID) {
  110. return -BLE_HS_EINVAL;
  111. }
  112. recent_test_id = test_id;
  113. has_reg_fault = true;
  114. bt_mesh_fault_update(bt_mesh_model_elem(model));
  115. return 0;
  116. }
  117. static const struct bt_mesh_health_srv_cb health_srv_cb = {
  118. .fault_get_cur = &fault_get_cur,
  119. .fault_get_reg = &fault_get_reg,
  120. .fault_clear = &fault_clear,
  121. .fault_test = &fault_test,
  122. };
  123. static struct bt_mesh_health_srv health_srv = {
  124. .cb = &health_srv_cb,
  125. };
  126. static struct bt_mesh_model_pub health_pub;
  127. static void
  128. health_pub_init(void)
  129. {
  130. health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(0);
  131. }
  132. static struct bt_mesh_model_pub gen_level_pub;
  133. static struct bt_mesh_model_pub gen_onoff_pub;
  134. static uint8_t gen_on_off_state;
  135. static int16_t gen_level_state;
  136. static void gen_onoff_status(struct bt_mesh_model *model,
  137. struct bt_mesh_msg_ctx *ctx)
  138. {
  139. struct os_mbuf *msg = NET_BUF_SIMPLE(3);
  140. uint8_t *status;
  141. ESP_LOGI(tag, "#mesh-onoff STATUS\n");
  142. bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x04));
  143. status = net_buf_simple_add(msg, 1);
  144. *status = gen_on_off_state;
  145. if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
  146. ESP_LOGI(tag, "#mesh-onoff STATUS: send status failed\n");
  147. }
  148. os_mbuf_free_chain(msg);
  149. }
  150. static void gen_onoff_get(struct bt_mesh_model *model,
  151. struct bt_mesh_msg_ctx *ctx,
  152. struct os_mbuf *buf)
  153. {
  154. ESP_LOGI(tag, "#mesh-onoff GET\n");
  155. gen_onoff_status(model, ctx);
  156. }
  157. static void gen_onoff_set(struct bt_mesh_model *model,
  158. struct bt_mesh_msg_ctx *ctx,
  159. struct os_mbuf *buf)
  160. {
  161. ESP_LOGI(tag, "#mesh-onoff SET\n");
  162. gen_on_off_state = buf->om_data[0];
  163. gen_onoff_status(model, ctx);
  164. }
  165. static void gen_onoff_set_unack(struct bt_mesh_model *model,
  166. struct bt_mesh_msg_ctx *ctx,
  167. struct os_mbuf *buf)
  168. {
  169. ESP_LOGI(tag, "#mesh-onoff SET-UNACK\n");
  170. gen_on_off_state = buf->om_data[0];
  171. }
  172. static const struct bt_mesh_model_op gen_onoff_op[] = {
  173. { BT_MESH_MODEL_OP_2(0x82, 0x01), 0, gen_onoff_get },
  174. { BT_MESH_MODEL_OP_2(0x82, 0x02), 2, gen_onoff_set },
  175. { BT_MESH_MODEL_OP_2(0x82, 0x03), 2, gen_onoff_set_unack },
  176. BT_MESH_MODEL_OP_END,
  177. };
  178. static void gen_level_status(struct bt_mesh_model *model,
  179. struct bt_mesh_msg_ctx *ctx)
  180. {
  181. struct os_mbuf *msg = NET_BUF_SIMPLE(4);
  182. ESP_LOGI(tag, "#mesh-level STATUS\n");
  183. bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x08));
  184. net_buf_simple_add_le16(msg, gen_level_state);
  185. if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
  186. ESP_LOGI(tag, "#mesh-level STATUS: send status failed\n");
  187. }
  188. os_mbuf_free_chain(msg);
  189. }
  190. static void gen_level_get(struct bt_mesh_model *model,
  191. struct bt_mesh_msg_ctx *ctx,
  192. struct os_mbuf *buf)
  193. {
  194. ESP_LOGI(tag, "#mesh-level GET\n");
  195. gen_level_status(model, ctx);
  196. }
  197. static void gen_level_set(struct bt_mesh_model *model,
  198. struct bt_mesh_msg_ctx *ctx,
  199. struct os_mbuf *buf)
  200. {
  201. int16_t level;
  202. level = (int16_t) net_buf_simple_pull_le16(buf);
  203. ESP_LOGI(tag, "#mesh-level SET: level=%d\n", level);
  204. gen_level_status(model, ctx);
  205. gen_level_state = level;
  206. ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state);
  207. }
  208. static void gen_level_set_unack(struct bt_mesh_model *model,
  209. struct bt_mesh_msg_ctx *ctx,
  210. struct os_mbuf *buf)
  211. {
  212. int16_t level;
  213. level = (int16_t) net_buf_simple_pull_le16(buf);
  214. ESP_LOGI(tag, "#mesh-level SET-UNACK: level=%d\n", level);
  215. gen_level_state = level;
  216. ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state);
  217. }
  218. static void gen_delta_set(struct bt_mesh_model *model,
  219. struct bt_mesh_msg_ctx *ctx,
  220. struct os_mbuf *buf)
  221. {
  222. int16_t delta_level;
  223. delta_level = (int16_t) net_buf_simple_pull_le16(buf);
  224. ESP_LOGI(tag, "#mesh-level DELTA-SET: delta_level=%d\n", delta_level);
  225. gen_level_status(model, ctx);
  226. gen_level_state += delta_level;
  227. ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state);
  228. }
  229. static void gen_delta_set_unack(struct bt_mesh_model *model,
  230. struct bt_mesh_msg_ctx *ctx,
  231. struct os_mbuf *buf)
  232. {
  233. int16_t delta_level;
  234. delta_level = (int16_t) net_buf_simple_pull_le16(buf);
  235. ESP_LOGI(tag, "#mesh-level DELTA-SET: delta_level=%d\n", delta_level);
  236. gen_level_state += delta_level;
  237. ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state);
  238. }
  239. static void gen_move_set(struct bt_mesh_model *model,
  240. struct bt_mesh_msg_ctx *ctx,
  241. struct os_mbuf *buf)
  242. {
  243. }
  244. static void gen_move_set_unack(struct bt_mesh_model *model,
  245. struct bt_mesh_msg_ctx *ctx,
  246. struct os_mbuf *buf)
  247. {
  248. }
  249. static const struct bt_mesh_model_op gen_level_op[] = {
  250. { BT_MESH_MODEL_OP_2(0x82, 0x05), 0, gen_level_get },
  251. { BT_MESH_MODEL_OP_2(0x82, 0x06), 3, gen_level_set },
  252. { BT_MESH_MODEL_OP_2(0x82, 0x07), 3, gen_level_set_unack },
  253. { BT_MESH_MODEL_OP_2(0x82, 0x09), 5, gen_delta_set },
  254. { BT_MESH_MODEL_OP_2(0x82, 0x0a), 5, gen_delta_set_unack },
  255. { BT_MESH_MODEL_OP_2(0x82, 0x0b), 3, gen_move_set },
  256. { BT_MESH_MODEL_OP_2(0x82, 0x0c), 3, gen_move_set_unack },
  257. BT_MESH_MODEL_OP_END,
  258. };
  259. static struct bt_mesh_model root_models[] = {
  260. BT_MESH_MODEL_CFG_SRV(&cfg_srv),
  261. BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
  262. BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op,
  263. &gen_onoff_pub, NULL),
  264. BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, gen_level_op,
  265. &gen_level_pub, NULL),
  266. };
  267. static struct bt_mesh_model_pub vnd_model_pub;
  268. static void vnd_model_recv(struct bt_mesh_model *model,
  269. struct bt_mesh_msg_ctx *ctx,
  270. struct os_mbuf *buf)
  271. {
  272. struct os_mbuf *msg = NET_BUF_SIMPLE(3);
  273. console_printf("#vendor-model-recv\n");
  274. console_printf("data:%s len:%d\n", bt_hex(buf->om_data, buf->om_len),
  275. buf->om_len);
  276. bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_3(0x01, CID_VENDOR));
  277. os_mbuf_append(msg, buf->om_data, buf->om_len);
  278. if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
  279. console_printf("#vendor-model-recv: send rsp failed\n");
  280. }
  281. os_mbuf_free_chain(msg);
  282. }
  283. static const struct bt_mesh_model_op vnd_model_op[] = {
  284. { BT_MESH_MODEL_OP_3(0x01, CID_VENDOR), 0, vnd_model_recv },
  285. BT_MESH_MODEL_OP_END,
  286. };
  287. static struct bt_mesh_model vnd_models[] = {
  288. BT_MESH_MODEL_VND(CID_VENDOR, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, vnd_model_op,
  289. &vnd_model_pub, NULL),
  290. };
  291. static struct bt_mesh_elem elements[] = {
  292. BT_MESH_ELEM(0, root_models, vnd_models),
  293. };
  294. static const struct bt_mesh_comp comp = {
  295. .cid = CID_VENDOR,
  296. .elem = elements,
  297. .elem_count = ARRAY_SIZE(elements),
  298. };
  299. static int output_number(bt_mesh_output_action_t action, uint32_t number)
  300. {
  301. ESP_LOGI(tag, "OOB Number: %u\n", number);
  302. return 0;
  303. }
  304. static void prov_complete(u16_t net_idx, u16_t addr)
  305. {
  306. ESP_LOGI(tag, "Local node provisioned, primary address 0x%04x\n", addr);
  307. }
  308. static const uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
  309. static const struct bt_mesh_prov prov = {
  310. .uuid = dev_uuid,
  311. .output_size = 4,
  312. .output_actions = BT_MESH_DISPLAY_NUMBER | BT_MESH_BEEP | BT_MESH_VIBRATE | BT_MESH_BLINK,
  313. .output_number = output_number,
  314. .complete = prov_complete,
  315. };
  316. static void
  317. blemesh_on_reset(int reason)
  318. {
  319. BLE_HS_LOG(ERROR, "Resetting state; reason=%d\n", reason);
  320. }
  321. static void
  322. blemesh_on_sync(void)
  323. {
  324. int err;
  325. ble_addr_t addr;
  326. ESP_LOGI(tag, "Bluetooth initialized\n");
  327. /* Use NRPA */
  328. err = ble_hs_id_gen_rnd(1, &addr);
  329. assert(err == 0);
  330. err = ble_hs_id_set_rnd(addr.val);
  331. assert(err == 0);
  332. err = bt_mesh_init(addr.type, &prov, &comp);
  333. if (err) {
  334. ESP_LOGI(tag, "Initializing mesh failed (err %d)\n", err);
  335. return;
  336. }
  337. ESP_LOGI(tag, "Mesh initialized\n");
  338. if (IS_ENABLED(CONFIG_SETTINGS)) {
  339. settings_load();
  340. }
  341. if (bt_mesh_is_provisioned()) {
  342. ESP_LOGI(tag, "Mesh network restored from flash\n");
  343. }
  344. }
  345. void blemesh_host_task(void *param)
  346. {
  347. ble_hs_cfg.reset_cb = blemesh_on_reset;
  348. ble_hs_cfg.sync_cb = blemesh_on_sync;
  349. ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
  350. health_pub_init();
  351. nimble_port_run();
  352. nimble_port_freertos_deinit();
  353. }
  354. void app_main(void)
  355. {
  356. /* Initialize NVS — it is used to store PHY calibration data */
  357. esp_err_t ret = nvs_flash_init();
  358. if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  359. ESP_ERROR_CHECK(nvs_flash_erase());
  360. ret = nvs_flash_init();
  361. }
  362. ESP_ERROR_CHECK(ret);
  363. ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
  364. nimble_port_init();
  365. ble_svc_gap_init();
  366. ble_svc_gatt_init();
  367. bt_mesh_register_gatt();
  368. /* XXX Need to have template for store */
  369. ble_store_config_init();
  370. nimble_port_freertos_init(blemesh_host_task);
  371. }