xref: /nrf52832-nimble/packages/NimBLE-latest/apps/blemesh/src/main.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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 
20 #include <assert.h>
21 #include "os/mynewt.h"
22 #include "mesh/mesh.h"
23 #include "console/console.h"
24 #include "hal/hal_system.h"
25 #include "hal/hal_gpio.h"
26 #include "bsp/bsp.h"
27 #include "shell/shell.h"
28 
29 /* BLE */
30 #include "nimble/ble.h"
31 #include "host/ble_hs.h"
32 #include "services/gap/ble_svc_gap.h"
33 #include "mesh/glue.h"
34 
35 #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
36 
37 /* Company ID */
38 #define CID_VENDOR 0x05C3
39 #define STANDARD_TEST_ID 0x00
40 #define TEST_ID 0x01
41 static int recent_test_id = STANDARD_TEST_ID;
42 
43 #define FAULT_ARR_SIZE 2
44 
45 static bool has_reg_fault = true;
46 
47 static struct bt_mesh_cfg_srv cfg_srv = {
48     .relay = BT_MESH_RELAY_DISABLED,
49     .beacon = BT_MESH_BEACON_ENABLED,
50 #if MYNEWT_VAL(BLE_MESH_FRIEND)
51     .frnd = BT_MESH_FRIEND_ENABLED,
52 #else
53     .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
54 #endif
55 #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
56     .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
57 #else
58     .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
59 #endif
60     .default_ttl = 7,
61 
62     /* 3 transmissions with 20ms interval */
63     .net_transmit = BT_MESH_TRANSMIT(2, 20),
64     .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
65 };
66 
67 static int
fault_get_cur(struct bt_mesh_model * model,uint8_t * test_id,uint16_t * company_id,uint8_t * faults,uint8_t * fault_count)68 fault_get_cur(struct bt_mesh_model *model,
69               uint8_t *test_id,
70               uint16_t *company_id,
71               uint8_t *faults,
72               uint8_t *fault_count)
73 {
74     uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE-1] = 0xff };
75 
76     console_printf("fault_get_cur() has_reg_fault %u\n", has_reg_fault);
77 
78     *test_id = recent_test_id;
79     *company_id = CID_VENDOR;
80 
81     *fault_count = min(*fault_count, sizeof(reg_faults));
82     memcpy(faults, reg_faults, *fault_count);
83 
84     return 0;
85 }
86 
87 static int
fault_get_reg(struct bt_mesh_model * model,uint16_t company_id,uint8_t * test_id,uint8_t * faults,uint8_t * fault_count)88 fault_get_reg(struct bt_mesh_model *model,
89               uint16_t company_id,
90               uint8_t *test_id,
91               uint8_t *faults,
92               uint8_t *fault_count)
93 {
94     if (company_id != CID_VENDOR) {
95         return -BLE_HS_EINVAL;
96     }
97 
98     console_printf("fault_get_reg() has_reg_fault %u\n", has_reg_fault);
99 
100     *test_id = recent_test_id;
101 
102     if (has_reg_fault) {
103         uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE-1] = 0xff };
104 
105         *fault_count = min(*fault_count, sizeof(reg_faults));
106         memcpy(faults, reg_faults, *fault_count);
107     } else {
108         *fault_count = 0;
109     }
110 
111     return 0;
112 }
113 
114 static int
fault_clear(struct bt_mesh_model * model,uint16_t company_id)115 fault_clear(struct bt_mesh_model *model, uint16_t company_id)
116 {
117     if (company_id != CID_VENDOR) {
118         return -BLE_HS_EINVAL;
119     }
120 
121     has_reg_fault = false;
122 
123     return 0;
124 }
125 
126 static int
fault_test(struct bt_mesh_model * model,uint8_t test_id,uint16_t company_id)127 fault_test(struct bt_mesh_model *model, uint8_t test_id, uint16_t company_id)
128 {
129     if (company_id != CID_VENDOR) {
130         return -BLE_HS_EINVAL;
131     }
132 
133     if (test_id != STANDARD_TEST_ID && test_id != TEST_ID) {
134         return -BLE_HS_EINVAL;
135     }
136 
137     recent_test_id = test_id;
138     has_reg_fault = true;
139     bt_mesh_fault_update(bt_mesh_model_elem(model));
140 
141     return 0;
142 }
143 
144 static const struct bt_mesh_health_srv_cb health_srv_cb = {
145     .fault_get_cur = &fault_get_cur,
146     .fault_get_reg = &fault_get_reg,
147     .fault_clear = &fault_clear,
148     .fault_test = &fault_test,
149 };
150 
151 static struct bt_mesh_health_srv health_srv = {
152     .cb = &health_srv_cb,
153 };
154 
155 static struct bt_mesh_model_pub health_pub;
156 
157 static void
health_pub_init(void)158 health_pub_init(void)
159 {
160     health_pub.msg  = BT_MESH_HEALTH_FAULT_MSG(0);
161 }
162 
163 static struct bt_mesh_model_pub gen_level_pub;
164 static struct bt_mesh_model_pub gen_onoff_pub;
165 
166 static uint8_t gen_on_off_state;
167 static int16_t gen_level_state;
168 
gen_onoff_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx)169 static void gen_onoff_status(struct bt_mesh_model *model,
170                              struct bt_mesh_msg_ctx *ctx)
171 {
172     struct os_mbuf *msg = NET_BUF_SIMPLE(3);
173     uint8_t *status;
174 
175     console_printf("#mesh-onoff STATUS\n");
176 
177     bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x04));
178     status = net_buf_simple_add(msg, 1);
179     *status = gen_on_off_state;
180 
181     if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
182         console_printf("#mesh-onoff STATUS: send status failed\n");
183     }
184 
185     os_mbuf_free_chain(msg);
186 }
187 
gen_onoff_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)188 static void gen_onoff_get(struct bt_mesh_model *model,
189               struct bt_mesh_msg_ctx *ctx,
190               struct os_mbuf *buf)
191 {
192     console_printf("#mesh-onoff GET\n");
193 
194     gen_onoff_status(model, ctx);
195 }
196 
gen_onoff_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)197 static void gen_onoff_set(struct bt_mesh_model *model,
198               struct bt_mesh_msg_ctx *ctx,
199               struct os_mbuf *buf)
200 {
201     console_printf("#mesh-onoff SET\n");
202 
203     gen_on_off_state = buf->om_data[0];
204     hal_gpio_write(LED_2, !gen_on_off_state);
205 
206     gen_onoff_status(model, ctx);
207 }
208 
gen_onoff_set_unack(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)209 static void gen_onoff_set_unack(struct bt_mesh_model *model,
210                 struct bt_mesh_msg_ctx *ctx,
211                 struct os_mbuf *buf)
212 {
213     console_printf("#mesh-onoff SET-UNACK\n");
214 
215     gen_on_off_state = buf->om_data[0];
216     hal_gpio_write(LED_2, !gen_on_off_state);
217 }
218 
219 static const struct bt_mesh_model_op gen_onoff_op[] = {
220     { BT_MESH_MODEL_OP_2(0x82, 0x01), 0, gen_onoff_get },
221     { BT_MESH_MODEL_OP_2(0x82, 0x02), 2, gen_onoff_set },
222     { BT_MESH_MODEL_OP_2(0x82, 0x03), 2, gen_onoff_set_unack },
223     BT_MESH_MODEL_OP_END,
224 };
225 
gen_level_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx)226 static void gen_level_status(struct bt_mesh_model *model,
227                              struct bt_mesh_msg_ctx *ctx)
228 {
229     struct os_mbuf *msg = NET_BUF_SIMPLE(4);
230 
231     console_printf("#mesh-level STATUS\n");
232 
233     bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x08));
234     net_buf_simple_add_le16(msg, gen_level_state);
235 
236     if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
237         console_printf("#mesh-level STATUS: send status failed\n");
238     }
239 
240     os_mbuf_free_chain(msg);
241 }
242 
gen_level_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)243 static void gen_level_get(struct bt_mesh_model *model,
244               struct bt_mesh_msg_ctx *ctx,
245               struct os_mbuf *buf)
246 {
247     console_printf("#mesh-level GET\n");
248 
249     gen_level_status(model, ctx);
250 }
251 
gen_level_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)252 static void gen_level_set(struct bt_mesh_model *model,
253               struct bt_mesh_msg_ctx *ctx,
254               struct os_mbuf *buf)
255 {
256     int16_t level;
257 
258     level = (int16_t) net_buf_simple_pull_le16(buf);
259     console_printf("#mesh-level SET: level=%d\n", level);
260 
261     gen_level_status(model, ctx);
262 
263     gen_level_state = level;
264     console_printf("#mesh-level: level=%d\n", gen_level_state);
265 }
266 
gen_level_set_unack(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)267 static void gen_level_set_unack(struct bt_mesh_model *model,
268                 struct bt_mesh_msg_ctx *ctx,
269                 struct os_mbuf *buf)
270 {
271     int16_t level;
272 
273     level = (int16_t) net_buf_simple_pull_le16(buf);
274     console_printf("#mesh-level SET-UNACK: level=%d\n", level);
275 
276     gen_level_state = level;
277     console_printf("#mesh-level: level=%d\n", gen_level_state);
278 }
279 
gen_delta_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)280 static void gen_delta_set(struct bt_mesh_model *model,
281               struct bt_mesh_msg_ctx *ctx,
282               struct os_mbuf *buf)
283 {
284     int16_t delta_level;
285 
286     delta_level = (int16_t) net_buf_simple_pull_le16(buf);
287     console_printf("#mesh-level DELTA-SET: delta_level=%d\n", delta_level);
288 
289     gen_level_status(model, ctx);
290 
291     gen_level_state += delta_level;
292     console_printf("#mesh-level: level=%d\n", gen_level_state);
293 }
294 
gen_delta_set_unack(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)295 static void gen_delta_set_unack(struct bt_mesh_model *model,
296                 struct bt_mesh_msg_ctx *ctx,
297                 struct os_mbuf *buf)
298 {
299     int16_t delta_level;
300 
301     delta_level = (int16_t) net_buf_simple_pull_le16(buf);
302     console_printf("#mesh-level DELTA-SET: delta_level=%d\n", delta_level);
303 
304     gen_level_state += delta_level;
305     console_printf("#mesh-level: level=%d\n", gen_level_state);
306 }
307 
gen_move_set(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)308 static void gen_move_set(struct bt_mesh_model *model,
309              struct bt_mesh_msg_ctx *ctx,
310              struct os_mbuf *buf)
311 {
312 }
313 
gen_move_set_unack(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)314 static void gen_move_set_unack(struct bt_mesh_model *model,
315                    struct bt_mesh_msg_ctx *ctx,
316                    struct os_mbuf *buf)
317 {
318 }
319 
320 static const struct bt_mesh_model_op gen_level_op[] = {
321     { BT_MESH_MODEL_OP_2(0x82, 0x05), 0, gen_level_get },
322     { BT_MESH_MODEL_OP_2(0x82, 0x06), 3, gen_level_set },
323     { BT_MESH_MODEL_OP_2(0x82, 0x07), 3, gen_level_set_unack },
324     { BT_MESH_MODEL_OP_2(0x82, 0x09), 5, gen_delta_set },
325     { BT_MESH_MODEL_OP_2(0x82, 0x0a), 5, gen_delta_set_unack },
326     { BT_MESH_MODEL_OP_2(0x82, 0x0b), 3, gen_move_set },
327     { BT_MESH_MODEL_OP_2(0x82, 0x0c), 3, gen_move_set_unack },
328     BT_MESH_MODEL_OP_END,
329 };
330 
331 static struct bt_mesh_model root_models[] = {
332     BT_MESH_MODEL_CFG_SRV(&cfg_srv),
333     BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
334     BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op,
335               &gen_onoff_pub, NULL),
336     BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, gen_level_op,
337               &gen_level_pub, NULL),
338 };
339 
340 static struct bt_mesh_model_pub vnd_model_pub;
341 
vnd_model_recv(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)342 static void vnd_model_recv(struct bt_mesh_model *model,
343                            struct bt_mesh_msg_ctx *ctx,
344                            struct os_mbuf *buf)
345 {
346     struct os_mbuf *msg = NET_BUF_SIMPLE(3);
347 
348     console_printf("#vendor-model-recv\n");
349 
350     console_printf("data:%s len:%d\n", bt_hex(buf->om_data, buf->om_len),
351                    buf->om_len);
352 
353     bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_3(0x01, CID_VENDOR));
354     os_mbuf_append(msg, buf->om_data, buf->om_len);
355 
356     if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
357         console_printf("#vendor-model-recv: send rsp failed\n");
358     }
359 
360     os_mbuf_free_chain(msg);
361 }
362 
363 static const struct bt_mesh_model_op vnd_model_op[] = {
364         { BT_MESH_MODEL_OP_3(0x01, CID_VENDOR), 0, vnd_model_recv },
365         BT_MESH_MODEL_OP_END,
366 };
367 
368 static struct bt_mesh_model vnd_models[] = {
369     BT_MESH_MODEL_VND(CID_VENDOR, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, vnd_model_op,
370               &vnd_model_pub, NULL),
371 };
372 
373 static struct bt_mesh_elem elements[] = {
374     BT_MESH_ELEM(0, root_models, vnd_models),
375 };
376 
377 static const struct bt_mesh_comp comp = {
378     .cid = CID_VENDOR,
379     .elem = elements,
380     .elem_count = ARRAY_SIZE(elements),
381 };
382 
output_number(bt_mesh_output_action_t action,uint32_t number)383 static int output_number(bt_mesh_output_action_t action, uint32_t number)
384 {
385     console_printf("OOB Number: %lu\n", number);
386 
387     return 0;
388 }
389 
prov_complete(u16_t net_idx,u16_t addr)390 static void prov_complete(u16_t net_idx, u16_t addr)
391 {
392     console_printf("Local node provisioned, primary address 0x%04x\n", addr);
393 }
394 
395 static const uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
396 
397 static const struct bt_mesh_prov prov = {
398     .uuid = dev_uuid,
399     .output_size = 4,
400     .output_actions = BT_MESH_DISPLAY_NUMBER | BT_MESH_BEEP | BT_MESH_VIBRATE | BT_MESH_BLINK,
401     .output_number = output_number,
402     .complete = prov_complete,
403 };
404 
405 static void
blemesh_on_reset(int reason)406 blemesh_on_reset(int reason)
407 {
408     BLE_HS_LOG(ERROR, "Resetting state; reason=%d\n", reason);
409 }
410 
411 static void
blemesh_on_sync(void)412 blemesh_on_sync(void)
413 {
414     int err;
415     ble_addr_t addr;
416 
417     console_printf("Bluetooth initialized\n");
418 
419     /* Use NRPA */
420     err = ble_hs_id_gen_rnd(1, &addr);
421     assert(err == 0);
422     err = ble_hs_id_set_rnd(addr.val);
423     assert(err == 0);
424 
425     err = bt_mesh_init(addr.type, &prov, &comp);
426     if (err) {
427         console_printf("Initializing mesh failed (err %d)\n", err);
428         return;
429     }
430 
431 #if (MYNEWT_VAL(BLE_MESH_SHELL))
432     shell_register_default_module("mesh");
433 #endif
434 
435     console_printf("Mesh initialized\n");
436 
437     if (IS_ENABLED(CONFIG_SETTINGS)) {
438         settings_load();
439     }
440 
441     if (bt_mesh_is_provisioned()) {
442         printk("Mesh network restored from flash\n");
443     }
444 }
445 
446 int
main(int argc,char ** argv)447 main(int argc, char **argv)
448 {
449 
450 #ifdef ARCH_sim
451     mcu_sim_parse_args(argc, argv);
452 #endif
453 
454     /* Initialize OS */
455     sysinit();
456 
457     /* Initialize the NimBLE host configuration. */
458     ble_hs_cfg.reset_cb = blemesh_on_reset;
459     ble_hs_cfg.sync_cb = blemesh_on_sync;
460     ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
461 
462     hal_gpio_init_out(LED_2, 0);
463 
464     health_pub_init();
465 
466     while (1) {
467         os_eventq_run(os_eventq_dflt_get());
468     }
469     return 0;
470 }
471