1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <sys/printk.h>
10
11 #include <settings/settings.h>
12
13 #include <bluetooth/bluetooth.h>
14 #include <bluetooth/mesh.h>
15
16 #include "board.h"
17
18 #define MOD_LF 0x0000
19
20 #define GROUP_ADDR 0xc000
21 #define PUBLISHER_ADDR 0x000f
22
23 #define OP_VENDOR_BUTTON BT_MESH_MODEL_OP_3(0x00, BT_COMP_ID_LF)
24
25 static const uint8_t net_key[16] = {
26 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
27 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
28 };
29 static const uint8_t dev_key[16] = {
30 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
31 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
32 };
33 static const uint8_t app_key[16] = {
34 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
35 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
36 };
37 static const uint16_t net_idx;
38 static const uint16_t app_idx;
39 static const uint32_t iv_index;
40 static uint8_t flags;
41 static uint16_t addr = NODE_ADDR;
42
heartbeat(const struct bt_mesh_hb_sub * sub,uint8_t hops,uint16_t feat)43 static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops,
44 uint16_t feat)
45 {
46 board_heartbeat(hops, feat);
47 board_play("100H");
48 }
49
50 static struct bt_mesh_cfg_cli cfg_cli = {
51 };
52
attention_on(struct bt_mesh_model * model)53 static void attention_on(struct bt_mesh_model *model)
54 {
55 printk("attention_on()\n");
56 board_attention(true);
57 board_play("100H100C100H100C100H100C");
58 }
59
attention_off(struct bt_mesh_model * model)60 static void attention_off(struct bt_mesh_model *model)
61 {
62 printk("attention_off()\n");
63 board_attention(false);
64 }
65
66 static const struct bt_mesh_health_srv_cb health_srv_cb = {
67 .attn_on = attention_on,
68 .attn_off = attention_off,
69 };
70
71 static struct bt_mesh_health_srv health_srv = {
72 .cb = &health_srv_cb,
73 };
74
75 BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
76
77 static struct bt_mesh_model root_models[] = {
78 BT_MESH_MODEL_CFG_SRV,
79 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
80 BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
81 };
82
vnd_button_pressed(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)83 static int vnd_button_pressed(struct bt_mesh_model *model,
84 struct bt_mesh_msg_ctx *ctx,
85 struct net_buf_simple *buf)
86 {
87 printk("src 0x%04x\n", ctx->addr);
88
89 if (ctx->addr == bt_mesh_model_elem(model)->addr) {
90 return 0;
91 }
92
93 board_other_dev_pressed(ctx->addr);
94 board_play("100G200 100G");
95
96 return 0;
97 }
98
99 static const struct bt_mesh_model_op vnd_ops[] = {
100 { OP_VENDOR_BUTTON, BT_MESH_LEN_EXACT(0), vnd_button_pressed },
101 BT_MESH_MODEL_OP_END,
102 };
103
104 static struct bt_mesh_model vnd_models[] = {
105 BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, NULL, NULL),
106 };
107
108 static struct bt_mesh_elem elements[] = {
109 BT_MESH_ELEM(0, root_models, vnd_models),
110 };
111
112 static const struct bt_mesh_comp comp = {
113 .cid = BT_COMP_ID_LF,
114 .elem = elements,
115 .elem_count = ARRAY_SIZE(elements),
116 };
117
configure(void)118 static void configure(void)
119 {
120 printk("Configuring...\n");
121
122 /* Add Application Key */
123 bt_mesh_cfg_app_key_add(net_idx, addr, net_idx, app_idx, app_key, NULL);
124
125 /* Bind to vendor model */
126 bt_mesh_cfg_mod_app_bind_vnd(net_idx, addr, addr, app_idx,
127 MOD_LF, BT_COMP_ID_LF, NULL);
128
129 /* Bind to Health model */
130 bt_mesh_cfg_mod_app_bind(net_idx, addr, addr, app_idx,
131 BT_MESH_MODEL_ID_HEALTH_SRV, NULL);
132
133 /* Add model subscription */
134 bt_mesh_cfg_mod_sub_add_vnd(net_idx, addr, addr, GROUP_ADDR,
135 MOD_LF, BT_COMP_ID_LF, NULL);
136
137 #if NODE_ADDR == PUBLISHER_ADDR
138 {
139 struct bt_mesh_cfg_hb_pub pub = {
140 .dst = GROUP_ADDR,
141 .count = 0xff,
142 .period = 0x05,
143 .ttl = 0x07,
144 .feat = 0,
145 .net_idx = net_idx,
146 };
147
148 bt_mesh_cfg_hb_pub_set(net_idx, addr, &pub, NULL);
149 printk("Publishing heartbeat messages\n");
150 }
151 #endif
152 printk("Configuration complete\n");
153
154 board_play("100C100D100E100F100G100A100H");
155 }
156
157 static const uint8_t dev_uuid[16] = { 0xdd, 0xdd };
158
159 static const struct bt_mesh_prov prov = {
160 .uuid = dev_uuid,
161 };
162
163 BT_MESH_HB_CB_DEFINE(hb_cb) = {
164 .recv = heartbeat,
165 };
166
bt_ready(int err)167 static void bt_ready(int err)
168 {
169 if (err) {
170 printk("Bluetooth init failed (err %d)\n", err);
171 return;
172 }
173
174 printk("Bluetooth initialized\n");
175
176 err = bt_mesh_init(&prov, &comp);
177 if (err) {
178 printk("Initializing mesh failed (err %d)\n", err);
179 return;
180 }
181
182 printk("Mesh initialized\n");
183
184 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
185 printk("Loading stored settings\n");
186 settings_load();
187 }
188
189 err = bt_mesh_provision(net_key, net_idx, flags, iv_index, addr,
190 dev_key);
191 if (err == -EALREADY) {
192 printk("Using stored settings\n");
193 } else if (err) {
194 printk("Provisioning failed (err %d)\n", err);
195 return;
196 } else {
197 printk("Provisioning completed\n");
198 configure();
199 }
200
201 #if NODE_ADDR != PUBLISHER_ADDR
202 /* Heartbeat subcscription is a temporary state (due to there
203 * not being an "indefinite" value for the period, so it never
204 * gets stored persistently. Therefore, we always have to configure
205 * it explicitly.
206 */
207 {
208 struct bt_mesh_cfg_hb_sub sub = {
209 .src = PUBLISHER_ADDR,
210 .dst = GROUP_ADDR,
211 .period = 0x10,
212 };
213
214 bt_mesh_cfg_hb_sub_set(net_idx, addr, &sub, NULL);
215 printk("Subscribing to heartbeat messages\n");
216 }
217 #endif
218 }
219
220 static uint16_t target = GROUP_ADDR;
221
board_button_1_pressed(void)222 void board_button_1_pressed(void)
223 {
224 NET_BUF_SIMPLE_DEFINE(msg, 3 + 4);
225 struct bt_mesh_msg_ctx ctx = {
226 .app_idx = app_idx,
227 .addr = target,
228 .send_ttl = BT_MESH_TTL_DEFAULT,
229 };
230
231 /* Bind to Health model */
232 bt_mesh_model_msg_init(&msg, OP_VENDOR_BUTTON);
233
234 if (bt_mesh_model_send(&vnd_models[0], &ctx, &msg, NULL, NULL)) {
235 printk("Unable to send Vendor Button message\n");
236 }
237
238 printk("Button message sent with OpCode 0x%08x\n", OP_VENDOR_BUTTON);
239 }
240
board_set_target(void)241 uint16_t board_set_target(void)
242 {
243 switch (target) {
244 case GROUP_ADDR:
245 target = 1U;
246 break;
247 case 9:
248 target = GROUP_ADDR;
249 break;
250 default:
251 target++;
252 break;
253 }
254
255 return target;
256 }
257
258 static K_SEM_DEFINE(tune_sem, 0, 1);
259 static const char *tune_str;
260
board_play(const char * str)261 void board_play(const char *str)
262 {
263 tune_str = str;
264 k_sem_give(&tune_sem);
265 }
266
main(void)267 void main(void)
268 {
269 int err;
270
271 printk("Initializing...\n");
272
273 err = board_init(&addr);
274 if (err) {
275 printk("Board initialization failed\n");
276 return;
277 }
278
279 printk("Unicast address: 0x%04x\n", addr);
280
281 /* Initialize the Bluetooth Subsystem */
282 err = bt_enable(bt_ready);
283 if (err) {
284 printk("Bluetooth init failed (err %d)\n", err);
285 return;
286 }
287
288 while (1) {
289 k_sem_take(&tune_sem, K_FOREVER);
290 board_play_tune(tune_str);
291 }
292
293 }
294