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