/
singlwolf
/
Radiola-2S3
Обзор
Документация
Войти
/
singlwolf
/
Radiola-2S3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/services.cpp
1 106 строк
28 KB
SinglWolf
v1.0.6
15 апр 2026, 05:04
15 апр 2026, 05:04
55b96c5
Код
Авторство
О чём код?
/** services.cpp **/ #include <cstring> #include <cstdio> #include <sys/time.h> #include "main.h" #include "net_work.h" #include "eeStorage.h" #include "services.h" #include "hardware.h" #include <ctime> #include <fs_system.h> #include "ui.h" #include "audioVS.h" #include "controls.h" #include "lv_i18n.h" #include "prio_.h" #define TAG "SERVICES" char StNumStr[4]; QueueHandle_t event_lcd = nullptr; static uint32_t my_tick_get_cb() { return millis(); } SemaphoreHandle_t xGuiSemaphore = nullptr; lv_obj_t *objColor = nullptr; lv_color_t color = {0, 0, 0}; lv_timer_t *PlayWait = nullptr; String copyNameSta = ""; String copyNameArtist = ""; String copyNameSong = ""; uint16_t currSta = 0; char oldDateStr[64] = {}; Services serv; Services::Services() = default; Services::~Services() {} bool sensor_show = true; static uint8_t wait_id = 0; //////////////////////////////////////// void *rmalloc(size_t memorySize) { if (psramInit()) return heap_caps_malloc(memorySize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); else return heap_caps_malloc(memorySize, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); } void *rcalloc(size_t elementCount, size_t elementSize) { if (psramInit()) return heap_caps_calloc(elementCount, elementSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); else return heap_caps_calloc(elementCount, elementSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); } //////////////////////////////////////// bool _hide(lv_obj_t *obj) { if (!lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) { lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); return true; } return false; } //////////////////////////////////////// bool _show(lv_obj_t *obj) { if (lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) { lv_obj_remove_flag(obj, LV_OBJ_FLAG_HIDDEN); return true; } return false; } //////////////////////////////////////// static void set_label_opacity(void *obj, int32_t value) { lv_obj_set_style_opa((lv_obj_t *)obj, (lv_opa_t)value, LV_PART_MAIN); } void start_blinking() { lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, objects.warn_label); lv_anim_set_exec_cb(&a, set_label_opacity); lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_TRANSP); lv_anim_set_time(&a, 250); lv_anim_set_playback_time(&a, 250); lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); lv_anim_set_path_cb(&a, lv_anim_path_linear); lv_anim_start(&a); lv_obj_remove_flag(objects.warn_label, LV_OBJ_FLAG_HIDDEN); } void stop_blinking() { lv_anim_del(objects.warn_label, set_label_opacity); lv_obj_add_flag(objects.warn_label, LV_OBJ_FLAG_HIDDEN); } //////////////////////////////////////// void play_wait(lv_timer_t *timer) { _hide(objects.numbers_panel_info); sensor_show = true; auto *ID = (uint8_t *)lv_timer_get_user_data(timer); if ((*ID <= eeprom.GetTotalSta()) && (*ID > 0)) { if (eeprom.GetID() != *ID) { player.play(*ID); } } lv_timer_delete(PlayWait); PlayWait = nullptr; StNumStr[0] = 0; } void startPlayWait(uint8_t ID) { uint8_t period = 15; if (ID == 0xFF) { period = 5; } _hide(objects.sensors_panel); sensor_show = false; wait_id = ID; if (PlayWait == nullptr) { PlayWait = lv_timer_create(play_wait, period * 100, &wait_id); } else { lv_timer_resume(PlayWait); } } // void resetPlayWait() { if (PlayWait) { lv_timer_reset(PlayWait); lv_timer_pause(PlayWait); } } //////////////////////////////////////// // StNum void Services::setStationNum(uint8_t num) { StNum = num; } uint8_t Services::getStationNum() { return StNum; } // a number of station in progress... void Services::setNumberbStation(char nb) { if (strlen(StNumStr) >= 3) StNumStr[0] = 0; uint8_t id = strlen(StNumStr); StNumStr[id] = nb; StNumStr[id + 1] = 0; event_lcd_s evt; evt.lcmd = setnum; xQueueSend(event_lcd, &evt, 0); } void Services::evtStation(bool next) { event_lcd_s evt; evt.lcmd = estation; evt.value = next; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtCheckFormat() { event_lcd_s evt; evt.lcmd = check_format; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtUpateRssi() { event_lcd_s evt; evt.lcmd = urssi; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtUpate(char *text) { } //-------------------- void Services::evtSetClock() { event_lcd_s evt; evt.lcmd = lclock; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetWait(uint8_t cmd) { event_lcd_s evt; evt.lcmd = lwait; evt.value = cmd; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetSta() { event_lcd_s evt; evt.lcmd = lsetsta; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetColor(lv_obj_t *obj, lv_color_t val) { // objColor = nullptr; // color = {0}; while (objColor != nullptr) { delay(1); } objColor = obj; color = val; event_lcd_s evt; evt.lcmd = lcolor; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetSensor(bool enable) { if (!sensor_show && enable) { return; } event_lcd_s evt; evt.lcmd = lsensor; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- bool set_warn = false; void Services::evtSetWarn(bool enable) { if (set_warn == enable) { return; } set_warn = enable; event_lcd_s evt; evt.lcmd = lsetwarn; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtAlarm(bool enable) { event_lcd_s evt; evt.lcmd = lalarm; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtRotat() { event_lcd_s evt; evt.lcmd = lrotat; xQueueSend(event_lcd, &evt, 0); } //-------------------- // void Services::evtSet_Sta() // { // event_lcd_s evt; // evt.lcmd = lrotat; // xQueueSend(event_lcd, &evt, 0); // } //-------------------- lv_color_t Services::colorHTML(String html) { html[0] = 0x20; // Заменяем '#' пробелом return lv_color_hex((uint32_t)strtoul(html.c_str(), nullptr, 16)); } void Services::set_custom_theme() { change_color_theme(dark_theme); _ui_set_style_text_color(objects.clock, colorHTML(Config->color.clock[dark_theme])); _ui_set_style_text_color(objects.temperature_label, colorHTML(Config->color.temp[dark_theme])); _ui_set_style_text_color(objects.minus_label, colorHTML(Config->color.temp[dark_theme])); _ui_set_style_text_color(objects.degre_label, colorHTML(Config->color.temp[dark_theme])); _ui_set_style_text_color(objects.pressure_label, colorHTML(Config->color.press[dark_theme])); _ui_set_style_text_color(objects.wet_label, colorHTML(Config->color.wet[dark_theme])); } //-------------------- void Services::evtSleep(bool enable) { event_lcd_s evt; evt.lcmd = lsleep; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtVUmeter(bool enable) { event_lcd_s evt; evt.lcmd = lvumeter; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetTheme() { event_lcd_s evt; evt.lcmd = ltheme; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtMute(bool enable) { event_lcd_s evt; evt.lcmd = lmute; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtExtInfo(bool enable) { event_lcd_s evt; evt.lcmd = lextinfo; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtClearTitle() { event_lcd_s evt; evt.lcmd = lclear; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetLogo() { event_lcd_s evt; evt.lcmd = llogo; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtPlayList(bool enable) { event_lcd_s evt; evt.lcmd = playlist; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtMenu(bool enable) { event_lcd_s evt; evt.lcmd = lmenu; evt.value = enable; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetVol() { event_lcd_s evt; evt.lcmd = lvol; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetName(uint8_t id) { event_lcd_s evt; evt.lcmd = lnameset; evt.value = id; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetStop() { event_lcd_s evt; evt.lcmd = lstop; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetPlay() { event_lcd_s evt; evt.lcmd = lplay; xQueueSend(event_lcd, &evt, 0); } //-------------------- void Services::evtSetMeta() { event_lcd_s evt; evt.lcmd = lmeta; xQueueSend(event_lcd, &evt, 0); } //-------------------- //-------------------- lv_timer_t *ShowSensor = nullptr; void Show_Sensor(lv_timer_t *timer) { LV_UNUSED(timer); serv.evtSetSensor(false); lv_timer_delete(ShowSensor); ShowSensor = nullptr; } // bool Services::startShowSensor(uint8_t set) { bool ret = ShowSensor != nullptr; if (!set) { set = Config->sensor.time; } if (!set) return ret; if (ShowSensor == nullptr) { ShowSensor = lv_timer_create(Show_Sensor, set * 1000U, nullptr); } else { lv_timer_reset(ShowSensor); } serv.evtSetSensor(true); return ret; } //-------------------- static lv_timer_t *VUmeter_tm = nullptr; bool VUmeter_stop = true; static constexpr uint8_t brights[] = {80, 138, 196, 255}; static uint8_t current_l = 0; static uint8_t current_r = 0; static lv_obj_t *left_leds[32]; static lv_obj_t *right_leds[32]; //-------------------- void Services::SetupVUmeter() { for (int i = 0; i < 32; i++) { left_leds[i] = lv_obj_get_child(objects.left_cannel, i); right_leds[i] = lv_obj_get_child(objects.right_cannel, i); } } //-------------------- void updateVUmeter(lv_timer_t *timer) { uint8_t target_l = 0; uint8_t target_r = 0; if (!VUmeter_stop) { // Читаем реальный уровень из VS1053 uint16_t vu = player.getVUlevel(); target_l = ((vu >> 8) & 0xFF); target_r = (vu & 0xFF); current_l = target_l; current_r = target_r; } else { if (current_l > 0) current_l--; if (current_r > 0) current_r--; } // Отрисовка состояния в контейнерах for (int i = 0; i < 32; i++) { // Левый канал int l_seg_level = current_l - (i * 3); // Сколько дБ приходится на этот светодиод if (l_seg_level < 0) l_seg_level = 0; if (l_seg_level > 3) l_seg_level = 3; lv_led_set_brightness(left_leds[i], brights[l_seg_level]); // Правый канал int r_seg_level = current_r - (i * 3); if (r_seg_level < 0) r_seg_level = 0; if (r_seg_level > 3) r_seg_level = 3; lv_led_set_brightness(right_leds[i], brights[r_seg_level]); } // Если всё упало в ноль при стопе — таймер на паузу if (VUmeter_stop && current_l == 0 && current_r == 0) { lv_timer_pause(VUmeter_tm); } } //-------------------- void startVUmeter() { if (VUmeter_tm == nullptr) VUmeter_tm = lv_timer_create(updateVUmeter, 30, nullptr); if (!lv_timer_get_paused(VUmeter_tm)) lv_timer_pause(VUmeter_tm); lv_timer_resume(VUmeter_tm); } //-------------------- // LCD display task //-------------------- void Services::taskWrapper(void *param) { auto *runner = static_cast<Services *>(param); runner->task_lcd(); } void Services::StartTask() { if (xTaskCreatePinnedToCore( &Services::taskWrapper, NAME_LCD, STACK_LCD, this, PRIO_LCD, nullptr /* &pxCreatedTask */, CPU_LCD) != pdPASS) { ESP_LOGE("LCD", "ERROR creating task! Out of memory?"); } } /*Set tick routine needed for LVGL internal timings*/ void Services::task_lcd() { xGuiSemaphore = xSemaphoreCreateMutex(); event_lcd_s evt; // lcd event // queue for events of the lcd event_lcd = xQueueCreate(20, sizeof(event_lcd_s)); if (event_lcd == nullptr) { Serial.println(F("Queue Create event_lcd failed!")); while (true) { delay(10); } } lv_tick_set_cb(my_tick_get_cb); // ESP_LOGD(TAG, "event_lcd: %d", (int)event_lcd); while (true) { while (xQueueReceive(event_lcd, &evt, 0)) { while (dev.Stop) { delay(100); } switch (evt.lcmd) { case lmeta: { const char *p = player.title[ICY_META].c_str(); const char *interp; int step = 3; interp = strstr(p, " - "); if (!interp) { interp = strstr(p, " \xe2\x80\x94 "); step = 5; } if (interp) { lv_label_set_text_fmt(objects.name_artist_label, "%.*s", (int)(interp - p), p); lv_label_set_text(objects.name_song_label, interp + step); } else { lv_label_set_text(objects.name_artist_label, p); lv_label_set_text(objects.name_song_label, ""); } copyNameArtist = lv_label_get_text(objects.name_artist_label); copyNameSong = lv_label_get_text(objects.name_song_label); } break; case lclock: { char TimeStr[16] = {}; struct tm timeinfo; getLocalTime(&timeinfo); strftime(TimeStr, 16, "%H %M", &timeinfo); lv_label_set_text(objects.clock_label, TimeStr); char *DateStr = network.getDate(Config->lcd.Long); if (strcmp(DateStr, oldDateStr) != 0) { lv_label_set_text(objects.date_label, DateStr); strcpy(oldDateStr, DateStr); } free(DateStr); } break; case lstop: { lv_label_set_text(objects.play_state_label, "!"); lv_label_set_text(objects.name_artist_label, ""); lv_label_set_text(objects.name_song_label, _("ОСТАНОВЛЕН")); } break; case lclear: { lv_label_set_text(objects.name_artist_label, ""); lv_label_set_text(objects.name_song_label, ""); lv_label_set_text(objects.icy_name_label, ""); lv_label_set_text(objects.icy_desc_label, ""); lv_label_set_text(objects.icy_genre_label, ""); lv_label_set_text(objects.icy_format_label, ""); lv_label_set_text(objects.bitrate_label, ""); lv_image_cache_drop((const void *)&objects.icon_ststion); } break; case lwait: { std::string text = ""; if (evt.value == WAIT_COMM) { text = _("КОМАНД"); } else if (evt.value == WAIT_REDIRECT) { text = _("ПЕРЕАДРЕСАЦИИ"); } else if (evt.value == WAIT_CONN) { text = _("ПОДКЛЮЧЕНИЯ"); } lv_label_set_text_fmt(objects.name_artist_label, "%s %s", _("ОЖИДАНИЕ"), text.c_str()); lv_label_set_text(objects.play_state_label, "\""); // PAUSE } break; case lsetsta: { if (eeprom.GetTotalSta() > 0) { lv_label_set_text_fmt(objects.name_station_label, "%d: %s", (eeprom.GetID()), eeprom.GetStaName(eeprom.GetID()).c_str()); } else { lv_label_set_text(objects.name_station_label, _("СПИСОК СТАНЦИЙ ПУСТ")); } copyNameSta = lv_label_get_text(objects.name_station_label); currSta = eeprom.GetID(); } break; case lsensor: { if (evt.value == 1) { bool show = false; String degree = "°\n"; if (Config->sensor.degree) { if (Config->sensor.cels) { degree = degree + "C"; } else { degree = degree + "F"; } } if (!Config->sensor.temp) { _hide(objects.temperature_panel); } else { show = true; if (dev.Temperature < 0) { set_var_minus("-"); } else { set_var_minus(" "); } lv_label_set_text_fmt(objects.temperature_label, "%.1f", abs(dev.Temperature)); lv_label_set_text(objects.degre_label, degree.c_str()); _show(objects.temperature_panel); } if (Config->sensor.press) { show = true; lv_label_set_text_fmt(objects.pressure_label, "%.1f", dev.Pressure); if (Config->sensor.torr) { lv_label_set_text(objects.pressure_desc_label, _("ММ РТ. СТОЛБА")); } else { lv_label_set_text(objects.pressure_desc_label, _("ГЕКТОПАСКАЛЕЙ")); } if (_show(objects.pressure_panel)) { lv_obj_set_style_border_side(objects.wet_panel, LV_BORDER_SIDE_LEFT, 0); } } else { if (_hide(objects.pressure_panel)) { lv_obj_set_style_border_side(objects.wet_panel, LV_BORDER_SIDE_NONE, 0); } } if ((!Config->sensor.wet) || (Config->i2c.bmp != 3)) { _hide(objects.wet_panel); } else { show = true; // abs((float)-1.2); lv_label_set_text_fmt(objects.wet_label, "%.1f", dev.Humidity); _show(objects.wet_panel); } if (lv_obj_has_flag(objects.roller_playlist, LV_OBJ_FLAG_HIDDEN) && lv_obj_has_flag(objects.sensors_panel, LV_OBJ_FLAG_HIDDEN) && show) { lv_obj_remove_flag(objects.sensors_panel, LV_OBJ_FLAG_HIDDEN); } } else { _hide(objects.sensors_panel); } } break; case lcolor: { _ui_set_style_text_color(objColor, color); objColor = nullptr; } break; case lrotat: { SetRotat(); } break; case llogo: { lv_image_cache_drop(nullptr); String path_img; if (player.play_type != player.LOCAL) { path_img = eeprom.GetStaLogo(eeprom.GetID()).c_str(); } else { path_img = "logo.png"; } path_img = "L:/icons/" + path_img; lv_fs_file_t f; if (lv_fs_open(&f, path_img.c_str(), LV_FS_MODE_RD)) { lv_obj_set_style_bg_color(objects.icon_ststion, lv_color_hex(0xff0000), 0); path_img = "L:/icons/logo.png"; } else { lv_obj_set_style_bg_color(objects.icon_ststion, lv_color_hex(0xff969fb1), 0); lv_fs_close(&f); } lv_image_set_src(objects.icon_ststion, path_img.c_str()); } break; case lnameset: { std::string name_sta; if (evt.value > 0) { name_sta = eeprom.GetStaName(evt.value).c_str(); } else { name_sta = _("БЕЗ ИМЕНИ"); } lv_label_set_text_fmt(objects.name_station_label, "%u: %s", evt.value, name_sta.c_str()); copyNameSta = lv_label_get_text(objects.name_station_label); } break; case lplay: currSta = eeprom.GetID(); lv_label_set_text(objects.play_state_label, " "); // Play break; case lvol: { uint8_t vol = player.getVolume(); lv_bar_set_value(objects.volume_bar, (int)vol, LV_ANIM_OFF); resetPlayWait(); lv_label_set_text(objects.numbers_panel_info_label, _("УРОВЕНЬ ГРОМКОСТИ")); lv_label_set_text_fmt(objects.numbers_panel_label, "%u", vol); _show(objects.numbers_panel_info); startPlayWait(0xFF); } break; case estation: { resetPlayWait(); if (evt.value) { currSta++; if (currSta > eeprom.GetTotalSta()) { currSta = 1; } } else if (evt.value == 0) { if (currSta > 1) { currSta--; } else { currSta = eeprom.GetTotalSta(); } } lv_label_set_text(objects.numbers_panel_info_label, _("НОМЕР СТАНЦИИ")); lv_label_set_text_fmt(objects.numbers_panel_label, "%u", currSta); _show(objects.numbers_panel_info); if (eeprom.GetID() != currSta) { lv_label_set_text_fmt(objects.name_station_label, "%d: %s", currSta, eeprom.GetStaName(currSta).c_str()); lv_label_set_text(objects.name_artist_label, ""); lv_label_set_text(objects.name_song_label, ""); } else { if (copyNameSta.length()) lv_label_set_text(objects.name_station_label, copyNameSta.c_str()); if (copyNameArtist.length()) lv_label_set_text(objects.name_artist_label, copyNameArtist.c_str()); if (copyNameSong.length()) lv_label_set_text(objects.name_song_label, copyNameSong.c_str()); } startPlayWait(currSta); } break; case setnum: { resetPlayWait(); lv_label_set_text(objects.numbers_panel_info_label, _("НОМЕР СТАНЦИИ")); lv_label_set_text(objects.numbers_panel_label, StNumStr); _show(objects.numbers_panel_info); startPlayWait(atoi(StNumStr)); } break; case lsleep: Serial.printf("lcd.SLEEP(%u)\n", evt.value); break; case lvumeter: { if (evt.value) { VUmeter_stop = false; startVUmeter(); } else { VUmeter_stop = true; } } break; case lsetwarn: if (evt.value) { start_blinking(); } else { stop_blinking(); } break; case playlist: list_station(evt.value); break; case lmenu: MainMenu(evt.value); break; case ltheme: serv.set_custom_theme(); break; case lextinfo: { if (evt.value == 0) { lv_obj_add_flag(objects.ext_info, LV_OBJ_FLAG_HIDDEN); } else { lv_label_set_text_fmt(objects.domain_label, "%s.local", ee->host.c_str()); lv_label_set_text(objects.time_zone_label, telnet.currentTZ().c_str()); lv_label_set_text_fmt(objects.total_station_label, "%u", eeprom.GetTotalSta()); lv_label_set_text(objects.curr_playlist_label, eeprom.GetCurrentPlayListName().c_str()); lv_label_set_text_fmt(objects.soft_version_label, " %d.%d.%d", VER_MAJOR, VER_MINOR, VER_PATH); lv_label_set_text_fmt(objects.soft_sdk_label, "%d.%d.%d", ESP_IDF_VERSION_MAJOR, ESP_IDF_VERSION_MINOR, ESP_IDF_VERSION_PATCH); lv_label_set_text_fmt(objects.soft_core_label, "%s", ESP_ARDUINO_VERSION_STR); lv_label_set_text_fmt(objects.soft_lvgl_label, "%d.%d.%d", lv_version_major(), lv_version_minor(), lv_version_patch()); lv_label_set_text(objects.fs_type_label, TypeFS().c_str()); lv_label_set_text(objects.fs_used_label, UsedFS().c_str()); lv_label_set_text(objects.fs_free_label, FreeFS().c_str()); lv_label_set_text(objects.fs_total_label, TotalFS().c_str()); if (Config->i2c.bmp > 0) { lv_obj_add_state(objects.bme, LV_STATE_CHECKED); if (Config->i2c.bmp == 3) { lv_checkbox_set_text(objects.bme, "BME280"); } else if (Config->i2c.bmp == 2) { lv_checkbox_set_text(objects.bme, "BMP280"); } } else { lv_obj_remove_state(objects.bme, LV_STATE_CHECKED); } if (Config->i2c.ds3231) { lv_obj_add_state(objects.dc3231, LV_STATE_CHECKED); } else { lv_obj_remove_state(objects.dc3231, LV_STATE_CHECKED); } if (Config->i2c.eeprom) { lv_obj_add_state(objects.eeprom, LV_STATE_CHECKED); } else { lv_obj_remove_state(objects.eeprom, LV_STATE_CHECKED); } if (Config->i2c.tda7313) { lv_obj_add_state(objects.tda7313, LV_STATE_CHECKED); } else { lv_obj_remove_state(objects.tda7313, LV_STATE_CHECKED); } if (!player.title[ICY_NAME].empty()) { lv_label_set_text(objects.icy_name_label, player.title[ICY_NAME].c_str()); } if (!player.title[ICY_DESCR].empty()) { lv_label_set_text(objects.icy_desc_label, player.title[ICY_DESCR].c_str()); } if (!player.title[ICY_GENGE].empty()) { lv_label_set_text(objects.icy_genre_label, player.title[ICY_GENGE].c_str()); } if (!player.title[ICY_FORMAT].empty()) { lv_label_set_text(objects.icy_format_label, player.title[ICY_FORMAT].c_str()); } if (!player.title[ICY_BITRATE].empty()) { lv_label_set_text_fmt(objects.bitrate_label, "%s", player.title[ICY_BITRATE].c_str()); } lv_obj_remove_flag(objects.ext_info, LV_OBJ_FLAG_HIDDEN); } } break; case lmute: { if (evt.value == 0) { lv_obj_add_flag(objects.mute_label, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_remove_flag(objects.mute_label, LV_OBJ_FLAG_HIDDEN); } player.mute(evt.value); } break; case lalarm: { Serial.printf("showAlarm(%u)\n", evt.value); } break; case check_format: { uint8_t format = player.checkFormat(); std::string str_format = player.getStrFormat(format); if (format > 0) { player.setTitle(ICY_FORMAT, str_format); serv.evtVUmeter(true); } else { player.title[ICY_META] = str_format; player.stop_error(); } } break; case urssi: { update_rssi(); // 5. High quality: 90% ~= -55db // 4. Good quality: 75% ~= -65db // 3. Medium quality: 50% ~= -75db // 2. Low quality: 30% ~= -85db // 1. Unusable quality: 8% ~= -96db // 0. No signal uint8_t bars = 0; uint32_t warning_color = 0xFF0000; // RED int8_t rssi = getRSSI(); if (rssi > -55) { bars = 4; warning_color = 0x00FF00; // LIME } else if ((rssi <= -55) & (rssi >= -75)) { bars = 3; warning_color = 0xADFF2F; // YellowGreen } else if ((rssi < -75) & (rssi >= -85)) { bars = 2; warning_color = 0xFFFF00; // Yellow } else if ((rssi < -85) & (rssi >= -96)) { bars = 1; warning_color = 0xFF4500; // OrangeRed } _ui_set_style_text_color(objects.wifi_label, lv_color_hex(warning_color)); _ui_set_style_text_color(objects.rssi_label, lv_color_hex(warning_color)); lv_label_set_text_fmt(objects.wifi_label, "%u", bars); lv_label_set_text_fmt(objects.rssi_label, "%d %s", rssi, _("дБм")); } break; default:; } vTaskDelay(1); } if ((event_lcd) && (!uxQueueMessagesWaiting(event_lcd))) { vTaskDelay(10); } if (xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) { if (network.state == WIFI_STA) { lv_timer_handler(); ui_tick(); } xSemaphoreGive(xGuiSemaphore); } vTaskDelay(2); } vTaskDelete(nullptr); } ////////////////////////////////////////