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