1 /*
2 * Copyright (C) 2018-2020 Alibaba Group Holding Limited
3 */
4
5 #include <api/mesh.h>
6 #include <mesh.h>
7 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
8 #include "common/log.h"
9 #include "genie_service.h"
10
11 struct bt_mesh_model_pub g_ctl_srv_pub = {
12
13 };
14
15 #if CONFIG_MESH_MODEL_CTL_SRV //light ctl server
_ctl_prepare_buf(struct bt_mesh_model * p_model,struct net_buf_simple * p_msg,bool is_ack)16 static void _ctl_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 u8_t remain_time_byte = 0;
20
21 BT_DBG("color_temperature cur(0x%04x) tar(0x%04x)", p_state->color_temperature[TYPE_PRESENT], p_state->color_temperature[TYPE_TARGET]);
22 #ifdef CONFIG_MESH_MODEL_TRANS
23 remain_time_byte = sig_model_transition_get_remain_time_byte(p_state, is_ack);
24
25 BT_DBG("remain(0x%02x)", remain_time_byte);
26 #endif
27
28 //prepear buff
29 bt_mesh_model_msg_init(p_msg, OP_GENERIC_LIGHT_CTL_STATUS);
30 if (is_ack && remain_time_byte == 0)
31 {
32 net_buf_simple_add_le16(p_msg, p_state->lightness[TYPE_TARGET]);
33 net_buf_simple_add_le16(p_msg, p_state->color_temperature[TYPE_TARGET]);
34 }
35 else
36 {
37 net_buf_simple_add_le16(p_msg, p_state->lightness[TYPE_PRESENT]);
38 net_buf_simple_add_le16(p_msg, p_state->color_temperature[TYPE_PRESENT]);
39
40 #ifdef CONFIG_MESH_MODEL_TRANS
41 if (remain_time_byte)
42 {
43 net_buf_simple_add_le16(p_msg, p_state->lightness[TYPE_TARGET]);
44 net_buf_simple_add_le16(p_msg, p_state->color_temperature[TYPE_TARGET]);
45 net_buf_simple_add_u8(p_msg, remain_time_byte);
46 }
47 #endif
48 }
49 }
50
_ctl_status(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,bool is_ack)51 static void _ctl_status(struct bt_mesh_model *p_model,
52 struct bt_mesh_msg_ctx *p_ctx, bool is_ack)
53 {
54 struct net_buf_simple *p_msg = NET_BUF_SIMPLE(2 + 9 + 4);
55
56 BT_DBG("addr(0x%04x)", bt_mesh_model_elem(p_model)->addr);
57
58 _ctl_prepare_buf(p_model, p_msg, is_ack);
59 p_ctx->send_ttl = GENIE_TRANSPORT_DEFAULT_TTL;
60 if (bt_mesh_model_send(p_model, p_ctx, p_msg, NULL, NULL))
61 {
62 BT_ERR("Unable to send ctl Status");
63 }
64 BT_DBG("Success!!!");
65 }
66
_ctl_analyze(struct bt_mesh_model * p_model,u16_t src_addr,struct net_buf_simple * p_buf)67 static u8_t _ctl_analyze(struct bt_mesh_model *p_model,
68 u16_t src_addr, struct net_buf_simple *p_buf)
69 {
70 u16_t lightness = 0;
71 u16_t color_temperature = 0;
72 u16_t uv = 0;
73 u8_t tid = 0;
74 #ifdef CONFIG_MESH_MODEL_TRANS
75 u8_t trans = 0;
76 u8_t delay = 0;
77 #endif
78 sig_model_element_state_t *p_elem = NULL;
79
80 if (!p_model || !p_buf)
81 return MESH_ANALYZE_ARGS_ERROR;
82
83 p_elem = p_model->user_data;
84
85 if (p_buf->len != 7 && p_buf->len != 9)
86 {
87 BT_ERR("MESH_ANALYZE_SIZE_ERROR p_buf->len(%d)", p_buf->len);
88 return MESH_ANALYZE_SIZE_ERROR;
89 }
90
91 //get message info
92 lightness = net_buf_simple_pull_le16(p_buf);
93 color_temperature = net_buf_simple_pull_le16(p_buf);
94 uv = net_buf_simple_pull_le16(p_buf);
95 tid = net_buf_simple_pull_u8(p_buf);
96
97 GENIE_LOG_INFO("uv:%d lightness:%d", uv, lightness);
98 (void)uv;
99 (void)lightness;
100 #ifdef CONFIG_MESH_MODEL_TRANS
101 if (p_buf->len)
102 {
103 trans = net_buf_simple_pull_u8(p_buf);
104 delay = net_buf_simple_pull_u8(p_buf);
105 }
106 else
107 {
108 trans = 0;
109 delay = 0;
110 }
111 if ((trans & 0x3F) == 0x3F)
112 {
113 BT_ERR("MESH_SET_TRANSTION_ERROR");
114 return MESH_SET_TRANSTION_ERROR;
115 }
116 #endif
117
118 //check color_temperature
119 if (color_temperature < COLOR_TEMPERATURE_MIN || color_temperature > COLOR_TEMPERATURE_MAX)
120 {
121 BT_ERR("MESH_ANALYZE_ARGS_ERROR color_temperature(0x%04x)", color_temperature);
122 return MESH_ANALYZE_ARGS_ERROR;
123 }
124
125 if (genie_transport_check_tid(src_addr, tid, p_elem->element_id) != MESH_SUCCESS)
126 {
127 BT_ERR("MESH_TID_REPEAT src_addr(0x%04x) tid(0x%02x)", src_addr, tid);
128 return MESH_TID_REPEAT;
129 }
130
131 p_elem->state.color_temperature[TYPE_TARGET] = color_temperature;
132 p_elem->powerup.last_color_temperature = p_elem->state.color_temperature[TYPE_TARGET];
133 BT_DBG("color_temperature cur(%04x) tar(%04x)", p_elem->state.color_temperature[TYPE_PRESENT], p_elem->state.color_temperature[TYPE_TARGET]);
134
135 #ifdef CONFIG_MESH_MODEL_TRANS
136 p_elem->state.trans = trans;
137 p_elem->state.delay = delay;
138 if (p_elem->state.trans)
139 {
140 p_elem->state.trans_start_time = k_uptime_get() + p_elem->state.delay * 5; // delay is in 5 millisecond steps
141 p_elem->state.trans_end_time = p_elem->state.trans_start_time + sig_model_transition_get_transition_time(p_elem->state.trans);
142 }
143 BT_DBG("trans(0x%02x) delay(0x%02x)", p_elem->state.trans, p_elem->state.delay);
144 #endif
145
146 //only check color_temperature when ali simaple model
147 if (p_elem->state.color_temperature[TYPE_PRESENT] != p_elem->state.color_temperature[TYPE_TARGET])
148 {
149 //only bind color_temperature when ali_simple_model is enable
150 sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_CTL);
151 sig_model_generic_color_temperature_bind_ops(p_elem);
152 }
153
154 return MESH_SUCCESS;
155 }
156
_ctl_get(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)157 static void _ctl_get(struct bt_mesh_model *p_model,
158 struct bt_mesh_msg_ctx *p_ctx,
159 struct net_buf_simple *p_buf)
160 {
161 BT_DBG("");
162
163 sig_model_msg msg;
164 sig_model_element_state_t *p_elem_state = NULL;
165
166 if (!p_model || !p_model->user_data)
167 {
168 GENIE_LOG_ERR("param err");
169 return;
170 }
171
172 memset(&msg, 0, sizeof(sig_model_msg));
173 msg.opcode = OP_GENERIC_LIGHT_CTL_GET;
174 if (p_buf != NULL)
175 {
176 msg.len = p_buf->len;
177 msg.data = (u8_t *)p_buf->data;
178 }
179 genie_transport_src_addr_set(p_ctx->addr);
180
181 p_elem_state = (sig_model_element_state_t *)p_model->user_data;
182 msg.element_id = p_elem_state->element_id;
183
184 sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
185
186 _ctl_status(p_model, p_ctx, 0);
187 }
188
_ctl_set(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)189 static void _ctl_set(struct bt_mesh_model *p_model,
190 struct bt_mesh_msg_ctx *p_ctx,
191 struct net_buf_simple *p_buf)
192 {
193 E_MESH_ERROR_TYPE ret = 0;
194 sig_model_msg msg;
195 sig_model_element_state_t *p_elem_state = NULL;
196
197 if (!p_model || !p_model->user_data)
198 {
199 GENIE_LOG_ERR("param err");
200 return;
201 }
202
203 memset(&msg, 0, sizeof(sig_model_msg));
204 msg.opcode = OP_GENERIC_LIGHT_CTL_SET;
205 if (p_buf != NULL)
206 {
207 msg.len = p_buf->len;
208 msg.data = (u8_t *)p_buf->data;
209 }
210 genie_transport_src_addr_set(p_ctx->addr);
211
212 p_elem_state = (sig_model_element_state_t *)p_model->user_data;
213 msg.element_id = p_elem_state->element_id;
214
215 sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
216
217 ret = _ctl_analyze(p_model, p_ctx->addr, p_buf);
218
219 BT_DBG("ret %d", ret);
220
221 if (ret == MESH_SUCCESS || ret == MESH_TID_REPEAT)
222 {
223 _ctl_status(p_model, p_ctx, 1);
224 if (ret == MESH_SUCCESS)
225 {
226 sig_model_event(SIG_MODEL_EVT_ANALYZE_MSG, (sig_model_element_state_t *)p_model->user_data);
227 }
228 }
229 }
230
_ctl_set_unack(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf)231 static void _ctl_set_unack(struct bt_mesh_model *p_model,
232 struct bt_mesh_msg_ctx *p_ctx,
233 struct net_buf_simple *p_buf)
234 {
235 BT_DBG("");
236 E_MESH_ERROR_TYPE ret = 0;
237 sig_model_msg msg;
238 sig_model_element_state_t *p_elem_state = NULL;
239
240 if (!p_model || !p_model->user_data)
241 {
242 GENIE_LOG_ERR("param err");
243 return;
244 }
245
246 memset(&msg, 0, sizeof(sig_model_msg));
247 msg.opcode = OP_GENERIC_LIGHT_CTL_SET_UNACK;
248 if (p_buf != NULL)
249 {
250 msg.len = p_buf->len;
251 msg.data = (u8_t *)p_buf->data;
252 }
253 genie_transport_src_addr_set(p_ctx->addr);
254
255 p_elem_state = (sig_model_element_state_t *)p_model->user_data;
256 msg.element_id = p_elem_state->element_id;
257
258 sig_model_event(SIG_MODEL_EVT_GENERIC_MESG, (void *)&msg);
259
260 ret = _ctl_analyze(p_model, p_ctx->addr, p_buf);
261
262 if (ret == MESH_SUCCESS)
263 {
264 sig_model_event(SIG_MODEL_EVT_ANALYZE_MSG, (sig_model_element_state_t *)p_model->user_data);
265 }
266 }
267
268 const struct bt_mesh_model_op g_ctl_srv_op[LIGHT_CTL_OPCODE_NUM] = {
269 {OP_GENERIC_LIGHT_CTL_GET, 0, _ctl_get},
270 {OP_GENERIC_LIGHT_CTL_SET, 7, _ctl_set},
271 {OP_GENERIC_LIGHT_CTL_SET_UNACK, 7, _ctl_set_unack},
272 BT_MESH_MODEL_OP_END,
273 };
274 #endif
275
sig_model_light_ctl_update_by_onoff(sig_model_element_state_t * p_elem)276 void sig_model_light_ctl_update_by_onoff(sig_model_element_state_t *p_elem)
277 {
278 sig_model_state_t *p_state = &p_elem->state;
279
280 BT_DBG("onoff cur(%d) tar(%d)", p_state->onoff[TYPE_PRESENT], p_state->onoff[TYPE_TARGET]);
281
282 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
283 if (p_state->onoff[TYPE_PRESENT] == 0 && p_state->onoff[TYPE_TARGET] == 1)
284 {
285 //turn on, check temperature
286 BT_DBG("color_temperature cur(%d) tar(%d)", p_state->color_temperature[TYPE_PRESENT], p_state->color_temperature[TYPE_TARGET]);
287 if (p_state->color_temperature[TYPE_PRESENT] != p_state->color_temperature[TYPE_TARGET])
288 {
289 if (p_elem->powerup.last_color_temperature)
290 {
291 p_state->color_temperature[TYPE_TARGET] = p_elem->powerup.last_color_temperature;
292 }
293 else
294 {
295 p_state->color_temperature[TYPE_TARGET] = COLOR_TEMPERATURE_DEFAULT;
296 }
297
298 sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_CTL);
299 }
300 }
301 #endif
302
303 BT_DBG("color_temperature cur(%04x) tar(%04x)", p_state->color_temperature[TYPE_PRESENT], p_state->color_temperature[TYPE_TARGET]);
304 }
305