1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5 #include "common/log.h"
6 #include "mesh.h"
7
8 #include <atomic.h>
9 #include "genie_service.h"
10
11 static ATOMIC_DEFINE(indicate_flags, SIG_MODEL_INDICATE_FLAGS);
12
sig_model_event_handle_delay_start(sig_model_element_state_t * p_elem)13 static sig_model_event_e sig_model_event_handle_delay_start(sig_model_element_state_t *p_elem)
14 {
15 #ifdef CONFIG_MESH_MODEL_TRANS
16 sig_model_transition_timer_stop(p_elem);
17 #endif
18
19 k_timer_start(&p_elem->state.delay_timer, p_elem->state.delay * 5);
20
21 return SIG_MODEL_EVT_NONE;
22 }
23
sig_model_event_handle_delay_end(sig_model_element_state_t * p_elem)24 static sig_model_event_e sig_model_event_handle_delay_end(sig_model_element_state_t *p_elem)
25 {
26 #ifdef CONFIG_MESH_MODEL_TRANS
27 bt_u32_t cur_time = k_uptime_get();
28 #endif
29
30 p_elem->state.delay = 0;
31
32 #ifdef CONFIG_MESH_MODEL_TRANS
33 if (p_elem->state.trans == 0 || cur_time >= p_elem->state.trans_end_time)
34 {
35 sig_model_transition_state_reset(p_elem);
36 return SIG_MODEL_EVT_ACTION_DONE;
37 }
38 else
39 {
40 return SIG_MODEL_EVT_TRANS_START;
41 }
42 #else
43 return SIG_MODEL_EVT_ACTION_DONE;
44 #endif
45 }
46
47 #ifdef CONFIG_MESH_MODEL_TRANS
sig_model_event_handle_trans_start(sig_model_element_state_t * p_elem)48 static sig_model_event_e sig_model_event_handle_trans_start(sig_model_element_state_t *p_elem)
49 {
50 bt_u32_t cur_time = k_uptime_get();
51
52 sig_model_transition_timer_stop(p_elem);
53
54 //check time
55 if (cur_time >= p_elem->state.trans_end_time - SIG_MODEL_TRANSITION_INTERVAL)
56 {
57 return SIG_MODEL_EVT_TRANS_END;
58 }
59 else
60 {
61 //start cycle
62 k_timer_start(&p_elem->state.trans_timer, SIG_MODEL_TRANSITION_INTERVAL);
63 BT_DBG("start trans %p", &p_elem->state.trans_timer);
64
65 return SIG_MODEL_EVT_NONE;
66 }
67 }
68
sig_model_event_handle_trans_cycle(sig_model_element_state_t * p_elem)69 static sig_model_event_e sig_model_event_handle_trans_cycle(sig_model_element_state_t *p_elem)
70 {
71 if (sig_model_transition_update(p_elem) == 0)
72 {
73 p_elem->state.trans = 0;
74 }
75
76 return SIG_MODEL_EVT_NONE;
77 }
78
sig_model_event_handle_trans_end(sig_model_element_state_t * p_elem)79 static sig_model_event_e sig_model_event_handle_trans_end(sig_model_element_state_t *p_elem)
80 {
81 //clear paras
82 sig_model_transition_state_reset(p_elem);
83 //action done
84 return SIG_MODEL_EVT_ACTION_DONE;
85 }
86 #endif
87
sig_model_event_handle_analyze_msg(sig_model_element_state_t * p_elem)88 static sig_model_event_e sig_model_event_handle_analyze_msg(sig_model_element_state_t *p_elem)
89 {
90 #ifdef CONFIG_MESH_MODEL_TRANS
91 if (p_elem->state.trans || p_elem->state.delay)
92 {
93 if (p_elem->state.delay)
94 {
95 return SIG_MODEL_EVT_DELAY_START;
96 }
97 else
98 {
99 return SIG_MODEL_EVT_TRANS_START;
100 }
101 }
102 #endif
103
104 return SIG_MODEL_EVT_ACTION_DONE;
105 }
106
sig_model_handle_action_done(sig_model_element_state_t * p_elem)107 static sig_model_event_e sig_model_handle_action_done(sig_model_element_state_t *p_elem)
108 {
109 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
110 BT_DBG("onoff cur(%d) tar(%d)", p_elem->state.onoff[TYPE_PRESENT], p_elem->state.onoff[TYPE_TARGET]);
111
112 if (p_elem->state.onoff[TYPE_PRESENT] != p_elem->state.onoff[TYPE_TARGET])
113 {
114 p_elem->state.onoff[TYPE_PRESENT] = p_elem->state.onoff[TYPE_TARGET];
115 atomic_set_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_ONOFF);
116 }
117 #endif
118
119 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
120 BT_DBG("lightness cur(%04x) tar(%04x)", p_elem->state.lightness[TYPE_PRESENT], p_elem->state.lightness[TYPE_TARGET]);
121
122 if (p_elem->state.lightness[TYPE_PRESENT] != p_elem->state.lightness[TYPE_TARGET])
123 {
124 p_elem->state.lightness[TYPE_PRESENT] = p_elem->state.lightness[TYPE_TARGET];
125 atomic_set_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_LIGHTNESS);
126 }
127 #endif
128
129 #ifdef CONFIG_MESH_MODEL_CTL_SRV
130 BT_DBG("color_temperature cur(%04x) tar(%04x)", p_elem->state.color_temperature[TYPE_PRESENT], p_elem->state.color_temperature[TYPE_TARGET]);
131
132 if (p_elem->state.color_temperature[TYPE_PRESENT] != p_elem->state.color_temperature[TYPE_TARGET])
133 {
134 p_elem->state.color_temperature[TYPE_PRESENT] = p_elem->state.color_temperature[TYPE_TARGET];
135 atomic_set_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_CTL);
136 }
137 #endif
138
139 #ifdef CONFIG_MESH_MODEL_SCENE_SRV
140 BT_DBG("scene cur(%04x) tar(%04x)", p_elem->state.scene[TYPE_PRESENT], p_elem->state.scene[TYPE_TARGET]);
141
142 if (p_elem->state.scene[TYPE_PRESENT] != p_elem->state.scene[TYPE_TARGET])
143 {
144 p_elem->state.scene[TYPE_PRESENT] = p_elem->state.scene[TYPE_TARGET];
145 atomic_set_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_SCENE);
146 }
147 #endif
148
149 if (bt_mesh_is_provisioned())
150 {
151 return SIG_MODEL_EVT_INDICATE;
152 }
153
154 return SIG_MODEL_EVT_NONE;
155 }
156
sig_model_handle_indicate(sig_model_element_state_t * p_elem)157 static sig_model_event_e sig_model_handle_indicate(sig_model_element_state_t *p_elem)
158 {
159 uint8_t payload[SIG_MODEL_INDICATE_PAYLOAD_MAX_LEN];
160 uint8_t payload_len = 0;
161 genie_transport_model_param_t transport_model_param = {0};
162
163 if (p_elem == NULL)
164 {
165 return SIG_MODEL_EVT_NONE;
166 }
167
168 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
169 if (atomic_test_and_clear_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_ONOFF))
170 {
171 payload[payload_len++] = ATTR_TYPE_GENERIC_ONOFF & 0xff;
172 payload[payload_len++] = (ATTR_TYPE_GENERIC_ONOFF >> 8) & 0xff;
173 payload[payload_len++] = p_elem->state.onoff[TYPE_PRESENT];
174 }
175 #endif
176 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
177 if (atomic_test_and_clear_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_LIGHTNESS))
178 {
179 payload[payload_len++] = ATTR_TYPE_LIGHTNESS & 0xff;
180 payload[payload_len++] = (ATTR_TYPE_LIGHTNESS >> 8) & 0xff;
181 payload[payload_len++] = p_elem->state.lightness[TYPE_PRESENT] & 0xff;
182 payload[payload_len++] = (p_elem->state.lightness[TYPE_PRESENT] >> 8) & 0xff;
183 }
184 #endif
185 #ifdef CONFIG_MESH_MODEL_CTL_SRV
186 if (atomic_test_and_clear_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_CTL))
187 {
188 payload[payload_len++] = ATTR_TYPE_COLOR_TEMPERATURE & 0xff;
189 payload[payload_len++] = (ATTR_TYPE_COLOR_TEMPERATURE >> 8) & 0xff;
190 payload[payload_len++] = p_elem->state.color_temperature[TYPE_PRESENT] & 0xff;
191 payload[payload_len++] = (p_elem->state.color_temperature[TYPE_PRESENT] >> 8) & 0xff;
192 }
193 #endif
194 #ifdef CONFIG_MESH_MODEL_SCENE_SRV
195 if (atomic_test_and_clear_bit(indicate_flags, SIG_MODEL_INDICATE_GEN_SCENE))
196 {
197 payload[payload_len++] = ATTR_TYPE_SENCE & 0xff;
198 payload[payload_len++] = (ATTR_TYPE_SENCE >> 8) & 0xff;
199 payload[payload_len++] = p_elem->state.scene[TYPE_PRESENT] & 0xff;
200 payload[payload_len++] = (p_elem->state.scene[TYPE_PRESENT] >> 8) & 0xff;
201 }
202 #endif
203
204 if (payload_len > 0)
205 {
206 memset(&transport_model_param, 0, sizeof(genie_transport_model_param_t));
207 transport_model_param.opid = VENDOR_OP_ATTR_INDICATE;
208 transport_model_param.data = payload;
209 transport_model_param.len = MIN(SIG_MODEL_INDICATE_PAYLOAD_MAX_LEN, payload_len);
210 transport_model_param.p_elem = bt_mesh_elem_find_by_id(p_elem->element_id);
211 transport_model_param.retry_period = GENIE_TRANSPORT_EACH_PDU_TIMEOUT * genie_transport_get_seg_count(transport_model_param.len);
212 transport_model_param.retry = GENIE_TRANSPORT_DEFAULT_RETRY_COUNT;
213
214 genie_transport_send_model(&transport_model_param);
215 }
216
217 return SIG_MODEL_EVT_NONE;
218 }
219
sig_model_event_set_indicate(int indicate)220 void sig_model_event_set_indicate(int indicate)
221 {
222 atomic_set_bit(indicate_flags, indicate);
223 }
224
sig_model_event(sig_model_event_e event,void * p_arg)225 void sig_model_event(sig_model_event_e event, void *p_arg)
226 {
227 sig_model_event_e next_event = SIG_MODEL_EVT_NONE;
228
229 if (event != SIG_MODEL_EVT_NONE)
230 {
231 #ifdef CONFIG_MESH_MODEL_TRANS
232 if (event != SIG_MODEL_EVT_TRANS_CYCLE)
233 {
234 GENIE_LOG_INFO("SigE:%d\r\n", event);
235 }
236 #else
237 GENIE_LOG_INFO("SigE:%d\r\n", event);
238 #endif
239 }
240
241 switch (event)
242 {
243 case SIG_MODEL_EVT_INDICATE:
244 {
245 next_event = sig_model_handle_indicate((sig_model_element_state_t *)p_arg);
246 }
247 break;
248 case SIG_MODEL_EVT_ACTION_DONE:
249 {
250 next_event = sig_model_handle_action_done((sig_model_element_state_t *)p_arg);
251 }
252 break;
253 case SIG_MODEL_EVT_ANALYZE_MSG:
254 {
255 next_event = sig_model_event_handle_analyze_msg((sig_model_element_state_t *)p_arg);
256 }
257 break;
258
259 case SIG_MODEL_EVT_DELAY_START:
260 {
261 next_event = sig_model_event_handle_delay_start((sig_model_element_state_t *)p_arg);
262 }
263 break;
264 case SIG_MODEL_EVT_DELAY_END:
265 {
266 next_event = sig_model_event_handle_delay_end((sig_model_element_state_t *)p_arg);
267 }
268 break;
269 #ifdef CONFIG_MESH_MODEL_TRANS
270 case SIG_MODEL_EVT_TRANS_START:
271 {
272 next_event = sig_model_event_handle_trans_start((sig_model_element_state_t *)p_arg);
273 }
274 break;
275 case SIG_MODEL_EVT_TRANS_CYCLE:
276 {
277 next_event = sig_model_event_handle_trans_cycle((sig_model_element_state_t *)p_arg);
278 }
279 break;
280 case SIG_MODEL_EVT_TRANS_END:
281 {
282 next_event = sig_model_event_handle_trans_end((sig_model_element_state_t *)p_arg);
283 }
284 break;
285 #endif
286 case SIG_MODEL_EVT_GENERIC_MESG:
287 {
288 sig_model_msg *p_msg = (sig_model_msg *)p_arg;
289 genie_down_msg(GENIE_DOWN_MESG_SIG_TYPE, p_msg->opcode, p_arg);
290 }
291 break;
292 default:
293 break;
294 }
295
296 if (next_event != SIG_MODEL_EVT_NONE)
297 {
298 sig_model_event(next_event, p_arg);
299 }
300
301 if (event == SIG_MODEL_EVT_ACTION_DONE)
302 {
303 genie_event(GENIE_EVT_USER_ACTION_DONE, p_arg);
304 }
305 #ifdef CONFIG_MESH_MODEL_TRANS
306 if (event == SIG_MODEL_EVT_TRANS_CYCLE)
307 {
308 genie_event(GENIE_EVT_USER_TRANS_CYCLE, p_arg);
309 }
310 #endif
311 }
312