1 /*
2 * Copyright (C) 2018-2020 Alibaba Group Holding Limited
3 */
4
5 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
6 #include <api/mesh.h>
7 #include "sig_models/sig_model.h"
8
9 #include "access.h"
10 #include "common/log.h"
11
12 struct bt_mesh_model_pub g_scene_pub = {
13 .msg = NET_BUF_SIMPLE(2 + 5 + 4),
14 };
15
_scene_prepare_buf(struct bt_mesh_model * p_model,struct net_buf_simple * p_msg,bool is_ack)16 static void _scene_prepare_buf(struct bt_mesh_model *p_model, struct net_buf_simple *p_msg, bool is_ack)
17 {
18 sig_model_state_t *p_state = &((sig_model_element_state_t *)p_model->user_data)->state;
19
20 bt_mesh_model_msg_init(p_msg, OP_GENERIC_SCENE_STATUS);
21 net_buf_simple_add_le16(p_msg, p_state->scene[TYPE_PRESENT]);
22 }
23
_scene_status(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,bool is_ack)24 static void _scene_status(struct bt_mesh_model *p_model,
25 struct bt_mesh_msg_ctx *p_ctx, bool is_ack)
26 {
27 struct net_buf_simple *p_msg = NET_BUF_SIMPLE(1 + 2 + 4);
28
29 BT_DBG("addr(0x%04x)", bt_mesh_model_elem(p_model)->addr);
30
31 _scene_prepare_buf(p_model, p_msg, is_ack);
32 p_ctx->send_ttl = GENIE_TRANSPORT_DEFAULT_TTL;
33 if (bt_mesh_model_send(p_model, p_ctx, p_msg, NULL, NULL))
34 {
35 BT_ERR("Unable to send scene Status");
36 }
37 BT_DBG("Success!!!");
38 }
39
genie_model_scene_changed(u16_t last_scene,u16_t target_scene)40 int genie_model_scene_changed(u16_t last_scene, u16_t target_scene)
41 {
42 return 0;
43 }
44
_scene_analyze(struct bt_mesh_model * p_model,u16_t src_addr,struct net_buf_simple * p_buf)45 static E_MESH_ERROR_TYPE _scene_analyze(struct bt_mesh_model *p_model,
46 u16_t src_addr, struct net_buf_simple *p_buf)
47 {
48 s16_t scene = 0;
49 u8_t tid = 0;
50 sig_model_element_state_t *p_elem = NULL;
51
52 if (!p_model || !p_buf)
53 return MESH_ANALYZE_ARGS_ERROR;
54
55 p_elem = p_model->user_data;
56
57 if (p_buf->len != 3 && p_buf->len != 5)
58 {
59 BT_ERR("MESH_ANALYZE_SIZE_ERROR buf->len(%d)", p_buf->len);
60 return MESH_ANALYZE_SIZE_ERROR;
61 }
62
63 scene = (s16_t)net_buf_simple_pull_le16(p_buf);
64 tid = net_buf_simple_pull_u8(p_buf);
65
66 if (genie_transport_check_tid(src_addr, tid, p_elem->element_id) != MESH_SUCCESS)
67 {
68 BT_ERR("MESH_TID_REPEAT src_addr(0x%04x) tid(0x%02x)", src_addr, tid);
69 return MESH_TID_REPEAT;
70 }
71 genie_transport_src_addr_set(src_addr);
72
73 if (p_elem->state.scene[TYPE_TARGET] != scene)
74 {
75 genie_model_scene_changed(p_elem->state.scene[TYPE_TARGET], scene);
76 p_elem->state.scene[TYPE_TARGET] = scene;
77 sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_SCENE);
78 }
79 else
80 {
81 GENIE_LOG_WARN("Dup light sence");
82 }
83
84 GENIE_LOG_INFO("light sence(0x%02x)", p_elem->state.scene);
85
86 return MESH_SUCCESS;
87 }
88
_scene_get(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)89 static void _scene_get(struct bt_mesh_model *p_model,
90 struct bt_mesh_msg_ctx *p_ctx,
91 struct net_buf_simple *p_buf)
92 {
93 sig_model_msg msg;
94 sig_model_element_state_t *p_elem_state = NULL;
95
96 memset(&msg, 0, sizeof(sig_model_msg));
97 msg.opcode = OP_GENERIC_SCENE_GET;
98
99 if (p_buf != NULL)
100 {
101 msg.len = p_buf->len;
102 msg.data = (u8_t *)p_buf->data;
103 }
104 genie_transport_src_addr_set(p_ctx->addr);
105
106 p_elem_state = (sig_model_element_state_t *)p_model->user_data;
107 msg.element_id = p_elem_state->element_id;
108 sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
109
110 #ifndef CONFIG_GENIE_MESH_NO_AUTO_REPLY
111 _scene_status(p_model, p_ctx, 0);
112 #endif
113 }
114
_scene_set(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)115 static void _scene_set(struct bt_mesh_model *p_model,
116 struct bt_mesh_msg_ctx *p_ctx,
117 struct net_buf_simple *p_buf)
118 {
119 sig_model_msg msg;
120 sig_model_element_state_t *p_elem_state = NULL;
121
122 memset(&msg, 0, sizeof(sig_model_msg));
123 msg.opcode = OP_GENERIC_SCENE_SET;
124 if (p_buf != NULL)
125 {
126 msg.len = p_buf->len;
127 msg.data = (u8_t *)p_buf->data;
128 }
129
130 E_MESH_ERROR_TYPE ret = _scene_analyze(p_model, p_ctx->addr, p_buf);
131
132 BT_DBG("ret %d", ret);
133
134 if (ret == MESH_SUCCESS)
135 {
136 p_elem_state = (sig_model_element_state_t *)p_model->user_data;
137 msg.element_id = p_elem_state->element_id;
138 sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
139 }
140
141 #ifndef CONFIG_GENIE_MESH_NO_AUTO_REPLY
142 if (ret == MESH_SUCCESS || ret == MESH_TID_REPEAT)
143 {
144 _scene_status(p_model, p_ctx, 1);
145 if (ret == MESH_SUCCESS)
146 {
147 sig_model_event(SIG_MODEL_EVT_ANALYZE_MSG, (sig_model_element_state_t *)p_model->user_data);
148 }
149 }
150 #endif
151 }
152
_scene_set_unack(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)153 static void _scene_set_unack(struct bt_mesh_model *p_model,
154 struct bt_mesh_msg_ctx *p_ctx,
155 struct net_buf_simple *p_buf)
156 {
157 sig_model_msg msg;
158 sig_model_element_state_t *p_elem_state = NULL;
159
160 memset(&msg, 0, sizeof(sig_model_msg));
161 msg.opcode = OP_GENERIC_SCENE_SET_UNACK;
162 if (p_buf != NULL)
163 {
164 msg.len = p_buf->len;
165 msg.data = (u8_t *)p_buf->data;
166 }
167
168 E_MESH_ERROR_TYPE ret = _scene_analyze(p_model, p_ctx->addr, p_buf);
169
170 if (ret == MESH_SUCCESS)
171 {
172 p_elem_state = (sig_model_element_state_t *)p_model->user_data;
173 msg.element_id = p_elem_state->element_id;
174 sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
175 #ifndef CONFIG_GENIE_MESH_NO_AUTO_REPLY
176 sig_model_event(SIG_MODEL_EVT_ANALYZE_MSG, (sig_model_element_state_t *)p_model->user_data);
177 #endif
178 }
179 }
180
181 const struct bt_mesh_model_op g_scene_op[GENIE_SCENE_OP_NUM] = {
182 {OP_GENERIC_SCENE_GET, 0, _scene_get},
183 {OP_GENERIC_SCENE_SET, 2, _scene_set},
184 {OP_GENERIC_SCENE_SET_UNACK, 2, _scene_set_unack},
185 BT_MESH_MODEL_OP_END,
186 };
187