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 <zephyr/sys/printk.h>
10
11 #include <zephyr/settings/settings.h>
12
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/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_cli_app_key_add(net_idx, addr, net_idx, app_idx, app_key, NULL);
124
125 /* Bind to vendor model */
126 bt_mesh_cfg_cli_mod_app_bind_vnd(net_idx, addr, addr, app_idx, MOD_LF, BT_COMP_ID_LF, NULL);
127
128 /* Bind to Health model */
129 bt_mesh_cfg_cli_mod_app_bind(net_idx, addr, addr, app_idx, BT_MESH_MODEL_ID_HEALTH_SRV,
130 NULL);
131
132 /* Add model subscription */
133 bt_mesh_cfg_cli_mod_sub_add_vnd(net_idx, addr, addr, GROUP_ADDR, MOD_LF, BT_COMP_ID_LF,
134 NULL);
135
136 #if NODE_ADDR == PUBLISHER_ADDR
137 {
138 struct bt_mesh_cfg_cli_hb_pub pub = {
139 .dst = GROUP_ADDR,
140 .count = 0xff,
141 .period = 0x05,
142 .ttl = 0x07,
143 .feat = 0,
144 .net_idx = net_idx,
145 };
146
147 bt_mesh_cfg_cli_hb_pub_set(net_idx, addr, &pub, NULL);
148 printk("Publishing heartbeat messages\n");
149 }
150 #endif
151 printk("Configuration complete\n");
152
153 board_play("100C100D100E100F100G100A100H");
154 }
155
156 static const uint8_t dev_uuid[16] = { 0xdd, 0xdd };
157
158 static const struct bt_mesh_prov prov = {
159 .uuid = dev_uuid,
160 };
161
162 BT_MESH_HB_CB_DEFINE(hb_cb) = {
163 .recv = heartbeat,
164 };
165
bt_ready(int err)166 static void bt_ready(int err)
167 {
168 if (err) {
169 printk("Bluetooth init failed (err %d)\n", err);
170 return;
171 }
172
173 printk("Bluetooth initialized\n");
174
175 err = bt_mesh_init(&prov, &comp);
176 if (err) {
177 printk("Initializing mesh failed (err %d)\n", err);
178 return;
179 }
180
181 printk("Mesh initialized\n");
182
183 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
184 printk("Loading stored settings\n");
185 settings_load();
186 }
187
188 err = bt_mesh_provision(net_key, net_idx, flags, iv_index, addr,
189 dev_key);
190 if (err == -EALREADY) {
191 printk("Using stored settings\n");
192 } else if (err) {
193 printk("Provisioning failed (err %d)\n", err);
194 return;
195 } else {
196 printk("Provisioning completed\n");
197 configure();
198 }
199
200 #if NODE_ADDR != PUBLISHER_ADDR
201 /* Heartbeat subscription is a temporary state (due to there
202 * not being an "indefinite" value for the period, so it never
203 * gets stored persistently. Therefore, we always have to configure
204 * it explicitly.
205 */
206 {
207 struct bt_mesh_cfg_cli_hb_sub sub = {
208 .src = PUBLISHER_ADDR,
209 .dst = GROUP_ADDR,
210 .period = 0x10,
211 };
212
213 bt_mesh_cfg_cli_hb_sub_set(net_idx, addr, &sub, NULL);
214 printk("Subscribing to heartbeat messages\n");
215 }
216 #endif
217 }
218
219 static uint16_t target = GROUP_ADDR;
220
board_button_1_pressed(void)221 void board_button_1_pressed(void)
222 {
223 NET_BUF_SIMPLE_DEFINE(msg, 3 + 4);
224 struct bt_mesh_msg_ctx ctx = {
225 .app_idx = app_idx,
226 .addr = target,
227 .send_ttl = BT_MESH_TTL_DEFAULT,
228 };
229
230 /* Bind to Health model */
231 bt_mesh_model_msg_init(&msg, OP_VENDOR_BUTTON);
232
233 if (bt_mesh_model_send(&vnd_models[0], &ctx, &msg, NULL, NULL)) {
234 printk("Unable to send Vendor Button message\n");
235 }
236
237 printk("Button message sent with OpCode 0x%08x\n", OP_VENDOR_BUTTON);
238 }
239
board_set_target(void)240 uint16_t board_set_target(void)
241 {
242 switch (target) {
243 case GROUP_ADDR:
244 target = 1U;
245 break;
246 case 9:
247 target = GROUP_ADDR;
248 break;
249 default:
250 target++;
251 break;
252 }
253
254 return target;
255 }
256
257 static K_SEM_DEFINE(tune_sem, 0, 1);
258 static const char *tune_str;
259
board_play(const char * str)260 void board_play(const char *str)
261 {
262 tune_str = str;
263 k_sem_give(&tune_sem);
264 }
265
main(void)266 int main(void)
267 {
268 int err;
269
270 printk("Initializing...\n");
271
272 err = board_init(&addr);
273 if (err) {
274 printk("Board initialization failed\n");
275 return 0;
276 }
277
278 printk("Unicast address: 0x%04x\n", addr);
279
280 /* Initialize the Bluetooth Subsystem */
281 err = bt_enable(bt_ready);
282 if (err) {
283 printk("Bluetooth init failed (err %d)\n", err);
284 return 0;
285 }
286
287 while (1) {
288 k_sem_take(&tune_sem, K_FOREVER);
289 board_play_tune(tune_str);
290 }
291
292 return 0;
293 }
294