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