General_view.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include "UnitempViews.h"
  2. #include "unitemp_icons.h"
  3. static View* view;
  4. static uint8_t sensor_index = 0;
  5. static char buff[7];
  6. static void _draw_temperature(Canvas* canvas, Sensor* sensor, uint8_t x, uint8_t y, Color color) {
  7. //Рисование рамки
  8. canvas_draw_rframe(canvas, x, y, 54, 20, 3);
  9. if(color == ColorBlack) {
  10. canvas_draw_rbox(canvas, x, y, 54, 19, 3);
  11. canvas_invert_color(canvas);
  12. } else {
  13. canvas_draw_rframe(canvas, x, y, 54, 19, 3);
  14. }
  15. int16_t temp_int = sensor->temp;
  16. int8_t temp_dec = abs((int16_t)(sensor->temp * 10) % 10);
  17. //Рисование иконки
  18. canvas_draw_icon(
  19. canvas, x + 3, y + 3, (app->settings.unit == CELSIUS ? &I_temp_C_11x14 : &I_temp_F_11x14));
  20. if((int16_t)sensor->temp == -128 || sensor->status == UT_TIMEOUT) {
  21. snprintf(buff, 5, "--");
  22. canvas_set_font(canvas, FontBigNumbers);
  23. canvas_draw_str_aligned(canvas, x + 27, y + 10, AlignCenter, AlignCenter, buff);
  24. snprintf(buff, 4, ". -");
  25. canvas_set_font(canvas, FontPrimary);
  26. canvas_draw_str_aligned(canvas, x + 50, y + 10 + 3, AlignRight, AlignCenter, buff);
  27. if(color == ColorBlack) canvas_invert_color(canvas);
  28. return;
  29. }
  30. //Целая часть температуры
  31. snprintf(buff, 7, "%d", temp_int);
  32. canvas_set_font(canvas, FontBigNumbers);
  33. canvas_draw_str_aligned(
  34. canvas, x + 27 + ((temp_int <= -10) ? 5 : 0), y + 10, AlignCenter, AlignCenter, buff);
  35. //Печать дробной части температуры в диапазоне от -9 до 99 (когда два знака в числе)
  36. if(temp_int > -10 && temp_int <= 99) {
  37. uint8_t int_len = canvas_string_width(canvas, buff);
  38. snprintf(buff, 4, ".%d", temp_dec);
  39. canvas_set_font(canvas, FontPrimary);
  40. canvas_draw_str(canvas, x + 27 + int_len / 2 + 2, y + 10 + 7, buff);
  41. }
  42. if(color == ColorBlack) canvas_invert_color(canvas);
  43. }
  44. static void _draw_humidity(Canvas* canvas, Sensor* sensor, const uint8_t pos[2]) {
  45. //Рисование рамки
  46. canvas_draw_rframe(canvas, pos[0], pos[1], 54, 20, 3);
  47. canvas_draw_rframe(canvas, pos[0], pos[1], 54, 19, 3);
  48. //Рисование иконки
  49. canvas_draw_icon(canvas, pos[0] + 3, pos[1] + 2, &I_hum_9x15);
  50. if((int8_t)sensor->hum == -128 || sensor->status == UT_TIMEOUT) {
  51. snprintf(buff, 5, "--");
  52. canvas_set_font(canvas, FontBigNumbers);
  53. canvas_draw_str_aligned(canvas, pos[0] + 27, pos[1] + 10, AlignCenter, AlignCenter, buff);
  54. snprintf(buff, 4, ". -");
  55. canvas_set_font(canvas, FontPrimary);
  56. canvas_draw_str_aligned(
  57. canvas, pos[0] + 50, pos[1] + 10 + 3, AlignRight, AlignCenter, buff);
  58. return;
  59. }
  60. //Целая часть влажности
  61. snprintf(buff, 5, "%d", (uint8_t)sensor->hum);
  62. canvas_set_font(canvas, FontBigNumbers);
  63. canvas_draw_str_aligned(canvas, pos[0] + 27, pos[1] + 10, AlignCenter, AlignCenter, buff);
  64. uint8_t int_len = canvas_string_width(canvas, buff);
  65. //Единица измерения
  66. canvas_set_font(canvas, FontPrimary);
  67. canvas_draw_str(canvas, pos[0] + 27 + int_len / 2 + 4, pos[1] + 10 + 7, "%");
  68. }
  69. static void _draw_pressure(Canvas* canvas, Sensor* sensor) {
  70. const uint8_t x = 29, y = 39;
  71. //Рисование рамки
  72. canvas_draw_rframe(canvas, x, y, 69, 20, 3);
  73. canvas_draw_rframe(canvas, x, y, 69, 19, 3);
  74. //Рисование иконки
  75. canvas_draw_icon(canvas, x + 3, y + 4, &I_pressure_7x13);
  76. //Давление
  77. snprintf(buff, 6, "%d", (uint16_t)sensor->pressure);
  78. canvas_set_font(canvas, FontBigNumbers);
  79. canvas_draw_str_aligned(canvas, x + 30, y + 10, AlignCenter, AlignCenter, buff);
  80. //Единица измерения
  81. canvas_draw_icon(canvas, x + 50, y + 3, &I_mm_hg_17x15);
  82. }
  83. static void _draw_singleSensor(Canvas* canvas, Sensor* sensor, const uint8_t pos[2], Color color) {
  84. canvas_set_font(canvas, FontPrimary);
  85. const uint8_t max_width = 61;
  86. char sensor_name[12] = {0};
  87. memcpy(sensor_name, sensor->name, 10);
  88. if(canvas_string_width(canvas, sensor_name) > max_width) {
  89. uint8_t i = 10;
  90. while((canvas_string_width(canvas, sensor_name) > max_width - 6) && (i != 0)) {
  91. sensor_name[i--] = '\0';
  92. }
  93. sensor_name[++i] = '.';
  94. sensor_name[++i] = '.';
  95. }
  96. canvas_draw_str_aligned(
  97. canvas, pos[0] + 27, pos[1] + 3, AlignCenter, AlignCenter, sensor_name);
  98. _draw_temperature(canvas, sensor, pos[0], pos[1] + 8, color);
  99. }
  100. static void _draw_view_noSensors(Canvas* canvas) {
  101. canvas_draw_str(canvas, 0, 24, "Sensors not found");
  102. }
  103. static void _draw_view_sensorsList(Canvas* canvas) {
  104. //Текущая страница
  105. uint8_t page = sensor_index / 4;
  106. //Количество датчиков, которые будут отображаться на странице
  107. uint8_t page_sensors_count;
  108. if((app->sensors_count - page * 4) / 4) {
  109. page_sensors_count = 4;
  110. } else {
  111. page_sensors_count = (app->sensors_count - page * 4) % 4;
  112. }
  113. //Количество страниц
  114. uint8_t pages = app->sensors_count / 4 + (app->sensors_count % 4 ? 1 : 0);
  115. //Стрелка вверх
  116. if(page > 0) {
  117. canvas_draw_icon(canvas, 60, 2, &I_arrow_up_5x9);
  118. }
  119. //Стрелка вниз
  120. if(pages > 0 && page < pages - 1) {
  121. canvas_draw_icon(canvas, 60, 56, &I_arrow_down_5x9);
  122. }
  123. const uint8_t value_positions[][4][2] = {
  124. {{36, 18}}, //1 датчик
  125. {{4, 18}, {70, 18}}, //2 датчика
  126. {{4, 3}, {70, 3}, {37, 33}}, //3 датчика
  127. {{4, 3}, {70, 3}, {4, 33}, {70, 33}}}; //4 датчика
  128. //Рисование рамки
  129. canvas_draw_rframe(canvas, 0, 0, 128, 63, 7);
  130. canvas_draw_rframe(canvas, 0, 0, 128, 64, 7);
  131. for(uint8_t i = 0; i < page_sensors_count; i++) {
  132. _draw_singleSensor(
  133. canvas,
  134. app->sensors[page * 4 + i],
  135. value_positions[page_sensors_count - 1][i],
  136. (i == sensor_index % 4 ? ColorBlack : ColorWhite));
  137. }
  138. }
  139. static void _draw_view_sensorsCarousel(Canvas* canvas) {
  140. static const uint8_t temp_positions[3][2] = {{37, 23}, {37, 16}, {9, 16}};
  141. static const uint8_t hum_positions[2][2] = {{37, 38}, {65, 16}};
  142. //Рисование рамки
  143. canvas_draw_rframe(canvas, 3, 0, 122, 63, 7);
  144. canvas_draw_rframe(canvas, 3, 0, 122, 64, 7);
  145. //Печать имени
  146. canvas_set_font(canvas, FontPrimary);
  147. canvas_draw_str_aligned(
  148. canvas, 64, 7, AlignCenter, AlignCenter, app->sensors[sensor_index]->name);
  149. //Подчёркивание
  150. uint8_t line_len = canvas_string_width(canvas, app->sensors[sensor_index]->name) + 2;
  151. canvas_draw_line(canvas, 64 - line_len / 2, 12, 64 + line_len / 2, 12);
  152. //Стрелка вправо
  153. if(unitemp_sensors_getTypesCount() > 0 && sensor_index < unitemp_sensors_getCount() - 1) {
  154. canvas_draw_icon(canvas, 117, 28, &I_arrow_right_5x9);
  155. }
  156. //Стрелка влево
  157. if(sensor_index > 0) {
  158. canvas_draw_icon(canvas, 6, 28, &I_arrow_left_5x9);
  159. }
  160. if(app->sensors[sensor_index]->status == UT_TIMEOUT) {
  161. const Icon* frames[] = {&I_happy_2_78x46, &I_happy_78x46, &I_sad_78x46};
  162. canvas_draw_icon(canvas, 24, 15, frames[furi_get_tick() % 2250 / 750]);
  163. return;
  164. }
  165. //Селектор значений для отображения
  166. switch(app->sensors[sensor_index]->type->datatype) {
  167. case UT_DATA_TYPE_TEMP:
  168. _draw_temperature(
  169. canvas,
  170. app->sensors[sensor_index],
  171. temp_positions[0][0],
  172. temp_positions[0][1],
  173. ColorWhite);
  174. break;
  175. case UT_DATA_TYPE_TEMP_HUM:
  176. _draw_temperature(
  177. canvas,
  178. app->sensors[sensor_index],
  179. temp_positions[1][0],
  180. temp_positions[1][1],
  181. ColorWhite);
  182. _draw_humidity(canvas, app->sensors[sensor_index], hum_positions[0]);
  183. break;
  184. case UT_DATA_TYPE_TEMP_PRESS:
  185. _draw_temperature(
  186. canvas,
  187. app->sensors[sensor_index],
  188. temp_positions[1][0],
  189. temp_positions[1][1],
  190. ColorWhite);
  191. _draw_pressure(canvas, app->sensors[sensor_index]);
  192. break;
  193. case UT_DATA_TYPE_TEMP_HUM_PRESS:
  194. _draw_temperature(
  195. canvas,
  196. app->sensors[sensor_index],
  197. temp_positions[2][0],
  198. temp_positions[2][1],
  199. ColorWhite);
  200. _draw_humidity(canvas, app->sensors[sensor_index], hum_positions[1]);
  201. _draw_pressure(canvas, app->sensors[sensor_index]);
  202. break;
  203. }
  204. }
  205. static void _draw_callback(Canvas* canvas, void* _model) {
  206. UNUSED(_model);
  207. app->sensors_ready = true;
  208. uint8_t sensors_count = unitemp_sensors_getCount();
  209. if(sensors_count == 0) {
  210. _draw_view_noSensors(canvas);
  211. }
  212. if(sensors_count > 0) {
  213. _draw_view_sensorsList(canvas);
  214. }
  215. if(0) _draw_view_sensorsCarousel(canvas);
  216. }
  217. static bool _input_callback(InputEvent* event, void* context) {
  218. Unitemp* app = context;
  219. //Выход по короткому нажатию "назад"
  220. if(event->key == InputKeyBack && event->type == InputTypeShort) {
  221. app->processing = false;
  222. }
  223. //Пролистывание списка по короткому нажатию "вниз"
  224. if(event->key == InputKeyDown && event->type == InputTypeShort) {
  225. if(++sensor_index >= unitemp_sensors_getCount()) sensor_index = 0;
  226. }
  227. //Пролистывание списка по короткому нажатию "вверх"
  228. if(event->key == InputKeyUp && event->type == InputTypeShort) {
  229. if(--sensor_index >= unitemp_sensors_getCount())
  230. sensor_index = unitemp_sensors_getCount() - 1;
  231. }
  232. //Пролистывание карусели по короткому нажатию "право"
  233. if(event->key == InputKeyRight && event->type == InputTypeShort) {
  234. if(++sensor_index >= unitemp_sensors_getCount()) sensor_index = 0;
  235. }
  236. //Пролистывание карусели по короткому нажатию "лево"
  237. if(event->key == InputKeyLeft && event->type == InputTypeShort) {
  238. if(--sensor_index >= unitemp_sensors_getCount())
  239. sensor_index = unitemp_sensors_getCount() - 1;
  240. }
  241. //Вход в главное меню по короткому нажатию "ок"
  242. if(event->key == InputKeyOk && event->type == InputTypeShort) {
  243. app->sensors_ready = false;
  244. unitemp_MainMenu_switch();
  245. }
  246. //Редактирование датчика при длинном нажатии "ок"
  247. if(event->key == InputKeyOk && event->type == InputTypeLong) {
  248. app->sensors_ready = false;
  249. unitemp_SensorEdit_switch(app->sensors[sensor_index]);
  250. }
  251. return true;
  252. }
  253. void unitemp_General_alloc(void) {
  254. view = view_alloc();
  255. view_set_context(view, app);
  256. view_set_draw_callback(view, _draw_callback);
  257. view_set_input_callback(view, _input_callback);
  258. view_dispatcher_add_view(app->view_dispatcher, GENERAL_VIEW, view);
  259. }
  260. void unitemp_General_switch(void) {
  261. app->sensors_ready = true;
  262. view_dispatcher_switch_to_view(app->view_dispatcher, GENERAL_VIEW);
  263. }
  264. void unitemp_General_free(void) {
  265. view_free(view);
  266. }