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