ble.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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 <assert.h>
  20. #include "mesh/mesh.h"
  21. #include "console/console.h"
  22. /* BLE */
  23. #include "nimble/nimble_port.h"
  24. #include "nimble/ble.h"
  25. #include "host/ble_hs.h"
  26. #include "services/gap/ble_svc_gap.h"
  27. #include "mesh/glue.h"
  28. #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
  29. /* Company ID */
  30. #define CID_VENDOR 0x05C3
  31. #define STANDARD_TEST_ID 0x00
  32. #define TEST_ID 0x01
  33. static int recent_test_id = STANDARD_TEST_ID;
  34. #define FAULT_ARR_SIZE 2
  35. static bool has_reg_fault = true;
  36. static int
  37. fault_get_cur(struct bt_mesh_model *model,
  38. uint8_t *test_id,
  39. uint16_t *company_id,
  40. uint8_t *faults,
  41. uint8_t *fault_count)
  42. {
  43. uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE-1] = 0xff };
  44. console_printf("fault_get_cur() has_reg_fault %u\n", has_reg_fault);
  45. *test_id = recent_test_id;
  46. *company_id = CID_VENDOR;
  47. *fault_count = min(*fault_count, sizeof(reg_faults));
  48. memcpy(faults, reg_faults, *fault_count);
  49. return 0;
  50. }
  51. static int
  52. fault_get_reg(struct bt_mesh_model *model,
  53. uint16_t company_id,
  54. uint8_t *test_id,
  55. uint8_t *faults,
  56. uint8_t *fault_count)
  57. {
  58. if (company_id != CID_VENDOR) {
  59. return -BLE_HS_EINVAL;
  60. }
  61. console_printf("fault_get_reg() has_reg_fault %u\n", has_reg_fault);
  62. *test_id = recent_test_id;
  63. if (has_reg_fault) {
  64. uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE-1] = 0xff };
  65. *fault_count = min(*fault_count, sizeof(reg_faults));
  66. memcpy(faults, reg_faults, *fault_count);
  67. } else {
  68. *fault_count = 0;
  69. }
  70. return 0;
  71. }
  72. static int
  73. fault_clear(struct bt_mesh_model *model, uint16_t company_id)
  74. {
  75. if (company_id != CID_VENDOR) {
  76. return -BLE_HS_EINVAL;
  77. }
  78. has_reg_fault = false;
  79. return 0;
  80. }
  81. static int
  82. fault_test(struct bt_mesh_model *model, uint8_t test_id, uint16_t company_id)
  83. {
  84. if (company_id != CID_VENDOR) {
  85. return -BLE_HS_EINVAL;
  86. }
  87. if (test_id != STANDARD_TEST_ID && test_id != TEST_ID) {
  88. return -BLE_HS_EINVAL;
  89. }
  90. recent_test_id = test_id;
  91. has_reg_fault = true;
  92. bt_mesh_fault_update(bt_mesh_model_elem(model));
  93. return 0;
  94. }
  95. static const struct bt_mesh_health_srv_cb health_srv_cb = {
  96. .fault_get_cur = &fault_get_cur,
  97. .fault_get_reg = &fault_get_reg,
  98. .fault_clear = &fault_clear,
  99. .fault_test = &fault_test,
  100. };
  101. static struct bt_mesh_health_srv health_srv = {
  102. .cb = &health_srv_cb,
  103. };
  104. static struct bt_mesh_model_pub health_pub;
  105. static void
  106. health_pub_init(void)
  107. {
  108. health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(0);
  109. }
  110. static struct bt_mesh_model_pub gen_level_pub;
  111. static struct bt_mesh_model_pub gen_onoff_pub;
  112. static uint8_t gen_on_off_state;
  113. static int16_t gen_level_state;
  114. static int gen_onoff_status(struct bt_mesh_model *model,
  115. struct bt_mesh_msg_ctx *ctx)
  116. {
  117. struct os_mbuf *msg = NET_BUF_SIMPLE(3);
  118. uint8_t *status;
  119. int rc;
  120. console_printf("#mesh-onoff STATUS\n");
  121. bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x04));
  122. status = net_buf_simple_add(msg, 1);
  123. *status = gen_on_off_state;
  124. rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL);
  125. if (rc) {
  126. console_printf("#mesh-onoff STATUS: send status failed\n");
  127. }
  128. os_mbuf_free_chain(msg);
  129. return rc;
  130. }
  131. static int gen_onoff_get(struct bt_mesh_model *model,
  132. struct bt_mesh_msg_ctx *ctx,
  133. struct os_mbuf *buf)
  134. {
  135. console_printf("#mesh-onoff GET\n");
  136. return gen_onoff_status(model, ctx);
  137. }
  138. static int gen_onoff_set(struct bt_mesh_model *model,
  139. struct bt_mesh_msg_ctx *ctx,
  140. struct os_mbuf *buf)
  141. {
  142. console_printf("#mesh-onoff SET\n");
  143. gen_on_off_state = buf->om_data[0];
  144. return gen_onoff_status(model, ctx);
  145. }
  146. static int gen_onoff_set_unack(struct bt_mesh_model *model,
  147. struct bt_mesh_msg_ctx *ctx,
  148. struct os_mbuf *buf)
  149. {
  150. console_printf("#mesh-onoff SET-UNACK\n");
  151. gen_on_off_state = buf->om_data[0];
  152. return 0;
  153. }
  154. static const struct bt_mesh_model_op gen_onoff_op[] = {
  155. { BT_MESH_MODEL_OP_2(0x82, 0x01), 0, gen_onoff_get },
  156. { BT_MESH_MODEL_OP_2(0x82, 0x02), 2, gen_onoff_set },
  157. { BT_MESH_MODEL_OP_2(0x82, 0x03), 2, gen_onoff_set_unack },
  158. BT_MESH_MODEL_OP_END,
  159. };
  160. static void gen_level_status(struct bt_mesh_model *model,
  161. struct bt_mesh_msg_ctx *ctx)
  162. {
  163. struct os_mbuf *msg = NET_BUF_SIMPLE(4);
  164. console_printf("#mesh-level STATUS\n");
  165. bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x08));
  166. net_buf_simple_add_le16(msg, gen_level_state);
  167. if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
  168. console_printf("#mesh-level STATUS: send status failed\n");
  169. }
  170. os_mbuf_free_chain(msg);
  171. }
  172. static int gen_level_get(struct bt_mesh_model *model,
  173. struct bt_mesh_msg_ctx *ctx,
  174. struct os_mbuf *buf)
  175. {
  176. console_printf("#mesh-level GET\n");
  177. gen_level_status(model, ctx);
  178. return 0;
  179. }
  180. static int gen_level_set(struct bt_mesh_model *model,
  181. struct bt_mesh_msg_ctx *ctx,
  182. struct os_mbuf *buf)
  183. {
  184. int16_t level;
  185. level = (int16_t) net_buf_simple_pull_le16(buf);
  186. console_printf("#mesh-level SET: level=%d\n", level);
  187. gen_level_status(model, ctx);
  188. gen_level_state = level;
  189. console_printf("#mesh-level: level=%d\n", gen_level_state);
  190. return 0;
  191. }
  192. static int gen_level_set_unack(struct bt_mesh_model *model,
  193. struct bt_mesh_msg_ctx *ctx,
  194. struct os_mbuf *buf)
  195. {
  196. int16_t level;
  197. level = (int16_t) net_buf_simple_pull_le16(buf);
  198. console_printf("#mesh-level SET-UNACK: level=%d\n", level);
  199. gen_level_state = level;
  200. console_printf("#mesh-level: level=%d\n", gen_level_state);
  201. return 0;
  202. }
  203. static int gen_delta_set(struct bt_mesh_model *model,
  204. struct bt_mesh_msg_ctx *ctx,
  205. struct os_mbuf *buf)
  206. {
  207. int16_t delta_level;
  208. delta_level = (int16_t) net_buf_simple_pull_le16(buf);
  209. console_printf("#mesh-level DELTA-SET: delta_level=%d\n", delta_level);
  210. gen_level_status(model, ctx);
  211. gen_level_state += delta_level;
  212. console_printf("#mesh-level: level=%d\n", gen_level_state);
  213. return 0;
  214. }
  215. static int gen_delta_set_unack(struct bt_mesh_model *model,
  216. struct bt_mesh_msg_ctx *ctx,
  217. struct os_mbuf *buf)
  218. {
  219. int16_t delta_level;
  220. delta_level = (int16_t) net_buf_simple_pull_le16(buf);
  221. console_printf("#mesh-level DELTA-SET: delta_level=%d\n", delta_level);
  222. gen_level_state += delta_level;
  223. console_printf("#mesh-level: level=%d\n", gen_level_state);
  224. return 0;
  225. }
  226. static int gen_move_set(struct bt_mesh_model *model,
  227. struct bt_mesh_msg_ctx *ctx,
  228. struct os_mbuf *buf)
  229. {
  230. return 0;
  231. }
  232. static int gen_move_set_unack(struct bt_mesh_model *model,
  233. struct bt_mesh_msg_ctx *ctx,
  234. struct os_mbuf *buf)
  235. {
  236. return 0;
  237. }
  238. static const struct bt_mesh_model_op gen_level_op[] = {
  239. { BT_MESH_MODEL_OP_2(0x82, 0x05), 0, gen_level_get },
  240. { BT_MESH_MODEL_OP_2(0x82, 0x06), 3, gen_level_set },
  241. { BT_MESH_MODEL_OP_2(0x82, 0x07), 3, gen_level_set_unack },
  242. { BT_MESH_MODEL_OP_2(0x82, 0x09), 5, gen_delta_set },
  243. { BT_MESH_MODEL_OP_2(0x82, 0x0a), 5, gen_delta_set_unack },
  244. { BT_MESH_MODEL_OP_2(0x82, 0x0b), 3, gen_move_set },
  245. { BT_MESH_MODEL_OP_2(0x82, 0x0c), 3, gen_move_set_unack },
  246. BT_MESH_MODEL_OP_END,
  247. };
  248. static struct bt_mesh_model root_models[] = {
  249. BT_MESH_MODEL_CFG_SRV,
  250. BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
  251. BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op,
  252. &gen_onoff_pub, NULL),
  253. BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, gen_level_op,
  254. &gen_level_pub, NULL),
  255. };
  256. static struct bt_mesh_model_pub vnd_model_pub;
  257. static int vnd_model_recv(struct bt_mesh_model *model,
  258. struct bt_mesh_msg_ctx *ctx,
  259. struct os_mbuf *buf)
  260. {
  261. struct os_mbuf *msg = NET_BUF_SIMPLE(3);
  262. int rc;
  263. console_printf("#vendor-model-recv\n");
  264. console_printf("data:%s len:%d\n", bt_hex(buf->om_data, buf->om_len),
  265. buf->om_len);
  266. bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_3(0x01, CID_VENDOR));
  267. os_mbuf_append(msg, buf->om_data, buf->om_len);
  268. rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL);
  269. if (rc) {
  270. console_printf("#vendor-model-recv: send rsp failed\n");
  271. }
  272. os_mbuf_free_chain(msg);
  273. return rc;
  274. }
  275. static const struct bt_mesh_model_op vnd_model_op[] = {
  276. { BT_MESH_MODEL_OP_3(0x01, CID_VENDOR), 0, vnd_model_recv },
  277. BT_MESH_MODEL_OP_END,
  278. };
  279. static struct bt_mesh_model vnd_models[] = {
  280. BT_MESH_MODEL_VND(CID_VENDOR, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, vnd_model_op,
  281. &vnd_model_pub, NULL),
  282. };
  283. static struct bt_mesh_elem elements[] = {
  284. BT_MESH_ELEM(0, root_models, vnd_models),
  285. };
  286. static const struct bt_mesh_comp comp = {
  287. .cid = CID_VENDOR,
  288. .elem = elements,
  289. .elem_count = ARRAY_SIZE(elements),
  290. };
  291. static int output_number(bt_mesh_output_action_t action, uint32_t number)
  292. {
  293. console_printf("OOB Number: %u\n", number);
  294. return 0;
  295. }
  296. static void prov_complete(uint16_t net_idx, uint16_t addr)
  297. {
  298. console_printf("Local node provisioned, primary address 0x%04x\n", addr);
  299. }
  300. static const uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
  301. static const struct bt_mesh_prov prov = {
  302. .uuid = dev_uuid,
  303. .output_size = 0,
  304. .output_actions = 0,
  305. .output_number = output_number,
  306. .complete = prov_complete,
  307. };
  308. static void
  309. blemesh_on_reset(int reason)
  310. {
  311. BLE_HS_LOG(ERROR, "Resetting state; reason=%d\n", reason);
  312. }
  313. void mesh_initialized(void);
  314. static void
  315. blemesh_on_sync(void)
  316. {
  317. int err;
  318. console_printf("Bluetooth initialized\n");
  319. err = bt_mesh_init(0, &prov, &comp);
  320. if (err) {
  321. console_printf("Initializing mesh failed (err %d)\n", err);
  322. return;
  323. }
  324. #if (MYNEWT_VAL(BLE_MESH_SHELL))
  325. shell_register_default_module("mesh");
  326. #endif
  327. console_printf("Mesh initialized\n");
  328. mesh_initialized();
  329. if (IS_ENABLED(CONFIG_SETTINGS)) {
  330. settings_load();
  331. }
  332. if (bt_mesh_is_provisioned()) {
  333. printk("Mesh network restored from flash\n");
  334. }
  335. }
  336. void
  337. nimble_host_task(void *param)
  338. {
  339. health_pub_init();
  340. /* Initialize the NimBLE host configuration. */
  341. ble_hs_cfg.reset_cb = blemesh_on_reset;
  342. ble_hs_cfg.sync_cb = blemesh_on_sync;
  343. ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
  344. nimble_port_run();
  345. }