state_binding.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
  2. *
  3. * SPDX-FileCopyrightText: 2018 Vikrant More
  4. * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. */
  8. #include <errno.h>
  9. #include "mesh_config.h"
  10. #include "mesh_common.h"
  11. #include "model_opcode.h"
  12. #include "state_binding.h"
  13. #include "state_transition.h"
  14. #if CONFIG_BLE_MESH_SERVER_MODEL
  15. #define MINDIFF (2.25e-308)
  16. static float bt_mesh_sqrt(float square)
  17. {
  18. float root = 0.0, last = 0.0, diff = 0.0;
  19. root = square / 3.0;
  20. diff = 1;
  21. if (square <= 0) {
  22. return 0;
  23. }
  24. do {
  25. last = root;
  26. root = (root + square / root) / 2.0;
  27. diff = root - last;
  28. } while (diff > MINDIFF || diff < -MINDIFF);
  29. return root;
  30. }
  31. static int32_t bt_mesh_ceiling(float num)
  32. {
  33. int32_t inum = (int32_t)num;
  34. if (num == (float)inum) {
  35. return inum;
  36. }
  37. return inum + 1;
  38. }
  39. uint16_t bt_mesh_convert_lightness_actual_to_linear(uint16_t actual)
  40. {
  41. float tmp = ((float) actual / UINT16_MAX);
  42. return bt_mesh_ceiling(UINT16_MAX * tmp * tmp);
  43. }
  44. uint16_t bt_mesh_convert_lightness_linear_to_actual(uint16_t linear)
  45. {
  46. return (uint16_t) (UINT16_MAX * bt_mesh_sqrt(((float) linear / UINT16_MAX)));
  47. }
  48. int16_t bt_mesh_convert_temperature_to_gen_level(uint16_t temp, uint16_t min, uint16_t max)
  49. {
  50. float tmp = (temp - min) * UINT16_MAX / (max - min);
  51. return (int16_t) (tmp + INT16_MIN);
  52. }
  53. uint16_t bt_mesh_covert_gen_level_to_temperature(int16_t level, uint16_t min, uint16_t max)
  54. {
  55. float diff = (float) (max - min) / UINT16_MAX;
  56. uint16_t tmp = (uint16_t) ((level - INT16_MIN) * diff);
  57. return (uint16_t) (min + tmp);
  58. }
  59. int16_t bt_mesh_convert_hue_to_level(uint16_t hue)
  60. {
  61. return (int16_t) (hue + INT16_MIN);
  62. }
  63. uint16_t bt_mesh_convert_level_to_hue(int16_t level)
  64. {
  65. return (uint16_t) (level - INT16_MIN);
  66. }
  67. int16_t bt_mesh_convert_saturation_to_level(uint16_t saturation)
  68. {
  69. return (int16_t) (saturation + INT16_MIN);
  70. }
  71. uint16_t bt_mesh_convert_level_to_saturation(int16_t level)
  72. {
  73. return (uint16_t) (level - INT16_MIN);
  74. }
  75. int bt_mesh_update_binding_state(struct bt_mesh_model *model,
  76. bt_mesh_server_state_type_t type,
  77. bt_mesh_server_state_value_t *value)
  78. {
  79. if (model == NULL || model->user_data == NULL ||
  80. value == NULL || type > BIND_STATE_MAX) {
  81. BT_ERR("%s, Invalid parameter", __func__);
  82. return -EINVAL;
  83. }
  84. switch (type) {
  85. #if CONFIG_BLE_MESH_GENERIC_SERVER
  86. case GENERIC_ONOFF_STATE: {
  87. if (model->id != BLE_MESH_MODEL_ID_GEN_ONOFF_SRV) {
  88. BT_ERR("Invalid Generic OnOff Server, model id 0x%04x", model->id);
  89. return -EINVAL;
  90. }
  91. struct bt_mesh_gen_onoff_srv *srv = model->user_data;
  92. bt_mesh_server_stop_transition(&srv->transition);
  93. srv->state.onoff = value->gen_onoff.onoff;
  94. gen_onoff_publish(model);
  95. break;
  96. }
  97. case GENERIC_LEVEL_STATE: {
  98. if (model->id != BLE_MESH_MODEL_ID_GEN_LEVEL_SRV) {
  99. BT_ERR("Invalid Generic Level Server, model id 0x%04x", model->id);
  100. return -EINVAL;
  101. }
  102. struct bt_mesh_gen_level_srv *srv = model->user_data;
  103. bt_mesh_server_stop_transition(&srv->transition);
  104. srv->state.level = value->gen_level.level;
  105. gen_level_publish(model);
  106. break;
  107. }
  108. case GENERIC_ONPOWERUP_STATE: {
  109. if (model->id != BLE_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV) {
  110. BT_ERR("Invalid Generic Power OnOff Server, model id 0x%04x", model->id);
  111. return -EINVAL;
  112. }
  113. struct bt_mesh_gen_power_onoff_srv *srv = model->user_data;
  114. if (srv->state == NULL) {
  115. BT_ERR("Invalid Generic Power OnOff Server state");
  116. return -EINVAL;
  117. }
  118. srv->state->onpowerup = value->gen_onpowerup.onpowerup;
  119. gen_onpowerup_publish(model);
  120. break;
  121. }
  122. case GENERIC_POWER_ACTUAL_STATE: {
  123. if (model->id != BLE_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV) {
  124. BT_ERR("Invalid Generic Power Level Server, model id 0x%04x", model->id);
  125. return -EINVAL;
  126. }
  127. struct bt_mesh_gen_power_level_srv *srv = model->user_data;
  128. if (srv->state == NULL) {
  129. BT_ERR("Invalid Generic Power Level Server state");
  130. return -EINVAL;
  131. }
  132. bt_mesh_server_stop_transition(&srv->transition);
  133. srv->state->power_actual = value->gen_power_actual.power;
  134. /**
  135. * Whenever the Generic Power Actual state is changed to a non-zero value
  136. * as a result of a non-transactional message or a completed sequence of
  137. * transactional messages, the value of the Generic Power Last state shall
  138. * be set to the value of the Generic Power Actual state.
  139. */
  140. if (srv->state->power_actual) {
  141. srv->state->power_last = srv->state->power_actual;
  142. }
  143. gen_power_level_publish(model, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
  144. break;
  145. }
  146. #endif /* CONFIG_BLE_MESH_GENERIC_SERVER */
  147. #if CONFIG_BLE_MESH_LIGHTING_SERVER
  148. case LIGHT_LIGHTNESS_ACTUAL_STATE: {
  149. if (model->id != BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) {
  150. BT_ERR("Invalid Light Lightness Server, model id 0x%04x", model->id);
  151. return -EINVAL;
  152. }
  153. struct bt_mesh_light_lightness_srv *srv = model->user_data;
  154. if (srv->state == NULL) {
  155. BT_ERR("Invalid Light Lightness Server state");
  156. return -EINVAL;
  157. }
  158. bt_mesh_server_stop_transition(&srv->actual_transition);
  159. srv->state->lightness_actual = value->light_lightness_actual.lightness;
  160. /**
  161. * Whenever the Light Lightness Actual state is changed with a non-transactional
  162. * message or a completed sequence of transactional messages to a non-zero value,
  163. * the value of the Light Lightness Last shall be set to the value of the Light
  164. * Lightness Actual.
  165. */
  166. if (srv->state->lightness_actual) {
  167. srv->state->lightness_last = srv->state->lightness_actual;
  168. }
  169. light_lightness_publish(model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
  170. break;
  171. }
  172. case LIGHT_LIGHTNESS_LINEAR_STATE: {
  173. if (model->id != BLE_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV) {
  174. BT_ERR("Invalid Light Lightness Server, model id 0x%04x", model->id);
  175. return -EINVAL;
  176. }
  177. struct bt_mesh_light_lightness_srv *srv = model->user_data;
  178. if (srv->state == NULL) {
  179. BT_ERR("Invalid Light Lightness Server state");
  180. return -EINVAL;
  181. }
  182. bt_mesh_server_stop_transition(&srv->linear_transition);
  183. srv->state->lightness_linear = value->light_lightness_linear.lightness;
  184. light_lightness_publish(model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
  185. break;
  186. }
  187. case LIGHT_CTL_LIGHTNESS_STATE: {
  188. if (model->id != BLE_MESH_MODEL_ID_LIGHT_CTL_SRV) {
  189. BT_ERR("Invalid Light CTL Server, model id 0x%04x", model->id);
  190. return -EINVAL;
  191. }
  192. struct bt_mesh_light_ctl_srv *srv = model->user_data;
  193. if (srv->state == NULL) {
  194. BT_ERR("Invalid Light CTL Server state");
  195. return -EINVAL;
  196. }
  197. bt_mesh_server_stop_transition(&srv->transition);
  198. srv->state->lightness = value->light_ctl_lightness.lightness;
  199. light_ctl_publish(model, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
  200. break;
  201. }
  202. case LIGHT_CTL_TEMP_DELTA_UV_STATE: {
  203. if (model->id != BLE_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV) {
  204. BT_ERR("Invalid Light CTL Temperature Server, model id 0x%04x", model->id);
  205. return -EINVAL;
  206. }
  207. struct bt_mesh_light_ctl_temp_srv *srv = model->user_data;
  208. if (srv->state == NULL) {
  209. BT_ERR("Invalid Light CTL Temperature Server state");
  210. return -EINVAL;
  211. }
  212. bt_mesh_server_stop_transition(&srv->transition);
  213. srv->state->temperature = value->light_ctl_temp_delta_uv.temperature;
  214. srv->state->delta_uv = value->light_ctl_temp_delta_uv.delta_uv;
  215. light_ctl_publish(model, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
  216. break;
  217. }
  218. case LIGHT_HSL_STATE: {
  219. if (model->id != BLE_MESH_MODEL_ID_LIGHT_HSL_SRV) {
  220. BT_ERR("Invalid Light HSL Server, model id 0x%04x", model->id);
  221. return -EINVAL;
  222. }
  223. struct bt_mesh_light_hsl_srv *srv = model->user_data;
  224. if (srv->state == NULL) {
  225. BT_ERR("Invalid Light HSL Server state");
  226. return -EINVAL;
  227. }
  228. bt_mesh_server_stop_transition(&srv->transition);
  229. srv->state->lightness = value->light_hsl.lightness;
  230. srv->state->hue = value->light_hsl.hue;
  231. srv->state->saturation = value->light_hsl.saturation;
  232. light_hsl_publish(model, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
  233. break;
  234. }
  235. case LIGHT_HSL_LIGHTNESS_STATE: {
  236. if (model->id != BLE_MESH_MODEL_ID_LIGHT_HSL_SRV) {
  237. BT_ERR("Invalid Light HSL Server, model id 0x%04x", model->id);
  238. return -EINVAL;
  239. }
  240. struct bt_mesh_light_hsl_srv *srv = model->user_data;
  241. if (srv->state == NULL) {
  242. BT_ERR("Invalid Light HSL Server state");
  243. return -EINVAL;
  244. }
  245. bt_mesh_server_stop_transition(&srv->transition);
  246. srv->state->lightness = value->light_hsl_lightness.lightness;
  247. light_hsl_publish(model, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
  248. break;
  249. }
  250. case LIGHT_HSL_HUE_STATE: {
  251. if (model->id != BLE_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV) {
  252. BT_ERR("Invalid Light HSL Hue Server, model id 0x%04x", model->id);
  253. return -EINVAL;
  254. }
  255. struct bt_mesh_light_hsl_hue_srv *srv = model->user_data;
  256. if (srv->state == NULL) {
  257. BT_ERR("Invalid Light HSL Hue Server state");
  258. return -EINVAL;
  259. }
  260. bt_mesh_server_stop_transition(&srv->transition);
  261. srv->state->hue = value->light_hsl_hue.hue;
  262. light_hsl_publish(model, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
  263. break;
  264. }
  265. case LIGHT_HSL_SATURATION_STATE: {
  266. if (model->id != BLE_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV) {
  267. BT_ERR("Invalid Light HSL Saturation Server, model id 0x%04x", model->id);
  268. return -EINVAL;
  269. }
  270. struct bt_mesh_light_hsl_sat_srv *srv = model->user_data;
  271. if (srv->state == NULL) {
  272. BT_ERR("Invalid Light HSL Saturation Server state");
  273. return -EINVAL;
  274. }
  275. bt_mesh_server_stop_transition(&srv->transition);
  276. srv->state->saturation = value->light_hsl_saturation.saturation;
  277. light_hsl_publish(model, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
  278. break;
  279. }
  280. case LIGHT_XYL_LIGHTNESS_STATE: {
  281. if (model->id != BLE_MESH_MODEL_ID_LIGHT_XYL_SRV) {
  282. BT_ERR("Invalid Light xyL Server, model id 0x%04x", model->id);
  283. return -EINVAL;
  284. }
  285. struct bt_mesh_light_xyl_srv *srv = model->user_data;
  286. if (srv->state == NULL) {
  287. BT_ERR("Invalid Light xyL Server state");
  288. return -EINVAL;
  289. }
  290. bt_mesh_server_stop_transition(&srv->transition);
  291. srv->state->lightness = value->light_xyl_lightness.lightness;
  292. light_xyl_publish(model, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
  293. break;
  294. }
  295. case LIGHT_LC_LIGHT_ONOFF_STATE: {
  296. if (model->id != BLE_MESH_MODEL_ID_LIGHT_LC_SRV) {
  297. BT_ERR("Invalid Light LC Server, model id 0x%04x", model->id);
  298. return -EINVAL;
  299. }
  300. struct bt_mesh_light_lc_srv *srv = model->user_data;
  301. if (srv->lc == NULL) {
  302. BT_ERR("Invalid Light LC Server state");
  303. return -EINVAL;
  304. }
  305. bt_mesh_server_stop_transition(&srv->transition);
  306. srv->lc->state.light_onoff = value->light_lc_light_onoff.onoff;
  307. light_lc_publish(model, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
  308. break;
  309. }
  310. #endif /* CONFIG_BLE_MESH_LIGHTING_SERVER */
  311. default:
  312. BT_WARN("Unknown binding state type 0x%02x", type);
  313. return -EINVAL;
  314. }
  315. return 0;
  316. }
  317. #endif /* CONFIG_BLE_MESH_SERVER_MODEL */