mirror of
https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library.git
synced 2026-03-06 16:16:56 +01:00
1962 lines
58 KiB
C++
1962 lines
58 KiB
C++
/*
|
|
Copyright (c) 2019 lewis he
|
|
This is just a demonstration. Most of the functions are not implemented.
|
|
The main implementation is low-power standby.
|
|
The off-screen standby (not deep sleep) current is about 4mA.
|
|
Select standard motherboard and standard backplane for testing.
|
|
Created by Lewis he on October 10, 2019.
|
|
*/
|
|
|
|
#include <TTGO.h>
|
|
#include <Arduino.h>
|
|
#include <time.h>
|
|
#include "gui.h"
|
|
#include <WiFi.h>
|
|
#include "string.h"
|
|
#include <Ticker.h>
|
|
#include "FS.h"
|
|
#include "SD.h"
|
|
|
|
//! lewis 2020/02/10 add 2019-nCov
|
|
#include "ArduinoJson.h"
|
|
#include "HTTPClient.h"
|
|
|
|
//! lewis 2020/02/14 add mlx90614 thermometer
|
|
#include "mlx90614.h"
|
|
|
|
|
|
#define RTC_TIME_ZONE "CST-8"
|
|
|
|
|
|
LV_FONT_DECLARE(Geometr);
|
|
LV_FONT_DECLARE(Ubuntu);
|
|
LV_IMG_DECLARE(bg);
|
|
LV_IMG_DECLARE(bg1);
|
|
LV_IMG_DECLARE(bg2);
|
|
LV_IMG_DECLARE(bg3);
|
|
LV_IMG_DECLARE(WALLPAPER_1_IMG);
|
|
LV_IMG_DECLARE(WALLPAPER_2_IMG);
|
|
LV_IMG_DECLARE(WALLPAPER_3_IMG);
|
|
LV_IMG_DECLARE(step);
|
|
LV_IMG_DECLARE(menu);
|
|
|
|
LV_IMG_DECLARE(wifi);
|
|
LV_IMG_DECLARE(light);
|
|
LV_IMG_DECLARE(bluetooth);
|
|
LV_IMG_DECLARE(sd);
|
|
LV_IMG_DECLARE(setting);
|
|
LV_IMG_DECLARE(on);
|
|
LV_IMG_DECLARE(off);
|
|
LV_IMG_DECLARE(level1);
|
|
LV_IMG_DECLARE(level2);
|
|
LV_IMG_DECLARE(level3);
|
|
LV_IMG_DECLARE(iexit);
|
|
LV_IMG_DECLARE(modules);
|
|
LV_IMG_DECLARE(CAMERA_PNG);
|
|
LV_IMG_DECLARE(nCov);
|
|
LV_FONT_DECLARE(chinese_font);
|
|
LV_FONT_DECLARE(digital_font);
|
|
LV_IMG_DECLARE(thermometer);
|
|
LV_IMG_DECLARE(qiut);
|
|
|
|
extern EventGroupHandle_t g_event_group;
|
|
extern QueueHandle_t g_event_queue_handle;
|
|
|
|
static lv_style_t settingStyle;
|
|
static lv_obj_t *mainBar = nullptr;
|
|
static lv_obj_t *timeLabel = nullptr;
|
|
static lv_obj_t *menuBtn = nullptr;
|
|
|
|
static uint8_t globalIndex = 0;
|
|
|
|
static void lv_update_task(struct _lv_task_t *);
|
|
static void lv_battery_task(struct _lv_task_t *);
|
|
static void updateTime();
|
|
static void view_event_handler(lv_obj_t *obj, lv_event_t event);
|
|
|
|
static void wifi_event_cb();
|
|
static void sd_event_cb();
|
|
static void setting_event_cb();
|
|
static void light_event_cb();
|
|
static void bluetooth_event_cb();
|
|
static void modules_event_cb();
|
|
static void camera_event_cb();
|
|
static void wifi_destory();
|
|
static void nCov_event_cb();
|
|
static void thermometer_event_cb();
|
|
|
|
class StatusBar
|
|
{
|
|
typedef struct {
|
|
bool vaild;
|
|
lv_obj_t *icon;
|
|
} lv_status_bar_t;
|
|
public:
|
|
StatusBar()
|
|
{
|
|
memset(_array, 0, sizeof(_array));
|
|
}
|
|
void createIcons(lv_obj_t *par)
|
|
{
|
|
_par = par;
|
|
|
|
static lv_style_t barStyle;
|
|
lv_style_copy(&barStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
barStyle.body.main_color = LV_COLOR_GRAY;
|
|
barStyle.body.grad_color = LV_COLOR_GRAY;
|
|
barStyle.body.opa = LV_OPA_20;
|
|
barStyle.body.radius = 0;
|
|
barStyle.body.border.color = LV_COLOR_GRAY;
|
|
barStyle.body.border.width = 0;
|
|
barStyle.body.border.opa = LV_OPA_50;
|
|
barStyle.text.color = LV_COLOR_WHITE;
|
|
barStyle.image.color = LV_COLOR_WHITE;
|
|
_bar = lv_cont_create(_par, NULL);
|
|
lv_obj_set_size(_bar, LV_HOR_RES, _barHeight);
|
|
lv_obj_set_style(_bar, &barStyle);
|
|
|
|
_array[0].icon = lv_label_create(_bar, NULL);
|
|
lv_label_set_text(_array[0].icon, "100%");
|
|
|
|
_array[1].icon = lv_img_create(_bar, NULL);
|
|
lv_img_set_src(_array[1].icon, LV_SYMBOL_BATTERY_FULL);
|
|
|
|
_array[2].icon = lv_img_create(_bar, NULL);
|
|
lv_img_set_src(_array[2].icon, LV_SYMBOL_WIFI);
|
|
lv_obj_set_hidden(_array[2].icon, true);
|
|
|
|
_array[3].icon = lv_img_create(_bar, NULL);
|
|
lv_img_set_src(_array[3].icon, LV_SYMBOL_BLUETOOTH);
|
|
lv_obj_set_hidden(_array[3].icon, true);
|
|
|
|
//step counter
|
|
_array[4].icon = lv_img_create(_bar, NULL);
|
|
lv_img_set_src(_array[4].icon, &step);
|
|
lv_obj_align(_array[4].icon, _bar, LV_ALIGN_IN_LEFT_MID, 10, 0);
|
|
|
|
_array[5].icon = lv_label_create(_bar, NULL);
|
|
lv_label_set_text(_array[5].icon, "0");
|
|
lv_obj_align(_array[5].icon, _array[4].icon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
|
|
|
refresh();
|
|
}
|
|
|
|
void setStepCounter(uint32_t counter)
|
|
{
|
|
lv_label_set_text(_array[5].icon, String(counter).c_str());
|
|
lv_obj_align(_array[5].icon, _array[4].icon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
|
}
|
|
|
|
void updateLevel(int level)
|
|
{
|
|
lv_label_set_text(_array[0].icon, (String(level) + "%").c_str());
|
|
refresh();
|
|
}
|
|
|
|
void updateBatteryIcon(lv_icon_battery_t icon)
|
|
{
|
|
const char *icons[6] = {LV_SYMBOL_BATTERY_EMPTY, LV_SYMBOL_BATTERY_1, LV_SYMBOL_BATTERY_2, LV_SYMBOL_BATTERY_3, LV_SYMBOL_BATTERY_FULL, LV_SYMBOL_CHARGE};
|
|
lv_img_set_src(_array[1].icon, icons[icon]);
|
|
refresh();
|
|
}
|
|
|
|
void show(lv_icon_status_bar_t icon)
|
|
{
|
|
lv_obj_set_hidden(_array[icon].icon, false);
|
|
refresh();
|
|
}
|
|
|
|
void hidden(lv_icon_status_bar_t icon)
|
|
{
|
|
lv_obj_set_hidden(_array[icon].icon, true);
|
|
refresh();
|
|
}
|
|
uint8_t height()
|
|
{
|
|
return _barHeight;
|
|
}
|
|
lv_obj_t *self()
|
|
{
|
|
return _bar;
|
|
}
|
|
private:
|
|
void refresh()
|
|
{
|
|
int prev;
|
|
for (int i = 0; i < 4; i++) {
|
|
if (!lv_obj_get_hidden(_array[i].icon)) {
|
|
if (i == LV_STATUS_BAR_BATTERY_LEVEL) {
|
|
lv_obj_align(_array[i].icon, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0);
|
|
} else {
|
|
lv_obj_align(_array[i].icon, _array[prev].icon, LV_ALIGN_OUT_LEFT_MID, iconOffset, 0);
|
|
}
|
|
prev = i;
|
|
}
|
|
}
|
|
};
|
|
lv_obj_t *_bar = nullptr;
|
|
lv_obj_t *_par = nullptr;
|
|
uint8_t _barHeight = 30;
|
|
lv_status_bar_t _array[6];
|
|
const int8_t iconOffset = -5;
|
|
};
|
|
|
|
|
|
|
|
class MenuBar
|
|
{
|
|
public:
|
|
typedef struct {
|
|
const char *name;
|
|
void *img;
|
|
void (*event_cb)();
|
|
} lv_menu_config_t;
|
|
|
|
MenuBar()
|
|
{
|
|
_cont = nullptr;
|
|
_view = nullptr;
|
|
_exit = nullptr;
|
|
_obj = nullptr;
|
|
_vp = nullptr;
|
|
};
|
|
~MenuBar() {};
|
|
|
|
void createMenu(lv_menu_config_t *config, int count, lv_event_cb_t event_cb, int direction = 1)
|
|
{
|
|
static lv_style_t menuStyle;
|
|
lv_style_copy(&menuStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
menuStyle.body.main_color = LV_COLOR_GRAY;
|
|
menuStyle.body.grad_color = LV_COLOR_GRAY;
|
|
menuStyle.body.opa = LV_OPA_0;
|
|
menuStyle.body.radius = 0;
|
|
menuStyle.body.border.color = LV_COLOR_GRAY;
|
|
menuStyle.body.border.width = 0;
|
|
menuStyle.body.border.opa = LV_OPA_50;
|
|
menuStyle.text.color = LV_COLOR_WHITE;
|
|
menuStyle.image.color = LV_COLOR_WHITE;
|
|
|
|
|
|
_count = count;
|
|
|
|
_vp = new lv_point_t [count];
|
|
|
|
_obj = new lv_obj_t *[count];
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
if (direction) {
|
|
_vp[i].x = 0;
|
|
_vp[i].y = i;
|
|
} else {
|
|
_vp[i].x = i;
|
|
_vp[i].y = 0;
|
|
}
|
|
}
|
|
|
|
_cont = lv_cont_create(lv_scr_act(), NULL);
|
|
lv_obj_set_size(_cont, LV_HOR_RES, LV_VER_RES - 30);
|
|
lv_obj_align(_cont, NULL, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
|
lv_obj_set_style(_cont, &menuStyle);
|
|
|
|
_view = lv_tileview_create(_cont, NULL);
|
|
lv_tileview_set_valid_positions(_view, _vp, count );
|
|
lv_tileview_set_edge_flash(_view, false);
|
|
lv_obj_align(_view, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
lv_tileview_set_style(_view, LV_TILEVIEW_STYLE_MAIN, &menuStyle);
|
|
lv_page_set_sb_mode(_view, LV_SB_MODE_OFF);
|
|
|
|
lv_coord_t _w = lv_obj_get_width(_view) ;
|
|
lv_coord_t _h = lv_obj_get_height(_view);
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
_obj[i] = lv_cont_create(_view, _view);
|
|
lv_obj_set_size(_obj[i], _w, _h);
|
|
|
|
lv_obj_t *img = lv_img_create(_obj[i], NULL);
|
|
lv_img_set_src(img, config[i].img);
|
|
lv_obj_align(img, _obj[i], LV_ALIGN_CENTER, 0, 0);
|
|
|
|
lv_obj_t *label = lv_label_create(_obj[i], NULL);
|
|
lv_label_set_text(label, config[i].name);
|
|
lv_obj_align(label, img, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
|
|
|
|
|
i == 0 ? lv_obj_align(_obj[i], NULL, LV_ALIGN_CENTER, 0, 0) : lv_obj_align(_obj[i], _obj[i - 1], direction ? LV_ALIGN_OUT_BOTTOM_MID : LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
|
|
|
lv_tileview_add_element(_view, _obj[i]);
|
|
lv_obj_set_click(_obj[i], true);
|
|
lv_obj_set_event_cb(_obj[i], event_cb);
|
|
}
|
|
|
|
_exit = lv_imgbtn_create(lv_scr_act(), NULL);
|
|
lv_imgbtn_set_src(_exit, LV_BTN_STATE_REL, &menu);
|
|
lv_imgbtn_set_src(_exit, LV_BTN_STATE_PR, &menu);
|
|
lv_imgbtn_set_src(_exit, LV_BTN_STATE_TGL_REL, &menu);
|
|
lv_imgbtn_set_src(_exit, LV_BTN_STATE_TGL_PR, &menu);
|
|
lv_obj_align(_exit, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -20, -20);
|
|
lv_obj_set_event_cb(_exit, event_cb);
|
|
lv_obj_set_top(_exit, true);
|
|
}
|
|
lv_obj_t *exitBtn() const
|
|
{
|
|
return _exit;
|
|
}
|
|
lv_obj_t *self() const
|
|
{
|
|
return _cont;
|
|
}
|
|
void hidden(bool en = true)
|
|
{
|
|
lv_obj_set_hidden(_cont, en);
|
|
lv_obj_set_hidden(_exit, en);
|
|
}
|
|
lv_obj_t *obj(int index) const
|
|
{
|
|
if (index > _count)return nullptr;
|
|
return _obj[index];
|
|
}
|
|
private:
|
|
lv_obj_t *_cont, *_view, *_exit, * *_obj;
|
|
lv_point_t *_vp ;
|
|
int _count = 0;
|
|
};
|
|
|
|
MenuBar::lv_menu_config_t _cfg[] = {
|
|
{.name = "WiFi", .img = (void *) &wifi, .event_cb = wifi_event_cb},
|
|
{.name = "nCov", .img = (void *) &nCov, .event_cb = nCov_event_cb},
|
|
{.name = "Thermometer", .img = (void *) &thermometer, .event_cb = thermometer_event_cb},
|
|
{.name = "Bluetooth", .img = (void *) &bluetooth, /*.event_cb = bluetooth_event_cb*/},
|
|
{.name = "SD Card", .img = (void *) &sd, /*.event_cb =sd_event_cb*/},
|
|
{.name = "Light", .img = (void *) &light, /*.event_cb = light_event_cb*/},
|
|
{.name = "Setting", .img = (void *) &setting, /*.event_cb = setting_event_cb */},
|
|
{.name = "Modules", .img = (void *) &modules, /*.event_cb = modules_event_cb */},
|
|
{.name = "Camera", .img = (void *) &CAMERA_PNG, /*.event_cb = camera_event_cb*/ },
|
|
};
|
|
|
|
|
|
MenuBar menuBars;
|
|
StatusBar bar;
|
|
|
|
static void event_handler(lv_obj_t *obj, lv_event_t event)
|
|
{
|
|
if (event == LV_EVENT_SHORT_CLICKED) { //! Event callback Is in here
|
|
if (obj == menuBtn) {
|
|
lv_obj_set_hidden(mainBar, true);
|
|
if (menuBars.self() == nullptr) {
|
|
menuBars.createMenu(_cfg, sizeof(_cfg) / sizeof(_cfg[0]), view_event_handler);
|
|
lv_obj_align(menuBars.self(), bar.self(), LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
|
|
|
} else {
|
|
menuBars.hidden(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void setupGui()
|
|
{
|
|
lv_style_copy(&settingStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
settingStyle.body.main_color = LV_COLOR_GRAY;
|
|
settingStyle.body.grad_color = LV_COLOR_GRAY;
|
|
settingStyle.body.opa = LV_OPA_0;
|
|
settingStyle.body.radius = 0;
|
|
settingStyle.body.border.color = LV_COLOR_GRAY;
|
|
settingStyle.body.border.width = 0;
|
|
settingStyle.body.border.opa = LV_OPA_50;
|
|
settingStyle.text.color = LV_COLOR_WHITE;
|
|
settingStyle.image.color = LV_COLOR_WHITE;
|
|
|
|
//Create wallpaper
|
|
void *images[] = {(void *) &bg, (void *) &bg1, (void *) &bg2, (void *) &bg3 };
|
|
lv_obj_t *scr = lv_scr_act();
|
|
lv_obj_t *img_bin = lv_img_create(scr, NULL); /*Create an image object*/
|
|
srand((int)time(0));
|
|
int r = rand() % 4;
|
|
lv_img_set_src(img_bin, images[r]);
|
|
lv_obj_align(img_bin, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
|
|
//! bar
|
|
bar.createIcons(scr);
|
|
updateBatteryLevel();
|
|
lv_icon_battery_t icon = LV_ICON_CALCULATION;
|
|
|
|
TTGOClass *ttgo = TTGOClass::getWatch();
|
|
|
|
if (ttgo->power->isChargeing()) {
|
|
icon = LV_ICON_CHARGE;
|
|
}
|
|
updateBatteryIcon(icon);
|
|
|
|
//! main
|
|
static lv_style_t mainStyle;
|
|
lv_style_copy(&mainStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
mainStyle.body.main_color = LV_COLOR_GRAY;
|
|
mainStyle.body.grad_color = LV_COLOR_GRAY;
|
|
mainStyle.body.opa = LV_OPA_0;
|
|
mainStyle.body.radius = 0;
|
|
mainStyle.body.border.color = LV_COLOR_GRAY;
|
|
mainStyle.body.border.width = 0;
|
|
mainStyle.body.border.opa = LV_OPA_50;
|
|
mainStyle.text.color = LV_COLOR_WHITE;
|
|
mainStyle.image.color = LV_COLOR_WHITE;
|
|
mainBar = lv_cont_create(scr, NULL);
|
|
lv_obj_set_size(mainBar, LV_HOR_RES, LV_VER_RES - bar.height());
|
|
lv_obj_set_style(mainBar, &mainStyle);
|
|
lv_obj_align(mainBar, bar.self(), LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
|
|
|
//! Time
|
|
static lv_style_t timeStyle;
|
|
lv_style_copy(&timeStyle, &mainStyle);
|
|
timeStyle.text.font = &Ubuntu;
|
|
|
|
timeLabel = lv_label_create(mainBar, NULL);
|
|
lv_label_set_style(timeLabel, LV_LABEL_STYLE_MAIN, &timeStyle);
|
|
updateTime();
|
|
|
|
//! menu
|
|
static lv_style_t style_pr;
|
|
lv_style_copy(&style_pr, &lv_style_plain);
|
|
style_pr.image.color = LV_COLOR_BLACK;
|
|
style_pr.image.intense = LV_OPA_50;
|
|
style_pr.text.color = lv_color_hex3(0xaaa);
|
|
|
|
menuBtn = lv_imgbtn_create(mainBar, NULL);
|
|
lv_imgbtn_set_src(menuBtn, LV_BTN_STATE_REL, &menu);
|
|
lv_imgbtn_set_src(menuBtn, LV_BTN_STATE_PR, &menu);
|
|
lv_imgbtn_set_src(menuBtn, LV_BTN_STATE_TGL_REL, &menu);
|
|
lv_imgbtn_set_src(menuBtn, LV_BTN_STATE_TGL_PR, &menu);
|
|
lv_imgbtn_set_style(menuBtn, LV_BTN_STATE_PR, &style_pr);
|
|
lv_obj_align(menuBtn, mainBar, LV_ALIGN_OUT_BOTTOM_MID, 0, -70);
|
|
lv_obj_set_event_cb(menuBtn, event_handler);
|
|
|
|
lv_task_create(lv_update_task, 1000, LV_TASK_PRIO_LOWEST, NULL);
|
|
lv_task_create(lv_battery_task, 30000, LV_TASK_PRIO_LOWEST, NULL);
|
|
}
|
|
|
|
void updateStepCounter(uint32_t counter)
|
|
{
|
|
bar.setStepCounter(counter);
|
|
}
|
|
|
|
static void updateTime()
|
|
{
|
|
time_t now;
|
|
struct tm info;
|
|
char buf[64];
|
|
time(&now);
|
|
localtime_r(&now, &info);
|
|
strftime(buf, sizeof(buf), "%H:%M", &info);
|
|
lv_label_set_text(timeLabel, buf);
|
|
lv_obj_align(timeLabel, NULL, LV_ALIGN_IN_TOP_MID, 0, 20);
|
|
}
|
|
|
|
void updateBatteryLevel()
|
|
{
|
|
TTGOClass *ttgo = TTGOClass::getWatch();
|
|
int p = ttgo->power->getBattPercentage();
|
|
bar.updateLevel(p);
|
|
}
|
|
|
|
void updateBatteryIcon(lv_icon_battery_t icon)
|
|
{
|
|
if (icon >= LV_ICON_CALCULATION) {
|
|
TTGOClass *ttgo = TTGOClass::getWatch();
|
|
int level = ttgo->power->getBattPercentage();
|
|
if (level > 95)icon = LV_ICON_BAT_FULL;
|
|
else if (level > 80)icon = LV_ICON_BAT_3;
|
|
else if (level > 45)icon = LV_ICON_BAT_2;
|
|
else if (level > 20)icon = LV_ICON_BAT_1;
|
|
else icon = LV_ICON_BAT_EMPTY;
|
|
}
|
|
bar.updateBatteryIcon(icon);
|
|
}
|
|
|
|
|
|
static void lv_update_task(struct _lv_task_t *data)
|
|
{
|
|
updateTime();
|
|
}
|
|
|
|
static void lv_battery_task(struct _lv_task_t *data)
|
|
{
|
|
updateBatteryLevel();
|
|
}
|
|
|
|
static void view_event_handler(lv_obj_t *obj, lv_event_t event)
|
|
{
|
|
int size = sizeof(_cfg) / sizeof(_cfg[0]);
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
if (obj == menuBars.exitBtn()) {
|
|
menuBars.hidden();
|
|
lv_obj_set_hidden(mainBar, false);
|
|
return;
|
|
}
|
|
for (int i = 0; i < size; i++) {
|
|
if (obj == menuBars.obj(i)) {
|
|
if (_cfg[i].event_cb != nullptr) {
|
|
menuBars.hidden();
|
|
_cfg[i].event_cb();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! Keyboard Class
|
|
*
|
|
*/
|
|
|
|
|
|
class Keyboard
|
|
{
|
|
public:
|
|
typedef enum {
|
|
KB_EVENT_OK,
|
|
KB_EVENT_EXIT,
|
|
} kb_event_t;
|
|
|
|
typedef void (*kb_event_cb)(kb_event_t event);
|
|
|
|
Keyboard()
|
|
{
|
|
_kbCont = nullptr;
|
|
};
|
|
|
|
~Keyboard()
|
|
{
|
|
if (_kbCont)
|
|
lv_obj_del(_kbCont);
|
|
_kbCont = nullptr;
|
|
};
|
|
|
|
void create(lv_obj_t *parent = nullptr)
|
|
{
|
|
static lv_style_t kbStyle;
|
|
lv_style_copy(&kbStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
kbStyle.body.main_color = LV_COLOR_GRAY;
|
|
kbStyle.body.grad_color = LV_COLOR_GRAY;
|
|
kbStyle.body.opa = LV_OPA_0;
|
|
kbStyle.body.radius = 0;
|
|
kbStyle.body.border.color = LV_COLOR_GRAY;
|
|
kbStyle.body.border.width = 0;
|
|
kbStyle.body.border.opa = LV_OPA_50;
|
|
kbStyle.text.color = LV_COLOR_WHITE;
|
|
kbStyle.image.color = LV_COLOR_WHITE;
|
|
|
|
if (parent == nullptr) {
|
|
parent = lv_scr_act();
|
|
}
|
|
|
|
_kbCont = lv_cont_create(parent, NULL);
|
|
lv_obj_set_size(_kbCont, LV_HOR_RES, LV_VER_RES - 30);
|
|
lv_obj_align(_kbCont, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
lv_obj_set_style(_kbCont, &kbStyle);
|
|
|
|
lv_obj_t *ta = lv_ta_create(_kbCont, NULL);
|
|
lv_obj_set_height(ta, 40);
|
|
lv_ta_set_one_line(ta, true);
|
|
lv_ta_set_pwd_mode(ta, false);
|
|
lv_ta_set_text(ta, "");
|
|
lv_obj_align(ta, _kbCont, LV_ALIGN_IN_TOP_MID, 0, 10);
|
|
|
|
lv_obj_t *kb = lv_kb_create(_kbCont, NULL);
|
|
lv_kb_set_map(kb, btnm_mapplus[0]);
|
|
lv_obj_set_height(kb, LV_VER_RES / 3 * 2);
|
|
lv_obj_align(kb, _kbCont, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
|
|
lv_kb_set_ta(kb, ta);
|
|
|
|
lv_obj_set_style(ta, &kbStyle);
|
|
lv_obj_set_style(kb, &kbStyle);
|
|
lv_obj_set_event_cb(kb, __kb_event_cb);
|
|
|
|
_kb = this;
|
|
}
|
|
|
|
void align(const lv_obj_t *base, lv_align_t align, lv_coord_t x = 0, lv_coord_t y = 0)
|
|
{
|
|
lv_obj_align(_kbCont, base, align, x, y);
|
|
}
|
|
|
|
static void __kb_event_cb(lv_obj_t *kb, lv_event_t event)
|
|
{
|
|
if (event != LV_EVENT_VALUE_CHANGED && event != LV_EVENT_LONG_PRESSED_REPEAT) return;
|
|
lv_kb_ext_t *ext = (lv_kb_ext_t *)lv_obj_get_ext_attr(kb);
|
|
const char *txt = lv_btnm_get_active_btn_text(kb);
|
|
if (txt == NULL) return;
|
|
static int index = 0;
|
|
if (strcmp(txt, LV_SYMBOL_OK) == 0) {
|
|
strcpy(__buf, lv_ta_get_text(ext->ta));
|
|
if (_kb->_cb != nullptr) {
|
|
_kb->_cb(KB_EVENT_OK);
|
|
}
|
|
return;
|
|
} else if (strcmp(txt, "Exit") == 0) {
|
|
if (_kb->_cb != nullptr) {
|
|
_kb->_cb(KB_EVENT_EXIT);
|
|
}
|
|
return;
|
|
} else if (strcmp(txt, LV_SYMBOL_RIGHT) == 0) {
|
|
index = index + 1 >= sizeof(btnm_mapplus) / sizeof(btnm_mapplus[0]) ? 0 : index + 1;
|
|
lv_kb_set_map(kb, btnm_mapplus[index]);
|
|
return;
|
|
} else if (strcmp(txt, "Del") == 0) {
|
|
lv_ta_del_char(ext->ta);
|
|
} else {
|
|
lv_ta_add_text(ext->ta, txt);
|
|
}
|
|
}
|
|
|
|
void setKeyboardEvent(kb_event_cb cb)
|
|
{
|
|
_cb = cb;
|
|
}
|
|
|
|
const char *getText()
|
|
{
|
|
return (const char *)__buf;
|
|
}
|
|
|
|
void hidden(bool en = true)
|
|
{
|
|
lv_obj_set_hidden(_kbCont, en);
|
|
}
|
|
|
|
private:
|
|
lv_obj_t *_kbCont = nullptr;
|
|
kb_event_cb _cb = nullptr;
|
|
static const char *btnm_mapplus[10][23];
|
|
static Keyboard *_kb;
|
|
static char __buf[128];
|
|
};
|
|
char Keyboard::__buf[128];
|
|
Keyboard *Keyboard::_kb = nullptr;
|
|
const char *Keyboard::btnm_mapplus[10][23] = {
|
|
{
|
|
"a", "b", "c", "\n",
|
|
"d", "e", "f", "\n",
|
|
"g", "h", "i", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"j", "k", "l", "\n",
|
|
"n", "m", "o", "\n",
|
|
"p", "q", "r", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"s", "t", "u", "\n",
|
|
"v", "w", "x", "\n",
|
|
"y", "z", " ", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"A", "B", "C", "\n",
|
|
"D", "E", "F", "\n",
|
|
"G", "H", "I", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"J", "K", "L", "\n",
|
|
"N", "M", "O", "\n",
|
|
"P", "Q", "R", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"S", "T", "U", "\n",
|
|
"V", "W", "X", "\n",
|
|
"Y", "Z", " ", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"1", "2", "3", "\n",
|
|
"4", "5", "6", "\n",
|
|
"7", "8", "9", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"0", "+", "-", "\n",
|
|
"/", "*", "=", "\n",
|
|
"!", "?", "#", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"<", ">", "@", "\n",
|
|
"%", "$", "(", "\n",
|
|
")", "{", "}", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
},
|
|
{
|
|
"[", "]", ";", "\n",
|
|
"\"", "'", ".", "\n",
|
|
",", ":", " ", "\n",
|
|
LV_SYMBOL_OK, "Del", "Exit", LV_SYMBOL_RIGHT, ""
|
|
}
|
|
};
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! Switch Class
|
|
*
|
|
*/
|
|
class Switch
|
|
{
|
|
public:
|
|
typedef struct {
|
|
const char *name;
|
|
void (*cb)(uint8_t, bool);
|
|
} switch_cfg_t;
|
|
|
|
typedef void (*exit_cb)();
|
|
Switch()
|
|
{
|
|
_swCont = nullptr;
|
|
}
|
|
~Switch()
|
|
{
|
|
if (_swCont)
|
|
lv_obj_del(_swCont);
|
|
_swCont = nullptr;
|
|
}
|
|
|
|
void create(switch_cfg_t *cfg, uint8_t count, exit_cb cb, lv_obj_t *parent = nullptr)
|
|
{
|
|
static lv_style_t swlStyle;
|
|
lv_style_copy(&swlStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
swlStyle.body.main_color = LV_COLOR_GRAY;
|
|
swlStyle.body.grad_color = LV_COLOR_GRAY;
|
|
swlStyle.body.opa = LV_OPA_0;
|
|
swlStyle.body.radius = 0;
|
|
swlStyle.body.border.color = LV_COLOR_GRAY;
|
|
swlStyle.body.border.width = 0;
|
|
swlStyle.body.border.opa = LV_OPA_50;
|
|
swlStyle.text.color = LV_COLOR_WHITE;
|
|
swlStyle.image.color = LV_COLOR_WHITE;
|
|
|
|
if (parent == nullptr) {
|
|
parent = lv_scr_act();
|
|
}
|
|
_exit_cb = cb;
|
|
|
|
_swCont = lv_cont_create(parent, NULL);
|
|
lv_obj_set_size(_swCont, LV_HOR_RES, LV_VER_RES - 30);
|
|
lv_obj_align(_swCont, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
lv_obj_set_style(_swCont, &swlStyle);
|
|
|
|
_count = count;
|
|
_sw = new lv_obj_t *[count];
|
|
_cfg = new switch_cfg_t [count];
|
|
|
|
memcpy(_cfg, cfg, sizeof(switch_cfg_t) * count);
|
|
|
|
lv_obj_t *prev = nullptr;
|
|
for (int i = 0; i < count; i++) {
|
|
lv_obj_t *la1 = lv_label_create(_swCont, NULL);
|
|
lv_label_set_text(la1, cfg[i].name);
|
|
i == 0 ? lv_obj_align(la1, NULL, LV_ALIGN_IN_TOP_LEFT, 30, 20) : lv_obj_align(la1, prev, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
|
|
_sw[i] = lv_imgbtn_create(_swCont, NULL);
|
|
lv_imgbtn_set_src(_sw[i], LV_BTN_STATE_REL, &off);
|
|
lv_imgbtn_set_src(_sw[i], LV_BTN_STATE_PR, &off);
|
|
lv_imgbtn_set_src(_sw[i], LV_BTN_STATE_TGL_REL, &off);
|
|
lv_imgbtn_set_src(_sw[i], LV_BTN_STATE_TGL_PR, &off);
|
|
lv_imgbtn_set_toggle(_sw[i], true);
|
|
lv_obj_align(_sw[i], la1, LV_ALIGN_OUT_RIGHT_MID, 80, 0);
|
|
lv_obj_set_event_cb(_sw[i], __switch_event_cb);
|
|
prev = la1;
|
|
}
|
|
|
|
_exitBtn = lv_imgbtn_create(_swCont, NULL);
|
|
lv_imgbtn_set_src(_exitBtn, LV_BTN_STATE_REL, &iexit);
|
|
lv_imgbtn_set_src(_exitBtn, LV_BTN_STATE_PR, &iexit);
|
|
lv_imgbtn_set_src(_exitBtn, LV_BTN_STATE_TGL_REL, &iexit);
|
|
lv_imgbtn_set_src(_exitBtn, LV_BTN_STATE_TGL_PR, &iexit);
|
|
lv_obj_align(_exitBtn, _swCont, LV_ALIGN_IN_BOTTOM_MID, 0, -5);
|
|
lv_obj_set_event_cb(_exitBtn, __switch_event_cb);
|
|
|
|
_switch = this;
|
|
}
|
|
|
|
void align(const lv_obj_t *base, lv_align_t align, lv_coord_t x = 0, lv_coord_t y = 0)
|
|
{
|
|
lv_obj_align(_swCont, base, align, x, y);
|
|
}
|
|
|
|
void hidden(bool en = true)
|
|
{
|
|
lv_obj_set_hidden(_swCont, en);
|
|
}
|
|
|
|
static void __switch_event_cb(lv_obj_t *obj, lv_event_t event)
|
|
{
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
if (obj == _switch->_exitBtn) {
|
|
if ( _switch->_exit_cb != nullptr) {
|
|
_switch->_exit_cb();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (event == LV_EVENT_VALUE_CHANGED) {
|
|
for (int i = 0; i < _switch->_count ; i++) {
|
|
lv_obj_t *sw = _switch->_sw[i];
|
|
if (obj == sw) {
|
|
const void *src = lv_imgbtn_get_src(sw, LV_BTN_STATE_REL);
|
|
const void *dst = src == &off ? &on : &off;
|
|
bool en = src == &off;
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_REL, dst);
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_PR, dst);
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_TGL_REL, dst);
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_TGL_PR, dst);
|
|
if (_switch->_cfg[i].cb != nullptr) {
|
|
_switch->_cfg[i].cb(i, en);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void setStatus(uint8_t index, bool en)
|
|
{
|
|
if (index > _count)return;
|
|
lv_obj_t *sw = _sw[index];
|
|
const void *dst = en ? &on : &off;
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_REL, dst);
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_PR, dst);
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_TGL_REL, dst);
|
|
lv_imgbtn_set_src(sw, LV_BTN_STATE_TGL_PR, dst);
|
|
}
|
|
|
|
private:
|
|
static Switch *_switch;
|
|
lv_obj_t *_swCont = nullptr;
|
|
uint8_t _count;
|
|
lv_obj_t **_sw = nullptr;
|
|
switch_cfg_t *_cfg = nullptr;
|
|
lv_obj_t *_exitBtn = nullptr;
|
|
exit_cb _exit_cb = nullptr;
|
|
};
|
|
|
|
Switch *Switch::_switch = nullptr;
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! Preload Class
|
|
*
|
|
*/
|
|
class Preload
|
|
{
|
|
public:
|
|
Preload()
|
|
{
|
|
_preloadCont = nullptr;
|
|
}
|
|
~Preload()
|
|
{
|
|
if (_preloadCont == nullptr) return;
|
|
lv_obj_del(_preloadCont);
|
|
_preloadCont = nullptr;
|
|
}
|
|
void create(lv_obj_t *parent = nullptr)
|
|
{
|
|
if (parent == nullptr) {
|
|
parent = lv_scr_act();
|
|
}
|
|
if (_preloadCont == nullptr) {
|
|
static lv_style_t plStyle;
|
|
lv_style_copy(&plStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
plStyle.body.main_color = LV_COLOR_GRAY;
|
|
plStyle.body.grad_color = LV_COLOR_GRAY;
|
|
plStyle.body.opa = LV_OPA_0;
|
|
plStyle.body.radius = 0;
|
|
plStyle.body.border.color = LV_COLOR_GRAY;
|
|
plStyle.body.border.width = 0;
|
|
plStyle.body.border.opa = LV_OPA_50;
|
|
plStyle.text.color = LV_COLOR_WHITE;
|
|
plStyle.image.color = LV_COLOR_WHITE;
|
|
|
|
static lv_style_t style;
|
|
lv_style_copy(&style, &lv_style_plain);
|
|
style.line.width = 10; /*10 px thick arc*/
|
|
style.line.color = LV_COLOR_GREEN; /*Blueish arc color*/
|
|
style.body.border.color = LV_COLOR_WHITE; /*Gray background color*/
|
|
style.body.border.width = 10;
|
|
style.body.padding.left = 0;
|
|
_preloadCont = lv_cont_create(parent, NULL);
|
|
lv_obj_set_size(_preloadCont, LV_HOR_RES, LV_VER_RES - 30);
|
|
lv_obj_align(_preloadCont, NULL, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
|
lv_obj_set_style(_preloadCont, &plStyle);
|
|
|
|
lv_obj_t *preload = lv_preload_create(_preloadCont, NULL);
|
|
lv_obj_set_size(preload, lv_obj_get_width(_preloadCont) / 2, lv_obj_get_height(_preloadCont) / 2);
|
|
lv_preload_set_style(preload, LV_PRELOAD_STYLE_MAIN, &style);
|
|
lv_obj_align(preload, _preloadCont, LV_ALIGN_CENTER, 0, 0);
|
|
}
|
|
}
|
|
void align(const lv_obj_t *base, lv_align_t align, lv_coord_t x = 0, lv_coord_t y = 0)
|
|
{
|
|
lv_obj_align(_preloadCont, base, align, x, y);
|
|
}
|
|
|
|
void hidden(bool en = true)
|
|
{
|
|
lv_obj_set_hidden(_preloadCont, en);
|
|
}
|
|
|
|
private:
|
|
lv_obj_t *_preloadCont = nullptr;
|
|
};
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! List Class
|
|
*
|
|
*/
|
|
|
|
class List
|
|
{
|
|
public:
|
|
typedef void(*list_event_cb)(const char *);
|
|
List()
|
|
{
|
|
}
|
|
~List()
|
|
{
|
|
if (_listCont == nullptr) return;
|
|
lv_obj_del(_listCont);
|
|
_listCont = nullptr;
|
|
}
|
|
void create(lv_obj_t *parent = nullptr, lv_style_t *style = nullptr)
|
|
{
|
|
if (parent == nullptr) {
|
|
parent = lv_scr_act();
|
|
}
|
|
if (_listCont == nullptr) {
|
|
static lv_style_t listStyle;
|
|
|
|
if (style != nullptr) {
|
|
lv_style_copy(&listStyle, style);
|
|
} else {
|
|
lv_style_copy(&listStyle, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
listStyle.body.main_color = LV_COLOR_GRAY;
|
|
listStyle.body.grad_color = LV_COLOR_GRAY;
|
|
listStyle.body.opa = LV_OPA_0;
|
|
listStyle.body.radius = 0;
|
|
listStyle.body.border.color = LV_COLOR_GRAY;
|
|
listStyle.body.border.width = 0;
|
|
listStyle.body.border.opa = LV_OPA_50;
|
|
listStyle.text.color = LV_COLOR_WHITE;
|
|
listStyle.image.color = LV_COLOR_WHITE;
|
|
listStyle.text.font = &chinese_font;
|
|
}
|
|
|
|
_listCont = lv_list_create(lv_scr_act(), NULL);
|
|
lv_obj_set_size(_listCont, LV_HOR_RES, LV_VER_RES - 30);
|
|
lv_list_set_style(_listCont, LV_LIST_STYLE_BG, &listStyle);
|
|
lv_obj_align(_listCont, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
}
|
|
_list = this;
|
|
}
|
|
//! lewis add
|
|
void setStyle( lv_list_style_t type, lv_style_t *style)
|
|
{
|
|
lv_list_set_style(_listCont, type, style);
|
|
}
|
|
//! lewis
|
|
lv_obj_t *add(const char *txt, void *imgsrc = (void *)LV_SYMBOL_WIFI)
|
|
{
|
|
lv_obj_t *btn = lv_list_add_btn(_listCont, imgsrc, txt);
|
|
lv_obj_set_event_cb(btn, __list_event_cb);
|
|
return btn;
|
|
}
|
|
|
|
void align(const lv_obj_t *base, lv_align_t align, lv_coord_t x = 0, lv_coord_t y = 0)
|
|
{
|
|
lv_obj_align(_listCont, base, align, x, y);
|
|
}
|
|
|
|
void hidden(bool en = true)
|
|
{
|
|
lv_obj_set_hidden(_listCont, en);
|
|
}
|
|
|
|
static void __list_event_cb(lv_obj_t *obj, lv_event_t event)
|
|
{
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
const char *txt = lv_list_get_btn_text(obj);
|
|
if (_list->_cb != nullptr) {
|
|
_list->_cb(txt);
|
|
}
|
|
}
|
|
}
|
|
void setListCb(list_event_cb cb)
|
|
{
|
|
_cb = cb;
|
|
}
|
|
private:
|
|
lv_obj_t *_listCont = nullptr;
|
|
static List *_list ;
|
|
list_event_cb _cb = nullptr;
|
|
};
|
|
List *List::_list = nullptr;
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! Task Class
|
|
*
|
|
*/
|
|
class Task
|
|
{
|
|
public:
|
|
Task()
|
|
{
|
|
_handler = nullptr;
|
|
_cb = nullptr;
|
|
}
|
|
~Task()
|
|
{
|
|
if ( _handler == nullptr)return;
|
|
Serial.println("Free Task Func");
|
|
lv_task_del(_handler);
|
|
_handler = nullptr;
|
|
_cb = nullptr;
|
|
}
|
|
|
|
void create(lv_task_cb_t cb, uint32_t period = 1000, lv_task_prio_t prio = LV_TASK_PRIO_LOW)
|
|
{
|
|
_handler = lv_task_create(cb, period, prio, NULL);
|
|
};
|
|
|
|
private:
|
|
lv_task_t *_handler = nullptr;
|
|
lv_task_cb_t _cb = nullptr;
|
|
};
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! MesBox Class
|
|
*
|
|
*/
|
|
|
|
class MBox
|
|
{
|
|
public:
|
|
MBox()
|
|
{
|
|
_mbox = nullptr;
|
|
}
|
|
~MBox()
|
|
{
|
|
if (_mbox == nullptr)return;
|
|
lv_obj_del(_mbox);
|
|
_mbox = nullptr;
|
|
}
|
|
|
|
void create(const char *text, lv_event_cb_t event_cb, const char **btns = nullptr, lv_obj_t *par = nullptr)
|
|
{
|
|
if (_mbox != nullptr)return;
|
|
lv_obj_t *p = par == nullptr ? lv_scr_act() : par;
|
|
_mbox = lv_mbox_create(p, NULL);
|
|
lv_mbox_set_text(_mbox, text);
|
|
if (btns == nullptr) {
|
|
static const char *defBtns[] = {"Ok", ""};
|
|
lv_mbox_add_btns(_mbox, defBtns);
|
|
} else {
|
|
lv_mbox_add_btns(_mbox, btns);
|
|
}
|
|
lv_obj_set_width(_mbox, LV_HOR_RES - 40);
|
|
lv_obj_set_event_cb(_mbox, event_cb);
|
|
lv_obj_align(_mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
}
|
|
|
|
void setData(void *data)
|
|
{
|
|
lv_obj_set_user_data(_mbox, data);
|
|
}
|
|
|
|
void *getData()
|
|
{
|
|
return lv_obj_get_user_data(_mbox);
|
|
}
|
|
|
|
void setBtn(const char **btns)
|
|
{
|
|
lv_mbox_add_btns(_mbox, btns);
|
|
}
|
|
|
|
private:
|
|
lv_obj_t *_mbox = nullptr;
|
|
};
|
|
|
|
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! GLOBAL VALUE
|
|
*
|
|
*/
|
|
static Keyboard *kb = nullptr;
|
|
static Switch *sw = nullptr;
|
|
static Preload *pl = nullptr;
|
|
static List *list = nullptr;
|
|
static Task *task = nullptr;
|
|
static Ticker *gTicker = nullptr;
|
|
static MBox *mbox = nullptr;
|
|
|
|
static char ssid[64], password[64];
|
|
|
|
/*****************************************************************
|
|
*
|
|
* !WIFI EVENT
|
|
*
|
|
*/
|
|
void wifi_connect_status(bool result)
|
|
{
|
|
if (gTicker != nullptr) {
|
|
delete gTicker;
|
|
gTicker = nullptr;
|
|
}
|
|
if (kb != nullptr) {
|
|
delete kb;
|
|
kb = nullptr;
|
|
}
|
|
if (sw != nullptr) {
|
|
delete sw;
|
|
sw = nullptr;
|
|
}
|
|
if (pl != nullptr) {
|
|
delete pl;
|
|
pl = nullptr;
|
|
}
|
|
if (result) {
|
|
bar.show(LV_STATUS_BAR_WIFI);
|
|
} else {
|
|
bar.hidden(LV_STATUS_BAR_WIFI);
|
|
}
|
|
menuBars.hidden(false);
|
|
}
|
|
|
|
|
|
void wifi_kb_event_cb(Keyboard::kb_event_t event)
|
|
{
|
|
if (event == 0) {
|
|
kb->hidden();
|
|
Serial.println(kb->getText());
|
|
strlcpy(password, kb->getText(), sizeof(password));
|
|
pl->hidden(false);
|
|
WiFi.mode(WIFI_STA);
|
|
WiFi.disconnect();
|
|
WiFi.begin(ssid, password);
|
|
gTicker = new Ticker;
|
|
gTicker->once_ms(5 * 1000, []() {
|
|
wifi_connect_status(false);
|
|
});
|
|
} else if (event == 1) {
|
|
delete kb;
|
|
delete sw;
|
|
delete pl;
|
|
pl = nullptr;
|
|
kb = nullptr;
|
|
sw = nullptr;
|
|
menuBars.hidden(false);
|
|
}
|
|
}
|
|
|
|
static void wifi_sync_mbox_cb(lv_task_t *t)
|
|
{
|
|
static struct tm timeinfo;
|
|
bool ret = false;
|
|
static int retry = 0;
|
|
configTzTime(RTC_TIME_ZONE, "pool.ntp.org");
|
|
while (1) {
|
|
ret = getLocalTime(&timeinfo);
|
|
if (!ret) {
|
|
Serial.printf("get ntp fail,retry : %d \n", retry++);
|
|
} else {
|
|
//! del preload
|
|
delete pl;
|
|
pl = nullptr;
|
|
|
|
char format[256];
|
|
snprintf(format, sizeof(format), "Time acquisition is:%d-%d-%d/%d:%d:%d, Whether to synchronize?", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
|
Serial.println(format);
|
|
delete task;
|
|
task = nullptr;
|
|
|
|
//! mbox
|
|
static const char *btns[] = {"Ok", "Cancle", ""};
|
|
mbox = new MBox;
|
|
mbox->create(format, [](lv_obj_t *obj, lv_event_t event) {
|
|
if (event == LV_EVENT_VALUE_CHANGED) {
|
|
const char *txt = lv_mbox_get_active_btn_text(obj);
|
|
if (!strcmp(txt, "Ok")) {
|
|
|
|
//!sync to rtc
|
|
struct tm *info = (struct tm *)mbox->getData();
|
|
Serial.printf("read use data = %d:%d:%d - %d:%d:%d \n", info->tm_year + 1900, info->tm_mon + 1, info->tm_mday, info->tm_hour, info->tm_min, info->tm_sec);
|
|
|
|
TTGOClass *ttgo = TTGOClass::getWatch();
|
|
ttgo->rtc->setDateTime(info->tm_year + 1900, info->tm_mon + 1, info->tm_mday, info->tm_hour, info->tm_min, info->tm_sec);
|
|
} else if (!strcmp(txt, "Cancle")) {
|
|
//!cancle
|
|
// Serial.println("Cancle press");
|
|
}
|
|
delete mbox;
|
|
mbox = nullptr;
|
|
sw->hidden(false);
|
|
}
|
|
});
|
|
mbox->setBtn(btns);
|
|
mbox->setData(&timeinfo);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void wifi_sw_event_cb(uint8_t index, bool en)
|
|
{
|
|
switch (index) {
|
|
case 0:
|
|
if (en) {
|
|
WiFi.begin();
|
|
} else {
|
|
WiFi.disconnect();
|
|
bar.hidden(LV_STATUS_BAR_WIFI);
|
|
}
|
|
break;
|
|
case 1:
|
|
sw->hidden();
|
|
pl = new Preload;
|
|
pl->create();
|
|
pl->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
WiFi.disconnect();
|
|
WiFi.scanNetworks(true);
|
|
break;
|
|
case 2:
|
|
if (!WiFi.isConnected()) {
|
|
//TODO pop-up window
|
|
Serial.println("WiFi is no connect");
|
|
return;
|
|
} else {
|
|
if (task != nullptr) {
|
|
Serial.println("task is runing ...");
|
|
return;
|
|
}
|
|
task = new Task;
|
|
task->create(wifi_sync_mbox_cb);
|
|
sw->hidden();
|
|
pl = new Preload;
|
|
pl->create();
|
|
pl->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void wifi_list_cb(const char *txt)
|
|
{
|
|
strlcpy(ssid, txt, sizeof(ssid));
|
|
delete list;
|
|
list = nullptr;
|
|
kb = new Keyboard;
|
|
kb->create();
|
|
kb->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
kb->setKeyboardEvent(wifi_kb_event_cb);
|
|
}
|
|
|
|
void wifi_list_add(const char *ssid)
|
|
{
|
|
if (list == nullptr) {
|
|
pl->hidden();
|
|
list = new List;
|
|
list->create();
|
|
list->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
list->setListCb(wifi_list_cb);
|
|
}
|
|
list->add(ssid);
|
|
}
|
|
|
|
|
|
static void wifi_event_cb()
|
|
{
|
|
Switch::switch_cfg_t cfg[3] = {{"Switch", wifi_sw_event_cb}, {"Scan", wifi_sw_event_cb}, {"NTP Sync", wifi_sw_event_cb}};
|
|
sw = new Switch;
|
|
sw->create(cfg, 3, []() {
|
|
delete sw;
|
|
sw = nullptr;
|
|
menuBars.hidden(false);
|
|
});
|
|
sw->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
sw->setStatus(0, WiFi.isConnected());
|
|
}
|
|
|
|
|
|
static void wifi_destory()
|
|
{
|
|
Serial.printf("globalIndex:%d\n", globalIndex);
|
|
switch (globalIndex) {
|
|
//! wifi management main
|
|
case 0:
|
|
menuBars.hidden(false);
|
|
delete sw;
|
|
sw = nullptr;
|
|
break;
|
|
//! wifi ap list
|
|
case 1:
|
|
if (list != nullptr) {
|
|
delete list;
|
|
list = nullptr;
|
|
}
|
|
if (gTicker != nullptr) {
|
|
delete gTicker;
|
|
gTicker = nullptr;
|
|
}
|
|
if (kb != nullptr) {
|
|
delete kb;
|
|
kb = nullptr;
|
|
}
|
|
if (pl != nullptr) {
|
|
delete pl;
|
|
pl = nullptr;
|
|
}
|
|
sw->hidden(false);
|
|
break;
|
|
//! wifi keyboard
|
|
case 2:
|
|
if (gTicker != nullptr) {
|
|
delete gTicker;
|
|
gTicker = nullptr;
|
|
}
|
|
if (kb != nullptr) {
|
|
delete kb;
|
|
kb = nullptr;
|
|
}
|
|
if (pl != nullptr) {
|
|
delete pl;
|
|
pl = nullptr;
|
|
}
|
|
sw->hidden(false);
|
|
break;
|
|
case 3:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
globalIndex--;
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* !SETTING EVENT
|
|
*
|
|
*/
|
|
static void setting_event_cb()
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! LIGHT EVENT
|
|
*
|
|
*/
|
|
static void light_sw_event_cb(uint8_t index, bool en)
|
|
{
|
|
//Add lights that need to be controlled
|
|
}
|
|
|
|
static void light_event_cb()
|
|
{
|
|
const uint8_t cfg_count = 4;
|
|
Switch::switch_cfg_t cfg[cfg_count] = {
|
|
{"light1", light_sw_event_cb},
|
|
{"light2", light_sw_event_cb},
|
|
{"light3", light_sw_event_cb},
|
|
{"light4", light_sw_event_cb},
|
|
};
|
|
sw = new Switch;
|
|
sw->create(cfg, cfg_count, []() {
|
|
delete sw;
|
|
sw = nullptr;
|
|
menuBars.hidden(false);
|
|
});
|
|
|
|
sw->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
|
|
//Initialize switch status
|
|
for (int i = 0; i < cfg_count; i++) {
|
|
sw->setStatus(i, 0);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! MBOX EVENT
|
|
*
|
|
*/
|
|
static lv_obj_t *mbox1 = nullptr;
|
|
|
|
static void create_mbox(const char *txt, lv_event_cb_t event_cb)
|
|
{
|
|
if (mbox1 != nullptr)return;
|
|
static const char *btns[] = {"Ok", ""};
|
|
mbox1 = lv_mbox_create(lv_scr_act(), NULL);
|
|
lv_mbox_set_text(mbox1, txt);
|
|
lv_mbox_add_btns(mbox1, btns);
|
|
lv_obj_set_width(mbox1, LV_HOR_RES - 40);
|
|
lv_obj_set_event_cb(mbox1, event_cb);
|
|
lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
}
|
|
|
|
static void destory_mbox()
|
|
{
|
|
if (pl != nullptr) {
|
|
delete pl;
|
|
pl = nullptr;
|
|
}
|
|
if (list != nullptr) {
|
|
delete list;
|
|
list = nullptr;
|
|
}
|
|
if (mbox1 != nullptr) {
|
|
lv_obj_del(mbox1);
|
|
mbox1 = nullptr;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! SD CARD EVENT
|
|
*
|
|
*/
|
|
|
|
static void sd_event_cb()
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! Modules EVENT
|
|
*
|
|
*/
|
|
static void modules_event_cb()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! Camera EVENT
|
|
*
|
|
*/
|
|
|
|
static void camera_event_cb()
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! nCov EVENT
|
|
*
|
|
*/
|
|
static const char *province[] = {
|
|
"北京市",
|
|
"上海市",
|
|
"天津市",
|
|
"重庆市",
|
|
"湖北省",
|
|
"湖南省",
|
|
"广东省",
|
|
"广西省",
|
|
"河北省",
|
|
"山西省",
|
|
"辽宁省",
|
|
"吉林省",
|
|
"江苏省",
|
|
"浙江省",
|
|
"安徽省",
|
|
"福建省",
|
|
"江西省",
|
|
"山东省",
|
|
"河南省",
|
|
"海南省",
|
|
"四川省",
|
|
"贵州省",
|
|
"云南省",
|
|
"陕西省",
|
|
"甘肃省",
|
|
"青海省",
|
|
"黑龙江省",
|
|
"台湾",
|
|
"香港",
|
|
"澳门",
|
|
"西藏自治区",
|
|
"内蒙古自治区",
|
|
"宁夏回族自治区",
|
|
"新疆维吾尔自治区",
|
|
};
|
|
|
|
typedef struct {
|
|
String city;
|
|
int confirmedCount;
|
|
int suspectedCount;
|
|
int curedCount;
|
|
int deadCount;
|
|
int locationId;
|
|
} nCovArray_t;
|
|
|
|
typedef struct {
|
|
nCovArray_t province;
|
|
nCovArray_t *cities;
|
|
int cities_size;
|
|
} nCovData_t;
|
|
|
|
lv_obj_t *nCov_Page = nullptr;
|
|
nCovData_t nCov_data;
|
|
bool capture_status = false;
|
|
bool capture_done = false;
|
|
lv_task_t *nCov_task_handle ;
|
|
StaticJsonDocument<2048 * 10> doc;
|
|
|
|
int url_encode(const char *src, const int srcLen, char *result, const int resultLen)
|
|
{
|
|
int index = 0;
|
|
char ch;
|
|
|
|
if ((src == NULL) || (result == NULL) || (srcLen <= 0) || (resultLen <= 0)) {
|
|
return 0;
|
|
}
|
|
for (int i = 0; (i < srcLen) && (index < resultLen); ++i) {
|
|
ch = src[i];
|
|
if (((ch >= 'A') && (ch < 'Z')) ||
|
|
((ch >= 'a') && (ch < 'z')) ||
|
|
((ch >= '0') && (ch < '9'))) {
|
|
result[index++] = ch;
|
|
} else if (ch == ' ') {
|
|
result[index++] = '+';
|
|
} else if (ch == '.' || ch == '-' || ch == '_' || ch == '*') {
|
|
result[index++] = ch;
|
|
} else {
|
|
if (index + 3 < resultLen) {
|
|
sprintf(result + index, "%%%02X", (unsigned char)ch);
|
|
index += 3;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
result[index] = '\0';
|
|
return index;
|
|
}
|
|
|
|
|
|
|
|
static bool nCov_capture_data(const char *prov)
|
|
{
|
|
char buf[128] = {0};
|
|
String url = "https://lab.isaaclin.cn/nCoV/api/area?latest=1&province=";
|
|
if (url_encode(prov, strlen(prov), buf, 128) <= 0) {
|
|
return false;
|
|
}
|
|
url += buf;
|
|
HTTPClient http;
|
|
|
|
http.begin( url);
|
|
Serial.println(url);
|
|
http.setTimeout(10000);
|
|
int httpCode = http.GET();
|
|
if (httpCode != HTTP_CODE_OK) {
|
|
Serial.printf("HTTP_CODE_ERROR %d\n", httpCode);
|
|
http.end();
|
|
return false;
|
|
}
|
|
|
|
String payload = http.getString();
|
|
http.end();
|
|
Serial.println(payload);
|
|
|
|
DeserializationError error = deserializeJson(doc, payload);
|
|
if (error) {
|
|
Serial.print(F("deserializeJson() failed: "));
|
|
Serial.println(error.c_str());
|
|
return false;
|
|
}
|
|
|
|
JsonObject results = doc["results"][0];
|
|
if (results["country"] == NULL) {
|
|
Serial.println("Search failed\n");
|
|
return false;
|
|
}
|
|
|
|
nCov_data.province.city = results["provinceShortName"].as<String>();
|
|
nCov_data.province.confirmedCount = results["confirmedCount"];;
|
|
nCov_data.province.suspectedCount = results["suspectedCount"];
|
|
nCov_data.province.curedCount = results["curedCount"];
|
|
nCov_data.province.deadCount = results["deadCount"];
|
|
|
|
|
|
nCov_data.cities_size = results["cities"].size();
|
|
Serial.printf("menory [%u] \n", nCov_data.cities_size);
|
|
nCov_data.cities = new nCovArray_t [nCov_data.cities_size];
|
|
if (nCov_data.cities == nullptr) {
|
|
Serial.printf("menory [%u] failed\n", nCov_data.cities_size);
|
|
return false;
|
|
}
|
|
|
|
JsonArray clities = results["cities"];
|
|
for (int i = 0; i < nCov_data.cities_size; ++i) {
|
|
nCov_data.cities[i].city = clities[i]["cityName"].as<String>();
|
|
nCov_data.cities[i].confirmedCount = clities[i]["confirmedCount"].as<int>();
|
|
nCov_data.cities[i].suspectedCount = clities[i]["suspectedCount"].as<int>();
|
|
nCov_data.cities[i].curedCount = clities[i]["curedCount"].as<int>();
|
|
nCov_data.cities[i].deadCount = clities[i]["deadCount"].as<int>();
|
|
nCov_data.cities[i].locationId = clities[i]["locationId"].as<int>();
|
|
}
|
|
|
|
// for (int i = 0; i < nCov_data.cities_size; ++i) {
|
|
// Serial.print("city:");
|
|
// Serial.print(nCov_data.cities[i].city );
|
|
// Serial.println();
|
|
// Serial.print("confirmedCount:");
|
|
// Serial.print(nCov_data.cities[i].confirmedCount );
|
|
// Serial.println();
|
|
// Serial.print("suspectedCount:");
|
|
// Serial.print(nCov_data.cities[i].suspectedCount );
|
|
// Serial.println();
|
|
// Serial.print("curedCount:");
|
|
// Serial.print(nCov_data.cities[i].curedCount );
|
|
// Serial.println();
|
|
// Serial.print("deadCount:");
|
|
// Serial.print(nCov_data.cities[i].deadCount );
|
|
// Serial.println();
|
|
// Serial.print("locationId:");
|
|
// Serial.print(nCov_data.cities[i].locationId );
|
|
// Serial.println();
|
|
// }
|
|
return true;
|
|
}
|
|
|
|
static void nCov_data_event_cb(lv_obj_t *obj, lv_event_t event)
|
|
{
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
if (nCov_Page != nullptr ) {
|
|
lv_obj_del(nCov_Page);
|
|
delete [] nCov_data.cities;
|
|
nCov_data.cities = nullptr;
|
|
|
|
delete list;
|
|
list = nullptr;
|
|
menuBars.hidden(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void ex_table_create(nCovData_t *data)
|
|
{
|
|
if (data == nullptr )return;
|
|
/*Create a normal cell style*/
|
|
static lv_style_t style_cell1;
|
|
lv_style_copy(&style_cell1, &lv_style_plain);
|
|
style_cell1.body.border.width = 1;
|
|
style_cell1.body.border.color = LV_COLOR_BLACK;
|
|
style_cell1.text.font = &chinese_font;
|
|
|
|
/*Crealte a header cell style*/
|
|
static lv_style_t style_cell2;
|
|
lv_style_copy(&style_cell2, &lv_style_plain);
|
|
style_cell2.body.border.width = 1;
|
|
style_cell2.body.border.color = LV_COLOR_BLACK;
|
|
style_cell2.body.main_color = LV_COLOR_SILVER;
|
|
style_cell2.body.grad_color = LV_COLOR_SILVER;
|
|
style_cell2.text.font = &chinese_font;
|
|
|
|
|
|
static lv_style_t page_style;
|
|
lv_style_copy(&page_style, &lv_style_plain); /*Copy a built-in style to initialize the new style*/
|
|
page_style.body.main_color = LV_COLOR_GRAY;
|
|
page_style.body.grad_color = LV_COLOR_GRAY;
|
|
page_style.body.opa = LV_OPA_0;
|
|
page_style.body.radius = 0;
|
|
page_style.body.border.color = LV_COLOR_GRAY;
|
|
page_style.body.border.width = 0;
|
|
page_style.body.border.opa = LV_OPA_50;
|
|
page_style.text.color = LV_COLOR_WHITE;
|
|
page_style.image.color = LV_COLOR_WHITE;
|
|
|
|
nCov_Page = lv_page_create(lv_scr_act(), NULL);
|
|
lv_page_set_edge_flash(nCov_Page, false);
|
|
lv_obj_set_size(nCov_Page, 240, 210);
|
|
lv_page_set_sb_mode(nCov_Page, LV_SB_MODE_OFF);
|
|
lv_obj_set_event_cb(nCov_Page, nCov_data_event_cb);
|
|
lv_page_set_style(nCov_Page, LV_PAGE_STYLE_BG, &page_style);
|
|
lv_obj_align(nCov_Page, bar.self(), LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
|
|
|
lv_obj_t *table = lv_table_create(nCov_Page, NULL);
|
|
|
|
lv_table_set_style(table, LV_TABLE_STYLE_BG, &page_style);
|
|
|
|
lv_table_set_style(table, LV_TABLE_STYLE_CELL1, &style_cell1);
|
|
lv_table_set_style(table, LV_TABLE_STYLE_CELL2, &style_cell2);
|
|
lv_table_set_style(table, LV_TABLE_STYLE_BG, &lv_style_transp_tight);
|
|
lv_table_set_col_cnt(table, 4);
|
|
lv_table_set_row_cnt(table, data->cities_size + 1);
|
|
lv_obj_align(table, NULL, LV_ALIGN_CENTER, 0, 0);
|
|
lv_page_glue_obj(table, true);
|
|
|
|
lv_table_set_col_width(table, 0, 240 / 4);
|
|
lv_table_set_col_width(table, 1, 240 / 4);
|
|
lv_table_set_col_width(table, 2, 240 / 4);
|
|
lv_table_set_col_width(table, 3, 240 / 4);
|
|
|
|
/*Make the cells of the first row center aligned */
|
|
lv_table_set_cell_align(table, 0, 0, LV_LABEL_ALIGN_CENTER);
|
|
lv_table_set_cell_align(table, 0, 1, LV_LABEL_ALIGN_CENTER);
|
|
lv_table_set_cell_align(table, 0, 2, LV_LABEL_ALIGN_CENTER);
|
|
lv_table_set_cell_align(table, 0, 3, LV_LABEL_ALIGN_CENTER);
|
|
|
|
/*Make the cells of the first row TYPE = 2 (use `style_cell2`) */
|
|
lv_table_set_cell_type(table, 0, 0, 2);
|
|
lv_table_set_cell_type(table, 0, 1, 2);
|
|
lv_table_set_cell_type(table, 0, 2, 2);
|
|
lv_table_set_cell_type(table, 0, 3, 2);
|
|
|
|
lv_table_set_cell_value(table, 0, 0, "城市");
|
|
lv_table_set_cell_value(table, 0, 1, "疑似");
|
|
lv_table_set_cell_value(table, 0, 2, "治愈");
|
|
lv_table_set_cell_value(table, 0, 3, "死亡");
|
|
|
|
lv_table_set_cell_value(table, 1, 0, String(data->province.city).c_str());
|
|
lv_table_set_cell_value(table, 1, 1, String(data->province.confirmedCount).c_str());
|
|
lv_table_set_cell_value(table, 1, 2, String(data->province.curedCount).c_str());
|
|
lv_table_set_cell_value(table, 1, 3, String(data->province.deadCount).c_str());
|
|
|
|
for (int i = 2; i < data->cities_size + 2; ++i) {
|
|
lv_table_set_cell_value(table, i, 0, data->cities[i - 2].city.c_str());
|
|
lv_table_set_cell_value(table, i, 1, String(data->cities[i - 2].confirmedCount).c_str());
|
|
lv_table_set_cell_value(table, i, 2, String(data->cities[i - 2].curedCount).c_str());
|
|
lv_table_set_cell_value(table, i, 3, String(data->cities[i - 2].deadCount).c_str());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void capture_task(void *arg)
|
|
{
|
|
for (;;) {
|
|
if (arg) {
|
|
capture_status = nCov_capture_data((const char *)arg);
|
|
capture_done = true;
|
|
Serial.println("nCov_capture_data done");
|
|
} else {
|
|
capture_done = true;
|
|
capture_status = false;
|
|
}
|
|
vTaskDelete(NULL);
|
|
}
|
|
}
|
|
|
|
static void nCov_list_cb(const char *txt)
|
|
{
|
|
Serial.println(txt);
|
|
list->hidden();
|
|
pl = new Preload;
|
|
pl->create();
|
|
pl->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
xTaskCreate(capture_task, "capture", 2048 * 4, (void *)txt, 10, NULL);
|
|
nCov_task_handle = lv_task_create([](lv_task_t *t) {
|
|
if (capture_done) {
|
|
if (pl != nullptr) {
|
|
delete pl;
|
|
pl = nullptr;
|
|
}
|
|
if (capture_status) {
|
|
ex_table_create(&nCov_data);
|
|
} else {
|
|
create_mbox("Server no response", [](lv_obj_t *obj, lv_event_t event) {
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
destory_mbox();
|
|
menuBars.hidden(false);
|
|
}
|
|
});
|
|
}
|
|
capture_status = false;
|
|
capture_done = false;
|
|
lv_task_del(nCov_task_handle);
|
|
}
|
|
}, 1000, LV_TASK_PRIO_LOW, NULL);
|
|
}
|
|
|
|
static void nCov_event_cb()
|
|
{
|
|
if (!WiFi.isConnected()) {
|
|
create_mbox("WiFi is not connect", [](lv_obj_t *obj, lv_event_t event) {
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
destory_mbox();
|
|
menuBars.hidden(false);
|
|
}
|
|
});
|
|
return;
|
|
} else {
|
|
static lv_style_t listStyle;
|
|
lv_style_copy(&listStyle, &lv_style_plain_color); /*Copy a built-in style to initialize the new style*/
|
|
listStyle.text.font = &chinese_font;
|
|
listStyle.body.padding.top = 30;
|
|
listStyle.body.padding.bottom = 30;
|
|
|
|
if (list == nullptr) {
|
|
list = new List;
|
|
list->create();
|
|
list->align(bar.self(), LV_ALIGN_OUT_BOTTOM_MID);
|
|
list->setListCb(nCov_list_cb);
|
|
}
|
|
for (int i = 0; i < sizeof(province) / sizeof(province[0]); ++i) {
|
|
lv_obj_t *btn = list->add(province[i], nullptr);
|
|
lv_obj_t *label = lv_list_get_btn_label(btn);
|
|
if (label != NULL) {
|
|
lv_label_set_long_mode(label, LV_LABEL_LONG_DOT);
|
|
}
|
|
}
|
|
|
|
list->setStyle(LV_LIST_STYLE_BTN_REL, &listStyle);
|
|
list->setStyle(LV_LIST_STYLE_BTN_PR, &listStyle);
|
|
list->setStyle(LV_LIST_STYLE_BTN_TGL_REL, &listStyle);
|
|
list->setStyle(LV_LIST_STYLE_BTN_TGL_PR, &listStyle);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************
|
|
*
|
|
* ! Thermometer EVENT
|
|
*
|
|
*/
|
|
static lv_task_t *temperature_handle = nullptr;
|
|
static lv_obj_t *temp_cont = nullptr;
|
|
static lv_obj_t *temp_label = nullptr;
|
|
static lv_obj_t *milieu_label = nullptr;
|
|
|
|
static void temperature_task(lv_task_t *t)
|
|
{
|
|
char buf[128] = {0};
|
|
snprintf(buf, sizeof(buf), "%.2f", mlx90614_read_object());
|
|
lv_label_set_text(temp_label, buf);
|
|
lv_obj_align(temp_label, temp_cont, LV_ALIGN_CENTER, 0, -30);
|
|
|
|
snprintf(buf, sizeof(buf), "%.2f", mlx90614_read_ambient());
|
|
lv_label_set_text(milieu_label, buf);
|
|
lv_obj_align(milieu_label, temp_cont, LV_ALIGN_CENTER, 0, 45);
|
|
|
|
lv_disp_trig_activity(NULL);
|
|
}
|
|
|
|
static void thermometer_event_cb()
|
|
{
|
|
TTGOClass *watch = TTGOClass::getWatch();
|
|
bool r = watch->deviceProbe(0x51);
|
|
Serial.printf(" probe : %d\n", r);
|
|
|
|
r = watch->deviceProbe(0x5A);
|
|
Serial.printf(" probe : %d\n", r);
|
|
|
|
if (!mlx90614_probe()) {
|
|
create_mbox("No detected Sensor", [](lv_obj_t *obj, lv_event_t event) {
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
destory_mbox();
|
|
menuBars.hidden(false);
|
|
}
|
|
});
|
|
return ;
|
|
}
|
|
|
|
if (temperature_handle) {
|
|
return;
|
|
}
|
|
|
|
static lv_style_t cont_style;
|
|
lv_style_copy(&cont_style, &lv_style_plain);
|
|
cont_style.body.main_color = LV_COLOR_GRAY;
|
|
cont_style.body.grad_color = LV_COLOR_GRAY;
|
|
cont_style.body.opa = LV_OPA_0;
|
|
cont_style.body.radius = 0;
|
|
cont_style.body.border.color = LV_COLOR_GRAY;
|
|
cont_style.body.border.width = 0;
|
|
cont_style.body.border.opa = LV_OPA_50;
|
|
cont_style.text.color = LV_COLOR_WHITE;
|
|
cont_style.image.color = LV_COLOR_WHITE;
|
|
|
|
temp_cont = lv_cont_create(lv_scr_act(), NULL);
|
|
lv_obj_set_style(temp_cont, &cont_style);
|
|
lv_obj_set_size(temp_cont, LV_HOR_RES, LV_VER_RES - 30);
|
|
lv_obj_align(temp_cont, bar.self(), LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
|
|
|
static lv_style_t temp_style;
|
|
lv_style_copy(&temp_style, &lv_style_plain);
|
|
temp_style.text.font = &digital_font;
|
|
temp_style.text.color = LV_COLOR_WHITE;
|
|
|
|
temp_label = lv_label_create(temp_cont, NULL);
|
|
lv_label_set_text(temp_label, "00.00");
|
|
lv_obj_set_style(temp_label, &temp_style);
|
|
lv_obj_align(temp_label, temp_cont, LV_ALIGN_CENTER, 0, -30);
|
|
|
|
milieu_label = lv_label_create(temp_cont, NULL);
|
|
lv_label_set_text(milieu_label, "00.00");
|
|
lv_obj_set_style(milieu_label, &temp_style);
|
|
lv_obj_align(milieu_label, temp_cont, LV_ALIGN_CENTER, 0, 45);
|
|
|
|
static lv_style_t obj_style;
|
|
lv_style_copy(&obj_style, &lv_style_plain);
|
|
obj_style.text.font = &chinese_font;
|
|
obj_style.text.color = LV_COLOR_WHITE;
|
|
|
|
lv_obj_t *obj_label = lv_label_create(temp_cont, NULL);
|
|
lv_label_set_text(obj_label, "对象温度:");
|
|
lv_obj_set_style(obj_label, &obj_style);
|
|
lv_obj_align(obj_label, temp_cont, LV_ALIGN_IN_TOP_LEFT, 15, 30);
|
|
|
|
|
|
lv_obj_t *ambient_label = lv_label_create(temp_cont, NULL);
|
|
lv_label_set_text(ambient_label, "环境温度:");
|
|
lv_obj_set_style(ambient_label, &obj_style);
|
|
lv_obj_align(ambient_label, temp_cont, LV_ALIGN_IN_LEFT_MID, 15, 10);
|
|
|
|
|
|
lv_obj_t *img_btn = lv_img_create(temp_cont, NULL);
|
|
lv_img_set_src(img_btn, &qiut);
|
|
lv_obj_align(img_btn, temp_cont, LV_ALIGN_IN_TOP_RIGHT, -15, 10);
|
|
lv_obj_set_click(img_btn, true);
|
|
lv_obj_set_event_cb(img_btn, [](lv_obj_t *obj, lv_event_t event) {
|
|
if (event == LV_EVENT_SHORT_CLICKED) {
|
|
if (temperature_handle) {
|
|
lv_task_del(temperature_handle);
|
|
temperature_handle = nullptr;
|
|
lv_obj_del(temp_cont);
|
|
temp_cont = nullptr;
|
|
}
|
|
menuBars.hidden(false);
|
|
}
|
|
});
|
|
temperature_handle = lv_task_create(temperature_task, 1000, LV_TASK_PRIO_LOW, nullptr);
|
|
}
|