1 /*
2  * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3  */
4 
5 #include <api/mesh.h>
6 #include <mesh_model.h>
7 
8 #define TAG "MESH BIND"
9 
10 typedef u16_t (*BIND_OPS_HANDLER)(S_ELEM_STATE *p_elem, u8_t type);
11 
12 u16_t model_bind_operation(BIND_OPERATION_ID id, S_ELEM_STATE *p_elem, u8_t type);
13 
14 
15 static u16_t _gen_onoff_operation(S_ELEM_STATE *p_elem, u8_t type);
16 static u16_t _gen_onpowerup_operation(S_ELEM_STATE *p_elem, u8_t type);
17 
18 static u16_t _gen_level_operation(S_ELEM_STATE *p_elem, u8_t type);
19 static u16_t _gen_power_actual_operation(S_ELEM_STATE *p_elem, u8_t type);
20 static u16_t _gen_lightness_linear_operation(S_ELEM_STATE *p_elem, u8_t type);
21 static u16_t _gen_lightness_actual_operation(S_ELEM_STATE *p_elem, u8_t type);
22 static u16_t _gen_power_range_operation(S_ELEM_STATE *p_elem, u8_t type);
23 
24 
25 BIND_OPS_HANDLER bind_handler[B_OPS_END_ID] = {
26     /* !!!START!!! --- Don't add new ID before this one */
27     //B_OPS_START_ID = -1,
28 
29     /* Generic OnOff */
30     _gen_onoff_operation,//B_GEN_ONOFF_ID = 0,
31 
32     /* Generic Level */
33     NULL,//B_GEN_LEVEL_ID,
34     NULL,//B_GEN_DELTA_ID,
35     NULL,//B_GEN_MOVE_ID,
36 
37     /* Generic Default Transition Time */
38     NULL,//B_GEN_DFT_TRANS_TIME_ID,
39 
40     /* Generic Power OnOff */
41     _gen_onpowerup_operation,//B_GEN_ON_PWR_UP_ID,
42 
43     /* Generic Power Level */
44     _gen_power_actual_operation,//B_GEN_PWR_ACTUAL_ID,
45     NULL,//B_GEN_PWR_LAST_ID,
46     NULL,//B_GEN_PWR_DFT_ID,
47     _gen_power_range_operation,//B_GEN_PWR_RANGE_ID,
48     /*lightness*/
49     _gen_lightness_linear_operation,//B_GEN_LIGHTNESS_LINEAR_ID
50     _gen_lightness_actual_operation,//B_GEN_LIGHTNESS_ACTUAL_ID
51     /* !!!END!!! --- Don't add new ID after this one */
52     NULL
53 };
54 
model_bind_operation(BIND_OPERATION_ID id,S_ELEM_STATE * p_elem,u8_t type)55 u16_t model_bind_operation(BIND_OPERATION_ID id, S_ELEM_STATE *p_elem, u8_t type)
56 {
57     BIND_OPS_HANDLER p_func = NULL;
58 
59     LOGD(TAG, "bind ops - id: %d, ele:%p\n", id, p_elem);
60 
61     if (id <= B_OPS_START_ID || id >= B_OPS_END_ID || !p_elem) {
62         LOGE(TAG, "invalid args, ignore\n");
63         return -1;
64     }
65 
66 #if 1
67     p_func = bind_handler[id];
68     LOGD(TAG, "p_func:%p\n", p_func);
69 
70     return p_func ? p_func(p_elem, type) : -1;
71 #else
72     {
73         u8_t i = 0;
74 
75         for (i = 0; i < sizeof(bind_handler) / sizeof(bind_handler[0]); i++) {
76             func = bind_handler[i];
77 
78             if (func) {
79                 func(i, p_elem, type);
80             } else {
81                 LOGD(TAG, "id:%d, func is NULL\n", i);
82             }
83         }
84 
85         return 0;
86     }
87 #endif
88 }
89 
90 /*
91 static u16_t _constrain_actual(S_ELEM_STATE *p_elem, u16_t var)
92 {
93 
94     S_MESH_STATE *p_state = &p_elem->state;
95 
96     if (var > 0 && var < p_state->power_range.range_min) {
97         var = p_state->power_range.range_min;
98     } else if (var > p_state->power_range.range_max) {
99         var =  p_state->power_range.range_max;
100     }
101     return var;
102 }*/
103 
104 /*
105 static u16_t _constrain_lightness(S_ELEM_STATE *p_elem, u16_t var)
106 {
107 
108     S_MESH_STATE *p_state = &p_elem->state;
109     S_MESH_POWERUP *p_powerup = &p_elem->powerup;
110     if (var > 0 && var < p_powerup->lightness_range.range_min) {
111         var = p_powerup->lightness_range.range_min;
112     } else if (var > p_powerup->lightness_range.range_max) {
113         var =  p_powerup->lightness_range.range_max;
114     }
115     return var;
116 }
117 
118 static u16_t _gen_onoff_operation(S_ELEM_STATE *p_elem, u8_t type) {
119     S_MESH_STATE *p_state = &p_elem->state;
120     S_MESH_POWERUP *p_power_up = &p_elem->powerup;
121     u16_t actual = 0;
122 
123     if (p_state->onoff[T_CUR]){
124         if(!p_power_up->lightness_default){
125          p_state->lightness_actual[T_CUR] = p_power_up->lightness_last;
126         }else{
127          p_state->lightness_actual[T_CUR] = p_power_up->lightness_default;
128         }
129     }
130     else{
131       p_state->actual[T_CUR] = p_state->actual[T_TAR] = actual;
132       p_state->lightness_actual[T_CUR] = 0;
133     }
134 
135     BT_INFO("onoff[T_TAR]:%d, onoff[T_CUR]:%d, actual[TAR]:0x%02x", p_state->onoff[T_TAR], p_state->onoff[T_CUR], p_state->actual[T_TAR]);
136 
137     return 0;
138 }
139 
140 static u16_t _gen_level_operation(S_ELEM_STATE *p_elem, u8_t type) {
141     LOGD(TAG, "");
142     S_MESH_STATE *p_state = &p_elem->state;
143     p_state->actual[T_TAR] = p_state->level[T_CUR] + 32768;
144     p_state->lightness_actual[T_TAR] = p_state->level[T_CUR] + 32768;
145     return 0;
146 }
147 
148 /*
149 static u16_t _gen_onpowerup_operation(S_ELEM_STATE *p_elem, u8_t type) {
150     S_MESH_STATE *p_state = &p_elem->state;
151     S_MESH_POWERUP *p_powerUp = &p_elem->powerup;
152     //Ethan: not supported, give 1  for the moment, don't need to adjust target actual here, will only take affect when next power on cycle
153 
154     if(p_state->powerUp_status == 0x00){
155       p_state->actual[T_CUR] = 0;
156       p_state->lightness_actual[T_CUR] = 0;
157     }else if(p_state->powerUp_status == 0x01 ){
158           if(p_state->power_default != 0x00){
159              p_state->actual[T_CUR] = p_state->power_default;
160           }else{
161               p_state->actual[T_CUR] = p_state->power_last;
162           }
163           if(p_powerUp->lightness_default != 0x00){
164              p_state->lightness_actual[T_CUR] = p_powerUp->lightness_default;
165           }else{
166              p_state->lightness_actual[T_CUR] = p_powerUp->lightness_last;
167           }
168     }else if(p_state->powerUp_status == 0x02){
169             p_state->actual[T_CUR] = p_state->power_last;
170             p_state->lightness_actual[T_CUR] = p_powerUp->lightness_last;
171     }
172 
173     BT_INFO("onpowerup ops, actual[TAR]:0x%02x\n", p_state->actual[type]);
174 
175     return 0;
176 }*/
177 
178 /*
179 static u16_t _gen_power_actual_operation(S_ELEM_STATE *p_elem, u8_t type)
180 {
181   LOGD(TAG, "");
182   S_MESH_STATE *p_state = &p_elem->state;
183   p_state->actual[type] = _constrain_actual(p_elem , p_state->actual[type]);
184   p_state->level[T_CUR] = p_state->actual - 32768;
185   if(p_state->actual == 0X0000){
186     p_state->onoff[T_TAR] = 0X00;
187   }else{
188     p_state->onoff[T_TAR] = 0X01;
189   }
190   p_state->power_last = p_state->actual[type];
191   return 0;
192 }*/
193 
194 /*
195 static u16_t _gen_power_range_operation(S_ELEM_STATE *p_elem, u8_t type)
196 {
197  LOGD(TAG, "");
198 
199 }
200 
201 static u16_t _gen_lightness_linear_operation(S_ELEM_STATE *p_elem, u8_t type)
202 {
203  LOGD(TAG, "");
204  S_MESH_STATE *p_state = &p_elem->state;
205  p_state->lightness_actual[type] = (uint16_t)(sqrt(p_state->lightness_linear / 65535) * 65535);
206 }
207 
208 static u16_t _gen_lightness_actual_operation(S_ELEM_STATE *p_elem, u8_t type)
209 {
210  LOGD(TAG, "");
211  S_MESH_STATE *p_state = &p_elem->state;
212  p_state->lightness_linear = p_state->lightness_actual[type] * p_state->lightness_actual[type] / 65535;
213  p_state->level = p_state->lightness_actual[type] - 32768;
214  if(!p_state->lightness_actual[T_CUR]){
215    p_state->onoff[type]= 0x00;
216  }else{
217    p_state->onoff[type]= 0x01;
218  }
219 }*/
220 
221 
222 
223