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