1 /*
2  * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <ctype.h>
8 //#include <aos/aos.h>
9 #include <aos/kernel.h>
10 
11 #include <misc/printk.h>
12 #include <misc/byteorder.h>
13 //#include <hal/soc/gpio.h>
14 //#include <hal/soc/pwm.h>
15 
16 #include <bluetooth/bluetooth.h>
17 //#include <soc.h>
18 #include <api/mesh.h>
19 #include "common/log.h"
20 #include "genie_service.h"
21 
22 #ifdef CONFIG_MESH_MODEL_TRANS
sig_model_transition_timer_stop(sig_model_element_state_t * p_elem)23 void sig_model_transition_timer_stop(sig_model_element_state_t *p_elem)
24 {
25     k_timer_stop(&p_elem->state.delay_timer);
26     k_timer_stop(&p_elem->state.trans_timer);
27 }
28 
sig_model_transition_state_reset(sig_model_element_state_t * p_elem)29 void sig_model_transition_state_reset(sig_model_element_state_t *p_elem)
30 {
31     p_elem->state.trans = 0;
32     p_elem->state.trans_start_time = 0;
33     p_elem->state.trans_end_time = 0;
34 }
35 
36 #define DELTA_ACTUAL_MIN 655
37 #define DELTA_TEMP_MIN 192
38 
sig_model_transition_update(sig_model_element_state_t * p_elem)39 uint8_t sig_model_transition_update(sig_model_element_state_t *p_elem)
40 {
41     uint8_t cycle = 0;
42     uint16_t delta = 0;
43     bt_u32_t cur_time = k_uptime_get();
44     sig_model_state_t *p_state = &p_elem->state;
45 
46     //stop cycle when timeout
47     if (cur_time <= p_state->trans_end_time - SIG_MODEL_TRANSITION_INTERVAL)
48     {
49 #if defined(CONFIG_MESH_MODEL_LIGHTNESS_SRV) || defined(CONFIG_MESH_MODEL_CTL_SRV)
50         uint16_t step = (p_state->trans_end_time - cur_time) / SIG_MODEL_TRANSITION_INTERVAL;
51 #endif
52 
53 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
54         if (p_state->onoff[TYPE_PRESENT] != p_state->onoff[TYPE_TARGET])
55         {
56             p_state->onoff[TYPE_PRESENT] = p_state->onoff[TYPE_TARGET];
57             sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_ONOFF);
58         }
59 #endif
60 
61 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
62         if (p_state->lightness[TYPE_PRESENT] != p_state->lightness[TYPE_TARGET])
63         {
64             if (p_state->lightness[TYPE_TARGET] > p_state->lightness[TYPE_PRESENT])
65             {
66                 delta = (p_state->lightness[TYPE_TARGET] - p_state->lightness[TYPE_PRESENT]) / step;
67                 delta = delta > DELTA_ACTUAL_MIN ? delta : DELTA_ACTUAL_MIN;
68                 if (LIGHTNESS_MAX_VALUE - p_state->lightness[TYPE_PRESENT] < delta ||
69                     p_state->lightness[TYPE_TARGET] - p_state->lightness[TYPE_PRESENT] < delta)
70                 {
71                     p_state->lightness[TYPE_PRESENT] = p_state->lightness[TYPE_TARGET];
72                     sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_LIGHTNESS);
73                 }
74                 else
75                 {
76                     p_state->lightness[TYPE_PRESENT] += delta;
77                     if (p_state->lightness[TYPE_PRESENT] == p_state->lightness[TYPE_TARGET])
78                     {
79                         sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_LIGHTNESS);
80                     }
81                 }
82             }
83             else
84             {
85                 delta = (p_state->lightness[TYPE_PRESENT] - p_state->lightness[TYPE_TARGET]) / step;
86                 delta = delta > DELTA_ACTUAL_MIN ? delta : DELTA_ACTUAL_MIN;
87                 if (p_state->lightness[TYPE_PRESENT] < delta ||
88                     p_state->lightness[TYPE_PRESENT] - delta < p_state->lightness[TYPE_TARGET])
89                 {
90                     p_state->lightness[TYPE_PRESENT] = p_state->lightness[TYPE_TARGET];
91                     sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_LIGHTNESS);
92                 }
93                 else
94                 {
95                     p_state->lightness[TYPE_PRESENT] -= delta;
96                     if (p_state->lightness[TYPE_PRESENT] == p_state->lightness[TYPE_TARGET])
97                     {
98                         sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_LIGHTNESS);
99                     }
100                 }
101             }
102             cycle = 1;
103         }
104 #endif
105 #ifdef CONFIG_MESH_MODEL_CTL_SRV
106         if (p_state->color_temperature[TYPE_PRESENT] != p_state->color_temperature[TYPE_TARGET])
107         {
108             if (p_state->color_temperature[TYPE_TARGET] > p_state->color_temperature[TYPE_PRESENT])
109             {
110                 delta = (p_state->color_temperature[TYPE_TARGET] - p_state->color_temperature[TYPE_PRESENT]) / step;
111                 delta = delta > DELTA_TEMP_MIN ? delta : DELTA_TEMP_MIN;
112                 if (COLOR_TEMPERATURE_MAX - p_state->color_temperature[TYPE_PRESENT] < delta ||
113                     p_state->color_temperature[TYPE_TARGET] - p_state->color_temperature[TYPE_PRESENT] < delta)
114                 {
115                     p_state->color_temperature[TYPE_PRESENT] = p_state->color_temperature[TYPE_TARGET];
116                     sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_CTL);
117                 }
118                 else
119                 {
120                     p_state->color_temperature[TYPE_PRESENT] += delta;
121                     if (p_state->color_temperature[TYPE_PRESENT] == p_state->color_temperature[TYPE_TARGET])
122                     {
123                         sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_CTL);
124                     }
125                 }
126                 delta += p_state->color_temperature[TYPE_PRESENT];
127                 p_state->color_temperature[TYPE_PRESENT] = delta > p_state->color_temperature[TYPE_TARGET] ? p_state->color_temperature[TYPE_TARGET] : delta;
128             }
129             else
130             {
131                 delta = (p_state->color_temperature[TYPE_PRESENT] - p_state->color_temperature[TYPE_TARGET]) / step;
132                 delta = delta > DELTA_TEMP_MIN ? delta : DELTA_TEMP_MIN;
133                 if (p_state->color_temperature[TYPE_PRESENT] < delta + COLOR_TEMPERATURE_MIN ||
134                     p_state->color_temperature[TYPE_PRESENT] - delta < p_state->color_temperature[TYPE_TARGET])
135                 {
136                     p_state->color_temperature[TYPE_PRESENT] = p_state->color_temperature[TYPE_TARGET];
137                     sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_CTL);
138                 }
139                 else
140                 {
141                     p_state->color_temperature[TYPE_PRESENT] -= delta;
142                     if (p_state->color_temperature[TYPE_PRESENT] == p_state->color_temperature[TYPE_TARGET])
143                     {
144                         sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_CTL);
145                     }
146                 }
147             }
148             cycle = 1;
149         }
150 #endif
151     }
152 #if 0
153     printf("next: %d->%d|%02x->%02x|%02x->%02x\n", p_state->onoff[TYPE_PRESENT], p_state->onoff[TYPE_TARGET],
154            p_state->lightness[TYPE_PRESENT], p_state->lightness[TYPE_TARGET], p_state->color_temperature[TYPE_PRESENT], p_state->color_temperature[TYPE_TARGET]);
155 #endif
156 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
157     if (p_state->onoff[TYPE_PRESENT] == p_state->onoff[TYPE_TARGET])
158 #endif
159 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
160         if (p_state->lightness[TYPE_PRESENT] == p_state->lightness[TYPE_TARGET])
161 #endif
162 #ifdef CONFIG_MESH_MODEL_CTL_SRV
163             if (p_state->color_temperature[TYPE_PRESENT] == p_state->color_temperature[TYPE_TARGET])
164 #endif
165                 cycle = 0;
166 
167     //BT_DBG("cycle %d", cycle);
168     if (cycle == 0)
169     {
170 #ifdef CONFIG_MESH_MODEL_GEN_ONOFF_SRV
171 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
172         if (p_state->lightness[TYPE_TARGET] == 0)
173         {
174             p_state->onoff[TYPE_TARGET] = 0;
175         }
176 #endif
177         if (p_state->onoff[TYPE_PRESENT] != p_state->onoff[TYPE_TARGET])
178         {
179             p_state->onoff[TYPE_PRESENT] = p_state->onoff[TYPE_TARGET];
180             sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_ONOFF);
181         }
182         //BT_DBG("onoff %d->%d", p_state->onoff[TYPE_PRESENT], p_state->onoff[TYPE_TARGET]);
183 #endif
184 #ifdef CONFIG_MESH_MODEL_LIGHTNESS_SRV
185         if (p_state->lightness[TYPE_PRESENT] != p_state->lightness[TYPE_TARGET])
186         {
187             p_state->lightness[TYPE_PRESENT] = p_state->lightness[TYPE_TARGET];
188             sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_LIGHTNESS);
189         }
190         //BT_DBG("lightness %02x->%02x", p_state->lightness[TYPE_PRESENT], p_state->lightness[TYPE_TARGET]);
191 #endif
192 #ifdef CONFIG_MESH_MODEL_CTL_SRV
193         if (p_state->color_temperature[TYPE_PRESENT] != p_state->color_temperature[TYPE_TARGET])
194         {
195             p_state->color_temperature[TYPE_PRESENT] = p_state->color_temperature[TYPE_TARGET];
196             sig_model_event_set_indicate(SIG_MODEL_INDICATE_GEN_CTL);
197         }
198         //BT_DBG("color_temperature %02x->%02x", p_state->color_temperature[TYPE_PRESENT], p_state->color_temperature[TYPE_TARGET]);
199 #endif
200         p_state->trans = 0;
201     }
202 
203     return cycle;
204 }
205 #endif
206 
207 #ifdef CONFIG_MESH_MODEL_TRANS
208 bt_u32_t TRANS_TIMES[] = {TRANSITION_TIME_UNIT_1, TRANSITION_TIME_UNIT_2, TRANSITION_TIME_UNIT_3, TRANSITION_TIME_UNIT_4};
209 
_get_transition_byte(bt_u32_t time)210 static uint8_t _get_transition_byte(bt_u32_t time)
211 {
212     if (time > TRANS_TIMES[3] * TRANSITION_TIME_VALUE_MAX)
213     {
214         return 0;
215     }
216     else if (time > TRANS_TIMES[2] * TRANSITION_TIME_VALUE_MAX)
217     {
218         return (time / TRANS_TIMES[3]) | TRANSITION_TIME_UNIT_BIT(3);
219     }
220     else if (time > TRANS_TIMES[1] * TRANSITION_TIME_VALUE_MAX)
221     {
222         return (time / TRANS_TIMES[2]) | TRANSITION_TIME_UNIT_BIT(2);
223     }
224     else if (time > TRANS_TIMES[0] * TRANSITION_TIME_VALUE_MAX)
225     {
226         return (time / TRANS_TIMES[1]) | TRANSITION_TIME_UNIT_BIT(1);
227     }
228     else
229     {
230         return (time / TRANS_TIMES[0]);
231     }
232 }
233 
234 //unit is 1ms
sig_model_transition_get_transition_time(uint8_t byte)235 bt_u32_t sig_model_transition_get_transition_time(uint8_t byte)
236 {
237     if ((byte & TRANSITION_TIME_VALUE_MASK) == TRANSITION_TIME_VALUE_INVALID)
238     {
239         MODEL_E("%s ERROR, invalid 0x%02X!!!\n", __func__, byte);
240         return TRANSITION_TIME_VALUE_INVALID;
241     }
242 
243     return (byte & TRANSITION_TIME_VALUE_MASK) * TRANS_TIMES[byte >> 6];
244 }
245 
sig_model_transition_get_remain_time_byte(sig_model_state_t * p_state,bool is_ack)246 uint8_t sig_model_transition_get_remain_time_byte(sig_model_state_t *p_state, bool is_ack)
247 {
248     uint8_t remain_time_byte = p_state->trans;
249     int64_t cur_time = k_uptime_get();
250     int64_t passed_time = 0;
251     bt_u32_t trans_duration = 0;
252 
253     if (!is_ack && p_state->trans_start_time < cur_time)
254     {
255         passed_time -= p_state->trans_start_time;
256         trans_duration = sig_model_transition_get_transition_time(p_state->trans);
257 
258         if (trans_duration > passed_time)
259         {
260             remain_time_byte = _get_transition_byte(trans_duration - passed_time);
261         }
262         else
263         {
264             remain_time_byte = TRANSITION_TIME_VALUE_MIN;
265         }
266     }
267 
268     return remain_time_byte;
269 }
270 #endif
271