Refactored code base and added WIFI configuration menu
Refactored code base: * Code moved to additional modules each with its individual responsibilities * Display module is responsible for input/output on the LCD screen * wifihandler is responsible for handling WIFI connection * Battey module is responsilbe to monitor the battery * Data exchange should only be done via public API Added WIFI configuration menu * WIFI no longer specified via defines * In settings tab, wifi submenu added to enter credentials * wifi credentials are stored in flash after a successful connection
This commit is contained in:
parent
4eb6590c58
commit
b872a70a8e
16 changed files with 1788 additions and 563 deletions
10
Platformio/.vscode/settings.json
vendored
10
Platformio/.vscode/settings.json
vendored
|
@ -2,7 +2,15 @@
|
|||
"cmake.configureOnOpen": false,
|
||||
"files.associations": {
|
||||
"random": "cpp",
|
||||
"array": "cpp"
|
||||
"array": "cpp",
|
||||
"adafruit_ft6206.h": "c",
|
||||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"string_view": "cpp",
|
||||
"initializer_list": "cpp"
|
||||
},
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO"
|
||||
}
|
BIN
Platformio/img/WiFi_High_Signal.png
Normal file
BIN
Platformio/img/WiFi_High_Signal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 552 B |
BIN
Platformio/img/WiFi_Low_Signal.png
Normal file
BIN
Platformio/img/WiFi_Low_Signal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 570 B |
BIN
Platformio/img/WiFi_Mid_Signal.png
Normal file
BIN
Platformio/img/WiFi_Mid_Signal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 559 B |
BIN
Platformio/img/WiFi_No_Signal.png
Normal file
BIN
Platformio/img/WiFi_No_Signal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 572 B |
|
@ -26,6 +26,9 @@ lib_deps =
|
|||
build_flags =
|
||||
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-I include ; Include the folder containing lv_conf.h
|
||||
-I src/display
|
||||
-I src/wifiHandler
|
||||
-I src/battery
|
||||
; The following lines replace the TFT_eSPI User_setup.h-file
|
||||
-D USER_SETUP_LOADED=1
|
||||
-D ILI9341_DRIVER=1
|
||||
|
|
|
@ -290,4 +290,157 @@ const lv_img_dsc_t lightbulb = {
|
|||
.header.h = 20,
|
||||
.data_size = 240,
|
||||
.data = lightbulb_map,
|
||||
};
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_WIFI_HIGH_SIGNAL
|
||||
#define LV_ATTRIBUTE_IMG_WIFI_HIGH_SIGNAL
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_WIFI_HIGH_SIGNAL uint8_t WiFi_High_Signal_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t WiFi_High_Signal = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 25,
|
||||
.header.h = 21,
|
||||
.data_size = 525,
|
||||
.data = WiFi_High_Signal_map,
|
||||
};
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_WIFI_LOW_SIGNAL
|
||||
#define LV_ATTRIBUTE_IMG_WIFI_LOW_SIGNAL
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_WIFI_LOW_SIGNAL uint8_t WiFi_Low_Signal_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
||||
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t WiFi_Low_Signal = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 25,
|
||||
.header.h = 21,
|
||||
.data_size = 525,
|
||||
.data = WiFi_Low_Signal_map,
|
||||
};
|
||||
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_WIFI_MID_SIGNAL
|
||||
#define LV_ATTRIBUTE_IMG_WIFI_MID_SIGNAL
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_WIFI_MID_SIGNAL uint8_t WiFi_Mid_Signal_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
||||
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t WiFi_Mid_Signal = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 25,
|
||||
.header.h = 21,
|
||||
.data_size = 525,
|
||||
.data = WiFi_Mid_Signal_map,
|
||||
};
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMG_WIFI_NO_SIGNAL
|
||||
#define LV_ATTRIBUTE_IMG_WIFI_NO_SIGNAL
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_WIFI_NO_SIGNAL uint8_t WiFi_No_Signal_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
||||
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
|
||||
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_img_dsc_t WiFi_No_Signal = {
|
||||
.header.cf = LV_IMG_CF_ALPHA_8BIT,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = 25,
|
||||
.header.h = 21,
|
||||
.data_size = 525,
|
||||
.data = WiFi_No_Signal_map,
|
||||
};
|
44
Platformio/src/battery/battery.cpp
Normal file
44
Platformio/src/battery/battery.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "battery.hpp"
|
||||
#include "display.hpp"
|
||||
#include <Arduino.h>
|
||||
|
||||
extern Display display;
|
||||
|
||||
Battery::Battery(int adc_pin, int charging_pin)
|
||||
{
|
||||
this->adc_pin = adc_pin;
|
||||
this->charging_pin = charging_pin;
|
||||
}
|
||||
|
||||
void Battery::setup()
|
||||
{
|
||||
// Power Pin Definition
|
||||
pinMode(this->charging_pin, INPUT_PULLUP);
|
||||
pinMode(this->adc_pin, INPUT);
|
||||
}
|
||||
|
||||
int Battery::getPercentage()
|
||||
{
|
||||
return constrain(map(this->getVoltage(), 3700, 4200, 0, 100), 0, 100);
|
||||
}
|
||||
|
||||
bool Battery::isCharging()
|
||||
{
|
||||
return !digitalRead(this->charging_pin);
|
||||
}
|
||||
|
||||
bool Battery::isConnected()
|
||||
{
|
||||
return ((!this->isCharging()) && (this->getVoltage() < 4350));
|
||||
}
|
||||
|
||||
int Battery::getVoltage()
|
||||
{
|
||||
return analogRead(this->adc_pin)*2*3300/4095 + 350;
|
||||
}
|
||||
|
||||
void Battery::update()
|
||||
{
|
||||
display.update_battery(this->getPercentage(), this->isCharging(), this->isConnected());
|
||||
|
||||
}
|
60
Platformio/src/battery/battery.hpp
Normal file
60
Platformio/src/battery/battery.hpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
|
||||
|
||||
#ifndef _BATTERY_HPP_
|
||||
#define _BATTERY_HPP_
|
||||
|
||||
class Battery
|
||||
{
|
||||
public:
|
||||
Battery(int adc_pin, int charging_pin);
|
||||
void setup();
|
||||
/**
|
||||
* @brief Get the Percentage of the battery
|
||||
*
|
||||
* @return int Percentage of the battery
|
||||
*/
|
||||
int getPercentage();
|
||||
|
||||
/**
|
||||
* @brief Function to determine if the battery is charging or not
|
||||
*
|
||||
* @return true Battery is currently charging
|
||||
* @return false Battery is currently not charging
|
||||
*/
|
||||
bool isCharging();
|
||||
|
||||
/**
|
||||
* @brief Function to determine if the battery is connected
|
||||
*
|
||||
* @return true Battery is connected
|
||||
* @return false Battery is not connected
|
||||
*/
|
||||
bool isConnected();
|
||||
|
||||
/**
|
||||
* @brief Function to update the battery status. This should be called on a regular basis
|
||||
*
|
||||
*/
|
||||
void update();
|
||||
private:
|
||||
/**
|
||||
* @brief Function to get the current voltage of the battery
|
||||
*
|
||||
* @return int Voltage of the battery in mV
|
||||
*/
|
||||
int getVoltage();
|
||||
|
||||
/**
|
||||
* @brief Variable to store which pin should be used for ADC
|
||||
*
|
||||
*/
|
||||
int adc_pin;
|
||||
|
||||
/**
|
||||
* @brief Variable to store which pin is used to inidicate if the battery is currently charging or not
|
||||
*
|
||||
*/
|
||||
int charging_pin;
|
||||
};
|
||||
|
||||
#endif
|
566
Platformio/src/display/display.cpp
Normal file
566
Platformio/src/display/display.cpp
Normal file
|
@ -0,0 +1,566 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include "display.hpp"
|
||||
#include "Wire.h"
|
||||
#include <Preferences.h>
|
||||
|
||||
|
||||
extern bool wakeupByIMUEnabled;
|
||||
extern Display display;
|
||||
// LVGL declarations
|
||||
LV_IMG_DECLARE(gradientLeft);
|
||||
LV_IMG_DECLARE(gradientRight);
|
||||
LV_IMG_DECLARE(appleTvIcon);
|
||||
LV_IMG_DECLARE(appleDisplayIcon);
|
||||
LV_IMG_DECLARE(appleBackIcon);
|
||||
LV_IMG_DECLARE(lightbulb);
|
||||
LV_IMG_DECLARE(WiFi_No_Signal);
|
||||
extern lv_obj_t* panel;
|
||||
static lv_disp_drv_t disp_drv;
|
||||
/*TODO: get rid of global variable and use API functions instead*/
|
||||
extern Preferences preferences;
|
||||
//TODO: fix callback function structure to pass it in and/or move it out of display class somehow else
|
||||
void smartHomeSlider_event_cb(lv_event_t * e);
|
||||
void smartHomeToggle_event_cb(lv_event_t * e);
|
||||
void WakeEnableSetting_event_cb(lv_event_t * e);
|
||||
void appleKey_event_cb(lv_event_t* e);
|
||||
void virtualKeypad_event_cb(lv_event_t* e);
|
||||
void bl_slider_event_cb(lv_event_t * e);
|
||||
void tabview_device_event_cb(lv_event_t* e);
|
||||
void store_scroll_value_event_cb(lv_event_t* e);
|
||||
void my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data);
|
||||
|
||||
// Display flushing
|
||||
static void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ){
|
||||
display.flush(disp, area, color_p);
|
||||
}
|
||||
|
||||
Display::Display(int backlight_pin, int enable_pin, int width, int height)
|
||||
{
|
||||
this->backlight_pin = backlight_pin;
|
||||
this->enable_pin = enable_pin;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->primary_color = lv_color_hex(0x303030); // gray
|
||||
|
||||
/*Initialize the keybard as null*/
|
||||
this->kb = NULL;
|
||||
}
|
||||
|
||||
void Display::hide_keyboard()
|
||||
{
|
||||
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
void Display::show_keyboard()
|
||||
{
|
||||
lv_obj_clear_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_move_foreground(this->kb);
|
||||
}
|
||||
|
||||
void Display::reset_settings_menu()
|
||||
{
|
||||
lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
|
||||
}
|
||||
|
||||
void Display::turnOff()
|
||||
{
|
||||
digitalWrite(this->backlight_pin, HIGH);
|
||||
digitalWrite(this->enable_pin, HIGH);
|
||||
pinMode(this->backlight_pin, INPUT);
|
||||
pinMode(this->enable_pin, INPUT);
|
||||
gpio_hold_en((gpio_num_t) this->backlight_pin);
|
||||
gpio_hold_en((gpio_num_t) this->enable_pin);
|
||||
preferences.putUChar("blBrightness", this->backlight_brightness);
|
||||
}
|
||||
|
||||
void Display::setup()
|
||||
{
|
||||
// LCD Pin Definition
|
||||
pinMode(this->enable_pin, OUTPUT);
|
||||
digitalWrite(this->enable_pin, HIGH);
|
||||
pinMode(this->backlight_pin, OUTPUT);
|
||||
digitalWrite(this->backlight_pin, HIGH);
|
||||
|
||||
this->tft = TFT_eSPI();
|
||||
ledcSetup(LCD_BACKLIGHT_LEDC_CHANNEL, LCD_BACKLIGHT_LEDC_FREQUENCY, LCD_BACKLIGHT_LEDC_BIT_RESOLUTION);
|
||||
ledcAttachPin(this->backlight_pin, LCD_BACKLIGHT_LEDC_CHANNEL);
|
||||
ledcWrite(LCD_BACKLIGHT_LEDC_CHANNEL, 0);
|
||||
|
||||
// Slowly charge the VSW voltage to prevent a brownout
|
||||
// Workaround for hardware rev 1!
|
||||
for(int i = 0; i < 100; i++){
|
||||
digitalWrite(this->enable_pin, HIGH); // LCD Logic off
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(this->enable_pin, LOW); // LCD Logic on
|
||||
}
|
||||
|
||||
delay(100); // Wait for the LCD driver to power on
|
||||
this->tft.init();
|
||||
this->tft.initDMA();
|
||||
this->tft.setRotation(0);
|
||||
this->tft.fillScreen(TFT_BLACK);
|
||||
this->tft.setSwapBytes(true);
|
||||
|
||||
//TODO: move touchscreen handling out of Display class
|
||||
// Setup touchscreen
|
||||
this->touch = Adafruit_FT6206();
|
||||
Wire.begin(19, 22, 400000); // Configure i2c pins and set frequency to 400kHz
|
||||
this->touch.begin(128); // Initialize touchscreen and set sensitivity threshold
|
||||
|
||||
this->backlight_brightness = preferences.getUChar("blBrightness", DEFAULT_BACKLIGHT_BRIGHTNESS);
|
||||
|
||||
// Setup LVGL
|
||||
lv_init();
|
||||
|
||||
}
|
||||
|
||||
static lv_disp_draw_buf_t draw_buf;
|
||||
void Display::setup_ui(){
|
||||
this->bufA = (lv_color_t*) malloc((this->width*this->height / 10)* sizeof(lv_color_t));
|
||||
this->bufB = (lv_color_t*) malloc((this->width*this->height / 10)* sizeof(lv_color_t));
|
||||
|
||||
lv_disp_draw_buf_init( &draw_buf, this->bufA, this->bufB, this->width * this->height / 10 );
|
||||
// Initialize the display driver
|
||||
lv_disp_drv_init( &disp_drv );
|
||||
disp_drv.hor_res = this->width;
|
||||
disp_drv.ver_res = this->height;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.draw_buf = &draw_buf;
|
||||
lv_disp_drv_register( &disp_drv );
|
||||
|
||||
//TODO: move touchscreen driver to its own module
|
||||
// Initialize the touchscreen driver
|
||||
static lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init( &indev_drv );
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = my_touchpad_read;
|
||||
lv_indev_drv_register( &indev_drv );
|
||||
// Set the background color
|
||||
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);
|
||||
|
||||
this->create_keyboard();
|
||||
// Setup a scrollable tabview for devices and settings
|
||||
lv_obj_t* tabview;
|
||||
tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0
|
||||
lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_size(tabview, this->width, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
|
||||
lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20);
|
||||
|
||||
// Add 4 tabs (names are irrelevant since the labels are hidden)
|
||||
lv_obj_t* tab1 = lv_tabview_add_tab(tabview, "Settings");
|
||||
lv_obj_t* tab2 = lv_tabview_add_tab(tabview, "Technisat");
|
||||
lv_obj_t* tab3 = lv_tabview_add_tab(tabview, "Apple TV");
|
||||
lv_obj_t* tab4 = lv_tabview_add_tab(tabview, "Smart Home");
|
||||
|
||||
// Configure number button grid
|
||||
static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST }; // equal x distribution
|
||||
static lv_coord_t row_dsc[] = { 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST }; // manual y distribution to compress the grid a bit
|
||||
|
||||
// Create a container with grid for tab2
|
||||
lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN);
|
||||
lv_obj_t* cont = lv_obj_create(tab2);
|
||||
lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_grid_column_dsc_array(cont, col_dsc, 0);
|
||||
lv_obj_set_style_grid_row_dsc_array(cont, row_dsc, 0);
|
||||
lv_obj_set_size(cont, 240, 270);
|
||||
lv_obj_set_layout(cont, LV_LAYOUT_GRID);
|
||||
lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_radius(cont, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* buttonLabel;
|
||||
lv_obj_t* obj;
|
||||
|
||||
// Iterate through grid buttons configure them
|
||||
for (int i = 0; i < 12; i++) {
|
||||
uint8_t col = i % 3;
|
||||
uint8_t row = i / 3;
|
||||
// Create the button object
|
||||
if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button
|
||||
obj = lv_btn_create(cont);
|
||||
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1);
|
||||
lv_obj_set_style_bg_color(obj, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(obj, 14, LV_PART_MAIN);
|
||||
lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN);
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes a event in its container
|
||||
// Create Labels for each button
|
||||
buttonLabel = lv_label_create(obj);
|
||||
if(i < 9){
|
||||
lv_label_set_text_fmt(buttonLabel, std::to_string(i+1).c_str(), col, row);
|
||||
lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event
|
||||
}
|
||||
else{
|
||||
lv_label_set_text_fmt(buttonLabel, "0", col, row);
|
||||
lv_obj_set_user_data(obj, (void*)9);
|
||||
}
|
||||
lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, LV_PART_MAIN);
|
||||
lv_obj_center(buttonLabel);
|
||||
}
|
||||
// Create a shared event for all button inside container
|
||||
lv_obj_add_event_cb(cont, virtualKeypad_event_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
|
||||
// Add content to the Apple TV tab (3)
|
||||
// Add a nice apple tv logo
|
||||
lv_obj_t* appleImg = lv_img_create(tab3);
|
||||
lv_img_set_src(appleImg, &appleTvIcon);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, -60);
|
||||
// create two buttons and add their icons accordingly
|
||||
lv_obj_t* button = lv_btn_create(tab3);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0);
|
||||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)1);
|
||||
|
||||
appleImg = lv_img_create(button);
|
||||
lv_img_set_src(appleImg, &appleBackIcon);
|
||||
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0);
|
||||
|
||||
button = lv_btn_create(tab3);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_RIGHT, -10, 0);
|
||||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)2);
|
||||
|
||||
appleImg = lv_img_create(button);
|
||||
lv_img_set_src(appleImg, &appleDisplayIcon);
|
||||
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
this->setup_settings(tab1);
|
||||
|
||||
// Add content to the smart home tab (4)
|
||||
lv_obj_set_layout(tab4, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(tab4, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
// Add a label, then a box for the light controls
|
||||
lv_obj_t* menuLabel = lv_label_create(tab4);
|
||||
lv_label_set_text(menuLabel, "Living Room");
|
||||
|
||||
lv_obj_t* menuBox = lv_obj_create(tab4);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* bulbIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(bulbIcon, &lightbulb);
|
||||
lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Floor Lamp");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleA = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleA, 40, 22);
|
||||
lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(this->primary_color, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleA, this->primary_color, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleA, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
|
||||
lv_obj_t *slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(this->primary_color, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
|
||||
// Add another this->settingsMenu box for a second appliance
|
||||
menuBox = lv_obj_create(tab4);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
bulbIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(bulbIcon, &lightbulb);
|
||||
lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Ceiling Light");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleB = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleB, 40, 22);
|
||||
lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(this->primary_color, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleB, this->primary_color, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleB, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
|
||||
slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(this->primary_color, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
|
||||
|
||||
// Add another room (empty for now)
|
||||
menuLabel = lv_label_create(tab4);
|
||||
lv_label_set_text(menuLabel, "Kitchen");
|
||||
|
||||
menuBox = lv_obj_create(tab4);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
|
||||
// Set current page according to the current Device
|
||||
lv_tabview_set_act(tabview, 0, LV_ANIM_OFF);
|
||||
|
||||
|
||||
// Create a page indicator
|
||||
panel = lv_obj_create(lv_scr_act());
|
||||
lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable
|
||||
lv_obj_set_size(panel, this->width, 30);
|
||||
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF);
|
||||
// This small hidden button enables the page indicator to scroll further
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Settings");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, this->primary_color, LV_PART_MAIN);
|
||||
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Technisat");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, this->primary_color, LV_PART_MAIN);
|
||||
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Apple TV");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, this->primary_color, LV_PART_MAIN);
|
||||
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Smart Home");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, this->primary_color, LV_PART_MAIN);
|
||||
// This small hidden button enables the page indicator to scroll further
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
|
||||
// Make the indicator scroll together with the tabs by creating a scroll event
|
||||
lv_obj_add_event_cb(lv_tabview_get_content(tabview), store_scroll_value_event_cb, LV_EVENT_SCROLL, NULL);
|
||||
lv_obj_add_event_cb(tabview, tabview_device_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
// Initialize scroll position for the indicator
|
||||
lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL);
|
||||
|
||||
// Style the panel background
|
||||
static lv_style_t style_btn;
|
||||
lv_style_init(&style_btn);
|
||||
lv_style_set_pad_all(&style_btn, 3);
|
||||
lv_style_set_border_width(&style_btn, 0);
|
||||
lv_style_set_bg_opa(&style_btn, LV_OPA_TRANSP);
|
||||
lv_obj_add_style(panel, &style_btn, 0);
|
||||
|
||||
// Make the indicator fade out at the sides using gradient bitmaps
|
||||
lv_obj_t* img1 = lv_img_create(lv_scr_act());
|
||||
lv_img_set_src(img1, &gradientLeft);
|
||||
lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px
|
||||
lv_obj_t* img2 = lv_img_create(lv_scr_act());
|
||||
lv_img_set_src(img2, &gradientRight);
|
||||
lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
lv_obj_set_size(img2, 30, 30);
|
||||
|
||||
|
||||
// Create a status bar
|
||||
lv_obj_t* statusbar = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_size(statusbar, 240, 20);
|
||||
lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(statusbar, 0, LV_PART_MAIN);
|
||||
lv_obj_align(statusbar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
|
||||
this->WifiLabel = lv_label_create(statusbar);
|
||||
lv_label_set_text(this->WifiLabel, "");
|
||||
lv_obj_align(this->WifiLabel, LV_ALIGN_LEFT_MID, -8, 0);
|
||||
lv_obj_set_style_text_font(this->WifiLabel, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
|
||||
this->objBattPercentage = lv_label_create(statusbar);
|
||||
lv_label_set_text(this->objBattPercentage, "");
|
||||
lv_obj_align(this->objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0);
|
||||
lv_obj_set_style_text_font(this->objBattPercentage, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
|
||||
this->objBattIcon = lv_label_create(statusbar);
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
lv_obj_align(this->objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0);
|
||||
lv_obj_set_style_text_font(this->objBattIcon, &lv_font_montserrat_16, LV_PART_MAIN);
|
||||
|
||||
}
|
||||
|
||||
|
||||
lv_obj_t* wifi_subpage;
|
||||
static lv_obj_t * kb;
|
||||
static lv_obj_t * ta;
|
||||
|
||||
/* Callback function to show and hide keybaord for attached textareas */
|
||||
static void ta_kb_event_cb(lv_event_t* e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * ta = lv_event_get_target(e);
|
||||
lv_obj_t * kb = (lv_obj_t*) lv_event_get_user_data(e);
|
||||
switch(code){
|
||||
case LV_EVENT_FOCUSED:
|
||||
lv_keyboard_set_textarea(kb, ta);
|
||||
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_move_foreground(kb);
|
||||
break;
|
||||
case LV_EVENT_DEFOCUSED:
|
||||
lv_keyboard_set_textarea(kb, NULL);
|
||||
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Display::create_keyboard()
|
||||
{
|
||||
this->kb = lv_keyboard_create(lv_scr_act());
|
||||
lv_obj_add_flag(this->kb, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_set_y(this->kb, 0);
|
||||
}
|
||||
|
||||
void Display::attach_keyboard(lv_obj_t* textarea)
|
||||
{
|
||||
if (this->kb == NULL)
|
||||
{
|
||||
this->create_keyboard();
|
||||
}
|
||||
lv_keyboard_set_textarea(this->kb, textarea);
|
||||
lv_obj_add_event_cb(textarea, ta_kb_event_cb, LV_EVENT_FOCUSED, this->kb);
|
||||
lv_obj_add_event_cb(textarea, ta_kb_event_cb, LV_EVENT_DEFOCUSED, this->kb);
|
||||
}
|
||||
|
||||
void Display::setup_settings(lv_obj_t* parent)
|
||||
{
|
||||
// Add content to the settings tab
|
||||
// With a flex layout, setting groups/boxes will position themselves automatically
|
||||
lv_obj_set_layout(parent, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(parent, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
// Add a label, then a box for the display settings
|
||||
this->settingsMenu = lv_menu_create(parent);
|
||||
lv_obj_set_width(this->settingsMenu, 210);
|
||||
|
||||
/* Create main page for settings this->settingsMenu*/
|
||||
this->settingsMainPage = lv_menu_page_create(this->settingsMenu, NULL);
|
||||
lv_obj_t* cont = lv_menu_cont_create(this->settingsMainPage);
|
||||
lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
//lv_obj_set_width(cont, lv_obj_get_width(parent));
|
||||
this->display_settings(cont);
|
||||
|
||||
this->create_wifi_settings(this->settingsMenu, cont);
|
||||
|
||||
// Another setting for the battery
|
||||
lv_obj_t* menuLabel = lv_label_create(cont);
|
||||
lv_label_set_text(menuLabel, "Battery");
|
||||
lv_obj_t* menuBox = lv_obj_create(cont);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 125);
|
||||
lv_obj_set_style_bg_color(menuBox, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_menu_set_page(this->settingsMenu, this->settingsMainPage);
|
||||
}
|
||||
|
||||
void Display::flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ){
|
||||
uint32_t w = ( area->x2 - area->x1 + 1 );
|
||||
uint32_t h = ( area->y2 - area->y1 + 1 );
|
||||
|
||||
this->tft.startWrite();
|
||||
this->tft.setAddrWindow( area->x1, area->y1, w, h );
|
||||
this->tft.pushPixelsDMA( ( uint16_t * )&color_p->full, w * h);
|
||||
this->tft.endWrite();
|
||||
|
||||
lv_disp_flush_ready( disp );
|
||||
}
|
||||
|
||||
void Display::update()
|
||||
{
|
||||
|
||||
static int fadeInTimer = millis(); // fadeInTimer = time after setup
|
||||
if(millis() < fadeInTimer + backlight_brightness){ // Fade in the backlight brightness
|
||||
ledcWrite(5, millis()-fadeInTimer);
|
||||
}
|
||||
else { // Dim Backlight before entering standby
|
||||
//if(standbyTimer < 2000) ledcWrite(5, 85); // Backlight dim
|
||||
//else ledcWrite(5, this->backlight_brightness); // Backlight on
|
||||
ledcWrite(5, this->backlight_brightness); // Backlight on
|
||||
}
|
||||
// Update LVGL UI
|
||||
lv_timer_handler();
|
||||
}
|
||||
|
||||
void Display::update_battery(int percentage, bool isCharging, bool isConnected)
|
||||
{
|
||||
if(isCharging || !isConnected)
|
||||
{
|
||||
Serial.println("charging?");
|
||||
lv_label_set_text(this->objBattPercentage, "");
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_USB);
|
||||
}
|
||||
else {
|
||||
Serial.println("Running on battery");
|
||||
if(percentage > 95){
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_FULL);
|
||||
} else if(percentage > 75)
|
||||
{
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_3);
|
||||
} else if(percentage > 50)
|
||||
{
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_2);
|
||||
} else if(percentage > 25)
|
||||
{
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_1);
|
||||
} else {
|
||||
lv_label_set_text(this->objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
307
Platformio/src/display/display.hpp
Normal file
307
Platformio/src/display/display.hpp
Normal file
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
* @file display.hpp
|
||||
* @author Thomas Bittner
|
||||
* @brief Header file describing the display class used to create the lvgl object to handle display input and outpu
|
||||
* @version 0.1
|
||||
* @date 2023-08-01
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
#ifndef _DISPLAY_HPP_
|
||||
#define _DISPLAY_HPP_
|
||||
|
||||
#include "driver/ledc.h"
|
||||
#include <TFT_eSPI.h> // Hardware-specific library
|
||||
#include <lvgl.h>
|
||||
#include <Adafruit_FT6206.h>
|
||||
|
||||
/*LEDC Channel to use for the LCD backlight*/
|
||||
#define LCD_BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_5
|
||||
|
||||
#define LCD_BACKLIGHT_LEDC_FREQUENCY 640
|
||||
|
||||
#define LCD_BACKLIGHT_LEDC_BIT_RESOLUTION 8
|
||||
|
||||
#define DEFAULT_BACKLIGHT_BRIGHTNESS 128
|
||||
|
||||
class Display
|
||||
{
|
||||
public:
|
||||
Display(int backlight_pin, int enable_pin, int width, int height);
|
||||
|
||||
/**
|
||||
* @brief Function to setup the display.
|
||||
*
|
||||
*/
|
||||
void setup();
|
||||
|
||||
/**
|
||||
* @brief Function to setup the user interface. This function has to be called after setup.
|
||||
*
|
||||
*/
|
||||
void setup_ui();
|
||||
|
||||
/**
|
||||
* @brief Function to flush the display (update what is shown on the LCD). This function is called within
|
||||
* the LVGL callback function
|
||||
*
|
||||
* @param disp
|
||||
* @param area
|
||||
* @param color_p
|
||||
*/
|
||||
void flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p );
|
||||
|
||||
/**
|
||||
* @brief Function to add list of networks to the wifi selection page.
|
||||
*
|
||||
* @param SSIDS Pointer to the list of SSIDs found. The strings are moved out and the pointer does not have to
|
||||
* life after the function returns.
|
||||
* @param RSSI Pointer to the list of the RSSI per SSID. The ordering of SSID and RSSI list should be equal. The
|
||||
* value is moved out of the array in the function, therefore the array does not have to be valid after the
|
||||
* function returns.
|
||||
* @param size Size of the SSIDS and RSSI array.
|
||||
*/
|
||||
void add_wifi_networks(String *SSIDS, int *RSSI, unsigned int size);
|
||||
|
||||
/**
|
||||
* @brief Clear the wifi networks listed in the wifi selection page. This function is called before new wifi
|
||||
* networks are added to the list to avoid double listing
|
||||
*
|
||||
*/
|
||||
void clear_wifi_networks();
|
||||
|
||||
/**
|
||||
* @brief Update the wifi status. This function will update the wifi label in the status bar according to the
|
||||
* parameter.
|
||||
*
|
||||
* @param connected Boolean parameter to indicate if a wifi connection is established or not.
|
||||
*/
|
||||
void update_wifi(bool connected);
|
||||
|
||||
/**
|
||||
* @brief Function to hide the keyboard. If the keyboard is attached to a text area, it will be hidden when the
|
||||
* text area is defocused. This function can be used if the keyboard need to be hidden due to some script event.
|
||||
*
|
||||
*/
|
||||
void hide_keyboard();
|
||||
|
||||
/**
|
||||
* @brief Function to show the keyboard. If a text area needs the keybaord, it should be attached to the text area
|
||||
* using the approbiate function. The keyboard will then show up when the text area is focused. This function is
|
||||
* needed if the keyboard should be shown due to some script or other trigger.
|
||||
*
|
||||
*/
|
||||
void show_keyboard();
|
||||
|
||||
/**
|
||||
* @brief API function which needs to be called regularly to update the display
|
||||
*
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* @brief Function to change the settings menu to main page again.
|
||||
*
|
||||
*/
|
||||
void reset_settings_menu();
|
||||
|
||||
/**
|
||||
* @brief Function to update the battery indicator on the display
|
||||
*
|
||||
* @param percentage Battery percentage
|
||||
* @param isCharging True if the battery is charging. False otherwise
|
||||
* @param isConnected True if a battery is connected, false otherwise
|
||||
*/
|
||||
void update_battery(int percentage, bool isCharging, bool isConnected);
|
||||
|
||||
void turnOff();
|
||||
private:
|
||||
/**
|
||||
* @brief Pin used for LCD backlight control
|
||||
*
|
||||
*/
|
||||
int backlight_pin;
|
||||
|
||||
/**
|
||||
* @brief Pin used to enable the LCD
|
||||
*
|
||||
*/
|
||||
int enable_pin;
|
||||
|
||||
/**
|
||||
* @brief Width of the display in pixel
|
||||
*
|
||||
*/
|
||||
int width;
|
||||
|
||||
/**
|
||||
* @brief Height of the display in pixel
|
||||
*
|
||||
*/
|
||||
int height;
|
||||
|
||||
/**
|
||||
* @brief Pointer to the buffer used for drawing on the screen
|
||||
*
|
||||
*/
|
||||
lv_color_t *bufA;
|
||||
|
||||
/**
|
||||
* @brief Pointer to the buffer used for drawing on the screen
|
||||
*
|
||||
*/
|
||||
lv_color_t *bufB;
|
||||
|
||||
/**
|
||||
* @brief Object of the touch input driver
|
||||
*
|
||||
*/
|
||||
Adafruit_FT6206 touch;
|
||||
/**
|
||||
* @brief Keyboard object used whenever a keyboard is needed.
|
||||
*
|
||||
*/
|
||||
lv_obj_t* kb;
|
||||
|
||||
/**
|
||||
* @brief Variable to store the primary color
|
||||
*
|
||||
*/
|
||||
lv_color_t primary_color;
|
||||
|
||||
/**
|
||||
* @brief Object of the TFT driver
|
||||
*
|
||||
*/
|
||||
TFT_eSPI tft;
|
||||
|
||||
/**
|
||||
* @brief Set the up settings object
|
||||
*
|
||||
* @param parent
|
||||
*/
|
||||
void setup_settings(lv_obj_t* parent);
|
||||
|
||||
/**
|
||||
* @brief Function to create the keyboard object which can then be attached to different text areas.
|
||||
*
|
||||
*/
|
||||
void create_keyboard();
|
||||
|
||||
/**
|
||||
* @brief Function to attach the keyboard to a text area. If the text area is selected, the keyboard
|
||||
* is shown and if the textarea is defocused, the keyboard will be hidden again.
|
||||
*
|
||||
* @param textarea Textarea where the keyboard should be attached to.
|
||||
*/
|
||||
void attach_keyboard(lv_obj_t* textarea);
|
||||
|
||||
/**
|
||||
* @brief LVGL Menu for settings pages as needed.
|
||||
*
|
||||
*/
|
||||
lv_obj_t* settingsMenu;
|
||||
|
||||
/**
|
||||
* @brief Main page of the settings menu
|
||||
*
|
||||
*/
|
||||
lv_obj_t* settingsMainPage;
|
||||
|
||||
/**
|
||||
* @brief Battery percentage label
|
||||
*
|
||||
*/
|
||||
lv_obj_t* objBattPercentage;
|
||||
|
||||
/**
|
||||
* @brief Battery icon object in the status bar
|
||||
*
|
||||
*/
|
||||
lv_obj_t* objBattIcon;
|
||||
|
||||
/************************************** WIFI Settings Menu *******************************************************/
|
||||
/**
|
||||
* @brief Container within the wifi selection page
|
||||
*/
|
||||
lv_obj_t* wifi_setting_cont;
|
||||
|
||||
/**
|
||||
* @brief Wifi settings entry point on the settings tab
|
||||
*
|
||||
*/
|
||||
lv_obj_t* wifiOverview;
|
||||
|
||||
/**
|
||||
* @brief Label in the wifi password page. This label is updated with the selected SSID when the credentials for
|
||||
* a wifi network is entered.
|
||||
*
|
||||
*/
|
||||
lv_obj_t* wifi_password_label;
|
||||
|
||||
/**
|
||||
* @brief Menu Subpage for the wifi password
|
||||
*/
|
||||
lv_obj_t* wifi_password_page;
|
||||
|
||||
/**
|
||||
* @brief Menu Subpage for wifi selection
|
||||
*/
|
||||
lv_obj_t* wifi_selection_page;
|
||||
|
||||
/**
|
||||
* @brief Wifi Label shown in the top status bar
|
||||
*/
|
||||
lv_obj_t* WifiLabel;
|
||||
|
||||
/**
|
||||
* @brief Create a wifi selection sub page object
|
||||
*
|
||||
* @param menu LVGL Menu where the sub page should be added to
|
||||
* @return lv_obj_t* Menu sub page object pointer
|
||||
*/
|
||||
lv_obj_t* create_wifi_selection_page(lv_obj_t* menu);
|
||||
|
||||
/**
|
||||
* @brief Method to create the wifi password sub page
|
||||
*
|
||||
* @param menu Menu where the sub page should be created
|
||||
* @return lv_obj_t* menu sub page object pointer
|
||||
*/
|
||||
lv_obj_t* create_wifi_password_page(lv_obj_t* menu);
|
||||
|
||||
/**
|
||||
* @brief Method to create the wifi settings on the main page
|
||||
*
|
||||
* @param parent lv object parent where the main settings page should be added to
|
||||
*/
|
||||
void create_wifi_main_page(lv_obj_t* parent);
|
||||
|
||||
/**
|
||||
* @brief Method to create wifi settings. This method will call the create_wifi_selection_page,
|
||||
* the create_wifi_password_page, and the create_wifi_main_page
|
||||
*
|
||||
* @param menu Settings menu where the sub pages should be added to
|
||||
* @param parent lv object parent where the main settings page should be added to
|
||||
*/
|
||||
void create_wifi_settings(lv_obj_t* menu, lv_obj_t* parent);
|
||||
|
||||
|
||||
/************************************** Display settings menu ********************************************************/
|
||||
/**
|
||||
* Variable to store the current backlight brightness level
|
||||
*/
|
||||
unsigned int backlight_brightness;
|
||||
|
||||
/**
|
||||
* @brief Function to create the display settings page.
|
||||
*
|
||||
* @param parent LVGL object acting as a parent for the display settings page
|
||||
*/
|
||||
void display_settings(lv_obj_t* parent);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
81
Platformio/src/display/displaySettings.cpp
Normal file
81
Platformio/src/display/displaySettings.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#include "display.hpp"
|
||||
#include <Arduino.h>
|
||||
|
||||
LV_IMG_DECLARE(high_brightness);
|
||||
LV_IMG_DECLARE(low_brightness);
|
||||
|
||||
/*TODO: get rid of global variable and use API functions instead*/
|
||||
extern bool wakeupByIMUEnabled;
|
||||
|
||||
// Slider Event handler
|
||||
void bl_slider_event_cb(lv_event_t * e){
|
||||
lv_obj_t * slider = lv_event_get_target(e);
|
||||
unsigned int* backlight_brightness = (unsigned int*) lv_event_get_user_data(e);
|
||||
*backlight_brightness = constrain(lv_slider_get_value(slider), 30, 255);
|
||||
}
|
||||
|
||||
// Wakeup by IMU Switch Event handler
|
||||
void WakeEnableSetting_event_cb(lv_event_t * e){
|
||||
wakeupByIMUEnabled = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
|
||||
}
|
||||
|
||||
void Display::display_settings(lv_obj_t* parent)
|
||||
{
|
||||
|
||||
lv_obj_t* menuLabel = lv_label_create(parent);
|
||||
lv_label_set_text(menuLabel, "Display");
|
||||
|
||||
lv_obj_t* menuBox = lv_obj_create(parent);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 109);
|
||||
lv_obj_set_style_bg_color(menuBox, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* brightnessIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(brightnessIcon, &low_brightness);
|
||||
lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_t* slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 30, 255);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(this->primary_color, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, this->backlight_brightness, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(66), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3);
|
||||
brightnessIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(brightnessIcon, &high_brightness);
|
||||
lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1);
|
||||
lv_obj_add_event_cb(slider, bl_slider_event_cb, LV_EVENT_VALUE_CHANGED, &this->backlight_brightness);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Lift to Wake");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
|
||||
lv_obj_t* wakeToggle = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(wakeToggle, 40, 22);
|
||||
lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29);
|
||||
lv_obj_set_style_bg_color(wakeToggle, lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(wakeToggle, WakeEnableSetting_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(wakeupByIMUEnabled) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Timeout");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64);
|
||||
lv_obj_t* drop = lv_dropdown_create(menuBox);
|
||||
lv_dropdown_set_options(drop, "10s\n"
|
||||
"30s\n"
|
||||
"1m\n"
|
||||
"3m");
|
||||
lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61);
|
||||
lv_obj_set_size(drop, 70, 22);
|
||||
//lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
//lv_obj_set_style_text_font(lv_dropdown_get_list(drop), &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(drop, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_color(lv_dropdown_get_list(drop), lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
|
||||
}
|
289
Platformio/src/display/wifiSettings.cpp
Normal file
289
Platformio/src/display/wifiSettings.cpp
Normal file
|
@ -0,0 +1,289 @@
|
|||
/**
|
||||
* @file wifiSettings.cpp
|
||||
* @author Thomas Bittner
|
||||
* @brief Functions to create the wifi settings user interface for the Display class for the OMOTE universal
|
||||
* remote control
|
||||
* @version 0.1
|
||||
* @date 2023-08-01
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
#include "display.hpp"
|
||||
#include <Arduino.h>
|
||||
#include "WiFi.h"
|
||||
#include "wifiHandler.hpp"
|
||||
|
||||
/*********************************************************************************************************************
|
||||
************************************************* Local functions ****************************************************
|
||||
**********************************************************************************************************************/
|
||||
|
||||
extern wifiHandler wifihandler;
|
||||
extern Display display;
|
||||
static char* ssid;
|
||||
|
||||
LV_IMG_DECLARE(WiFi_No_Signal);
|
||||
LV_IMG_DECLARE(WiFi_Low_Signal);
|
||||
LV_IMG_DECLARE(WiFi_Mid_Signal);
|
||||
LV_IMG_DECLARE(WiFi_High_Signal);
|
||||
|
||||
/**
|
||||
* @brief Callback function for the show password checkbox. Checking the box will show the password while unchecked the
|
||||
* password will be shown as dots.
|
||||
*
|
||||
* @param e Pointer to event object for the event where this callback is called
|
||||
*/
|
||||
static void show_password_cb(lv_event_t* e)
|
||||
{
|
||||
lv_obj_t* password_field = (lv_obj_t*) e->user_data;
|
||||
if (lv_obj_has_state(e->target, LV_STATE_CHECKED)){
|
||||
lv_textarea_set_password_mode(password_field, false);
|
||||
}
|
||||
else{
|
||||
lv_textarea_set_password_mode(password_field, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Textarea callback function for the password field. In case the enter key is pressed in the text area, the
|
||||
* function will try to connect to the network with the provided password.
|
||||
*
|
||||
* @param e Pointer to event object for the event where this callback is called
|
||||
*/
|
||||
static void ta_event_cb(lv_event_t* e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * ta = lv_event_get_target(e);
|
||||
lv_obj_t * kb = (lv_obj_t*) lv_event_get_user_data(e);
|
||||
|
||||
const char* password = lv_textarea_get_text(ta);
|
||||
switch(code){
|
||||
case LV_EVENT_READY:
|
||||
wifihandler.connect(ssid, password);
|
||||
lv_obj_clear_state(ta, LV_STATE_FOCUSED);
|
||||
display.hide_keyboard();
|
||||
display.reset_settings_menu();
|
||||
/* Fall through on purpose. Pressing enter should disable the keyboard as well*/
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function in case a wifi is selected. This callback function will change the label of the wifi password
|
||||
* sub page to the selected wifi network.
|
||||
*
|
||||
* @param e Pointer to event object for the event where this callback is called
|
||||
*/
|
||||
static void wifi_selected_cb(lv_event_t* e)
|
||||
{
|
||||
lv_obj_t* label = lv_obj_get_child(e->target, 0);
|
||||
lv_label_set_text((lv_obj_t*) e->user_data, lv_label_get_text(label));
|
||||
ssid = lv_label_get_text(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback which is triggered when the wifi settings are opened (the wifi settings are pressed in the settings
|
||||
* main page). This function will trigger the asynchronous scan for wifi networks and update the label of the wifi
|
||||
* selection page to indicate that wifi networks are being searched for. The wifi event callback function then has to
|
||||
* call the API function to fill the page with the found networks.
|
||||
*
|
||||
* @param event Pointer to event object for the event where this callback is called
|
||||
*/
|
||||
static void wifi_settings_cb(lv_event_t* event)
|
||||
{
|
||||
lv_obj_t* cont = (lv_obj_t*) lv_event_get_user_data(event);
|
||||
lv_obj_clean(cont);
|
||||
lv_obj_t* label = lv_label_create(cont);
|
||||
lv_label_set_text(label, "Searching for wifi networks");
|
||||
//This will trigger an asynchronouse network scan
|
||||
wifihandler.scan();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback which is triggered when clicking the connect button. It triggers the wifi connection.
|
||||
*
|
||||
* @param event Pointer to event object for the event where this callback is called
|
||||
*/
|
||||
static void connect_btn_cb(lv_event_t* event)
|
||||
{
|
||||
lv_obj_t* ta = (lv_obj_t*) event->user_data;
|
||||
const char* password = lv_textarea_get_text(ta);
|
||||
|
||||
wifihandler.connect(ssid, password);
|
||||
lv_obj_clear_state(ta, LV_STATE_FOCUSED);
|
||||
display.hide_keyboard();
|
||||
display.reset_settings_menu();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************
|
||||
****************************************************** Class Methods ***************************************************
|
||||
***********************************************************************************************************************/
|
||||
|
||||
void Display::clear_wifi_networks()
|
||||
{
|
||||
lv_obj_clean(this->wifi_setting_cont);
|
||||
}
|
||||
|
||||
void Display::add_wifi_networks(String *SSIDs, int *RSSI, unsigned int size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
lv_obj_t* menuBox = lv_obj_create(this->wifi_setting_cont);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 45);
|
||||
lv_obj_set_scrollbar_mode(menuBox, LV_SCROLLBAR_MODE_OFF);
|
||||
lv_obj_t* menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "no networks found");
|
||||
}
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
lv_obj_t* menuBox = lv_obj_create(this->wifi_setting_cont);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 45);
|
||||
lv_obj_set_scrollbar_mode(menuBox, LV_SCROLLBAR_MODE_OFF);
|
||||
lv_obj_t* menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text_fmt(menuLabel, "%s", SSIDs[i]);
|
||||
|
||||
#if 0
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text_fmt(menuLabel, "%d", RSSI[i]);
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
|
||||
#else
|
||||
|
||||
lv_obj_t* wifi_image = lv_img_create(menuBox);
|
||||
lv_obj_align(wifi_image, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
|
||||
if (RSSI[i] > -50)
|
||||
{
|
||||
lv_img_set_src(wifi_image, &WiFi_High_Signal);
|
||||
}
|
||||
else if (RSSI[i] > -60)
|
||||
{
|
||||
lv_img_set_src(wifi_image, &WiFi_Mid_Signal);
|
||||
}
|
||||
else if (RSSI[i] > -70)
|
||||
{
|
||||
lv_img_set_src(wifi_image, &WiFi_Low_Signal);
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_img_set_src(wifi_image, &WiFi_No_Signal);
|
||||
}
|
||||
lv_obj_set_style_img_recolor(wifi_image, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(wifi_image, LV_OPA_COVER, LV_PART_MAIN);
|
||||
#endif
|
||||
|
||||
lv_menu_set_load_page_event(this->settingsMenu, menuBox, this->wifi_password_page);
|
||||
lv_obj_add_event_cb(menuBox, wifi_selected_cb, LV_EVENT_CLICKED, this->wifi_password_label);
|
||||
}
|
||||
}
|
||||
|
||||
void Display::update_wifi(bool connected)
|
||||
{
|
||||
|
||||
lv_obj_t* ip_label = lv_obj_get_child(this->wifiOverview, 3);
|
||||
lv_obj_t* ssid_label = lv_obj_get_child(this->wifiOverview, 0);
|
||||
if (connected)
|
||||
{
|
||||
lv_label_set_text(this->WifiLabel, LV_SYMBOL_WIFI);
|
||||
lv_label_set_text(ssid_label, wifihandler.getSSID());
|
||||
lv_label_set_text(ip_label, wifihandler.getIP().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_label_set_text(this->WifiLabel, "");
|
||||
lv_label_set_text(ssid_label, "Disconnected");
|
||||
lv_label_set_text(ip_label, "-");
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_t* Display::create_wifi_password_page(lv_obj_t* menu)
|
||||
{
|
||||
lv_obj_t* ret_val = lv_menu_page_create(menu, NULL);
|
||||
lv_obj_t* cont = lv_menu_cont_create(ret_val);
|
||||
lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
this->wifi_password_label = lv_label_create(cont);
|
||||
lv_label_set_text(this->wifi_password_label, "Password");
|
||||
lv_obj_t* password_input = lv_textarea_create(cont);
|
||||
lv_obj_set_width(password_input, lv_pct(100));
|
||||
lv_textarea_set_password_mode(password_input, true);
|
||||
lv_textarea_set_one_line(password_input, true);
|
||||
lv_textarea_set_placeholder_text(password_input, "Password");
|
||||
lv_obj_add_event_cb(password_input, ta_event_cb, LV_EVENT_READY, NULL );
|
||||
this->attach_keyboard(password_input);
|
||||
|
||||
lv_obj_t* show_password = lv_checkbox_create(cont);
|
||||
lv_checkbox_set_text(show_password, "Show password");
|
||||
lv_obj_add_event_cb(show_password, show_password_cb, LV_EVENT_VALUE_CHANGED, password_input);
|
||||
|
||||
lv_obj_t* connect_button = lv_btn_create(cont);
|
||||
lv_obj_t* label = lv_label_create(connect_button);
|
||||
lv_label_set_text(label, "Connect");
|
||||
lv_obj_add_event_cb(connect_button, connect_btn_cb, LV_EVENT_CLICKED, password_input);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
lv_obj_t* Display::create_wifi_selection_page(lv_obj_t* menu)
|
||||
{
|
||||
/* Create sub page for wifi*/
|
||||
lv_obj_t* subpage = lv_menu_page_create(menu, NULL);
|
||||
this->wifi_setting_cont = lv_menu_cont_create(subpage);
|
||||
lv_obj_set_layout(this->wifi_setting_cont, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(this->wifi_setting_cont, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(this->wifi_setting_cont, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
lv_obj_t* menuLabel = lv_label_create(this->wifi_setting_cont);
|
||||
lv_label_set_text(menuLabel, "Searching for wifi networks");
|
||||
|
||||
|
||||
return subpage;
|
||||
}
|
||||
|
||||
void Display::create_wifi_main_page(lv_obj_t* parent)
|
||||
{
|
||||
lv_obj_t* menuLabel = lv_label_create(parent);
|
||||
lv_label_set_text(menuLabel, "Wi-Fi");
|
||||
this->wifiOverview = lv_obj_create(parent);
|
||||
lv_obj_set_size(this->wifiOverview, lv_pct(100), 80);
|
||||
lv_obj_set_style_bg_color(this->wifiOverview, this->primary_color, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(this->wifiOverview, 0, LV_PART_MAIN);
|
||||
menuLabel = lv_label_create(this->wifiOverview);
|
||||
|
||||
lv_obj_t* arrow = lv_label_create(this->wifiOverview);
|
||||
lv_label_set_text(arrow, LV_SYMBOL_RIGHT);
|
||||
lv_obj_align(arrow, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
|
||||
lv_obj_t* ip_label = lv_label_create(this->wifiOverview);
|
||||
lv_label_set_text(ip_label, "IP:");
|
||||
lv_obj_align(ip_label, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
|
||||
lv_obj_t* ip = lv_label_create(this->wifiOverview);
|
||||
lv_obj_align(ip, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
|
||||
if (wifihandler.isConnected())
|
||||
{
|
||||
lv_label_set_text(menuLabel, wifihandler.getSSID());
|
||||
lv_label_set_text(ip, wifihandler.getIP().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_label_set_text(menuLabel, "Disconnected");
|
||||
lv_label_set_text(ip, "-");
|
||||
}
|
||||
lv_menu_set_load_page_event(this->settingsMenu, this->wifiOverview, this->wifi_selection_page);
|
||||
lv_obj_add_event_cb(this->wifiOverview, wifi_settings_cb, LV_EVENT_CLICKED, this->wifi_setting_cont);
|
||||
}
|
||||
|
||||
|
||||
void Display::create_wifi_settings(lv_obj_t* menu, lv_obj_t* parent)
|
||||
{
|
||||
this->wifi_selection_page = this->create_wifi_selection_page(menu);
|
||||
this->wifi_password_page = this->create_wifi_password_page(this->settingsMenu);
|
||||
this->create_wifi_main_page(parent);
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
// OMOTE firmware for ESP32
|
||||
// 2023 Maximilian Kern
|
||||
|
||||
#include <TFT_eSPI.h> // Hardware-specific library
|
||||
#include <Keypad.h> // modified for inverted logic
|
||||
#include <Preferences.h>
|
||||
#include "SparkFunLIS3DH.h"
|
||||
|
@ -15,6 +14,9 @@
|
|||
#include <Adafruit_FT6206.h>
|
||||
#include "driver/ledc.h"
|
||||
#include <PubSubClient.h>
|
||||
#include "display.hpp"
|
||||
#include "wifiHandler.hpp"
|
||||
#include "battery.hpp"
|
||||
|
||||
#define ENABLE_WIFI // Comment out to diable connected features
|
||||
|
||||
|
@ -53,6 +55,12 @@
|
|||
|
||||
// Variables and Object declarations ------------------------------------------------------------------------------------------------------
|
||||
|
||||
// LCD declarations
|
||||
#define screenWidth 240
|
||||
#define screenHeight 320
|
||||
Display display(LCD_BL, LCD_EN, screenWidth, screenHeight);
|
||||
wifiHandler wifihandler;
|
||||
Battery battery(ADC_BAT, CRG_STAT);
|
||||
// Battery declares
|
||||
int battery_voltage = 0;
|
||||
int battery_percentage = 100;
|
||||
|
@ -66,21 +74,12 @@ int standbyTimer = SLEEP_TIMEOUT;
|
|||
bool wakeupByIMUEnabled = true;
|
||||
LIS3DH IMU(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19.
|
||||
|
||||
// LCD declarations
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
#define screenWidth 240
|
||||
#define screenHeight 320
|
||||
Adafruit_FT6206 touch = Adafruit_FT6206();
|
||||
TS_Point touchPoint;
|
||||
TS_Point oldPoint;
|
||||
int backlight_brightness = 255;
|
||||
|
||||
// LVGL declarations
|
||||
static lv_disp_draw_buf_t draw_buf;
|
||||
static lv_color_t bufA[ screenWidth * screenHeight / 10 ];
|
||||
static lv_color_t bufB[ screenWidth * screenHeight / 10 ];
|
||||
lv_obj_t* objBattPercentage;
|
||||
lv_obj_t* objBattIcon;
|
||||
LV_IMG_DECLARE(gradientLeft);
|
||||
LV_IMG_DECLARE(gradientRight);
|
||||
LV_IMG_DECLARE(appleTvIcon);
|
||||
|
@ -90,7 +89,6 @@ LV_IMG_DECLARE(high_brightness);
|
|||
LV_IMG_DECLARE(low_brightness);
|
||||
LV_IMG_DECLARE(lightbulb);
|
||||
lv_obj_t* panel;
|
||||
lv_color_t color_primary = lv_color_hex(0x303030); // gray
|
||||
|
||||
// Keypad declarations
|
||||
const byte ROWS = 5; //four rows
|
||||
|
@ -126,17 +124,15 @@ byte wakeup_reason;
|
|||
enum Wakeup_reasons{WAKEUP_BY_RESET, WAKEUP_BY_IMU, WAKEUP_BY_KEYPAD};
|
||||
Preferences preferences;
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
#define MQTT_SERVER "YOUR_MQTT_SERVER_IP"
|
||||
lv_obj_t* WifiLabel;
|
||||
WiFiClient espClient;
|
||||
PubSubClient client(espClient);
|
||||
|
||||
|
||||
// Helper Functions -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Set the page indicator scroll position relative to the tabview scroll position
|
||||
static void store_scroll_value_event_cb(lv_event_t* e){
|
||||
void store_scroll_value_event_cb(lv_event_t* e){
|
||||
float bias = (150.0 + 8.0) / 240.0;
|
||||
int offset = 240 / 2 - 150 / 2 - 8 - 50 - 3;
|
||||
lv_obj_t* screen = lv_event_get_target(e);
|
||||
|
@ -144,18 +140,13 @@ static void store_scroll_value_event_cb(lv_event_t* e){
|
|||
}
|
||||
|
||||
// Update current device when the tabview page is changes
|
||||
static void tabview_device_event_cb(lv_event_t* e){
|
||||
void tabview_device_event_cb(lv_event_t* e){
|
||||
currentDevice = lv_tabview_get_tab_act(lv_event_get_target(e));
|
||||
}
|
||||
|
||||
// Slider Event handler
|
||||
static void bl_slider_event_cb(lv_event_t * e){
|
||||
lv_obj_t * slider = lv_event_get_target(e);
|
||||
backlight_brightness = constrain(lv_slider_get_value(slider), 60, 255);
|
||||
}
|
||||
|
||||
// Virtual Keypad Event handler
|
||||
static void virtualKeypad_event_cb(lv_event_t* e) {
|
||||
void virtualKeypad_event_cb(lv_event_t* e) {
|
||||
lv_obj_t* target = lv_event_get_target(e);
|
||||
lv_obj_t* cont = lv_event_get_current_target(e);
|
||||
if (target == cont) return; // stop if container was clicked
|
||||
|
@ -165,19 +156,15 @@ static void virtualKeypad_event_cb(lv_event_t* e) {
|
|||
}
|
||||
|
||||
// Apple Key Event handler
|
||||
static void appleKey_event_cb(lv_event_t* e) {
|
||||
void appleKey_event_cb(lv_event_t* e) {
|
||||
// Send IR command based on the event user data
|
||||
IrSender.sendSony(50 + (int)e->user_data, 15);
|
||||
Serial.println(50 + (int)e->user_data);
|
||||
}
|
||||
|
||||
// Wakeup by IMU Switch Event handler
|
||||
static void WakeEnableSetting_event_cb(lv_event_t * e){
|
||||
wakeupByIMUEnabled = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
|
||||
}
|
||||
|
||||
// Smart Home Toggle Event handler
|
||||
static void smartHomeToggle_event_cb(lv_event_t * e){
|
||||
void smartHomeToggle_event_cb(lv_event_t * e){
|
||||
char payload[8];
|
||||
if(lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED)) strcpy(payload,"true");
|
||||
else strcpy(payload,"false");
|
||||
|
@ -187,7 +174,7 @@ static void smartHomeToggle_event_cb(lv_event_t * e){
|
|||
}
|
||||
|
||||
// Smart Home Toggle Event handler
|
||||
static void smartHomeSlider_event_cb(lv_event_t * e){
|
||||
void smartHomeSlider_event_cb(lv_event_t * e){
|
||||
lv_obj_t * slider = lv_event_get_target(e);
|
||||
char payload[8];
|
||||
dtostrf(lv_slider_get_value(slider), 1, 2, payload);
|
||||
|
@ -196,18 +183,6 @@ static void smartHomeSlider_event_cb(lv_event_t * e){
|
|||
if((int)e->user_data == 2) client.publish("bulb2_setbrightness", payload);
|
||||
}
|
||||
|
||||
// Display flushing
|
||||
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p ){
|
||||
uint32_t w = ( area->x2 - area->x1 + 1 );
|
||||
uint32_t h = ( area->y2 - area->y1 + 1 );
|
||||
|
||||
tft.startWrite();
|
||||
tft.setAddrWindow( area->x1, area->y1, w, h );
|
||||
tft.pushPixelsDMA( ( uint16_t * )&color_p->full, w * h);
|
||||
tft.endWrite();
|
||||
|
||||
lv_disp_flush_ready( disp );
|
||||
}
|
||||
|
||||
// Read the touchpad
|
||||
void my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data){
|
||||
|
@ -316,12 +291,7 @@ void configIMUInterrupts()
|
|||
|
||||
// Enter Sleep Mode
|
||||
void enterSleep(){
|
||||
// Save settings to internal flash memory
|
||||
preferences.putBool("wkpByIMU", wakeupByIMUEnabled);
|
||||
preferences.putUChar("blBrightness", backlight_brightness);
|
||||
preferences.putUChar("currentDevice", currentDevice);
|
||||
if(!preferences.getBool("alreadySetUp")) preferences.putBool("alreadySetUp", true);
|
||||
preferences.end();
|
||||
Serial.println("enterSleep called");
|
||||
|
||||
// Configure IMU
|
||||
uint8_t intDataRead;
|
||||
|
@ -330,18 +300,22 @@ void enterSleep(){
|
|||
IMU.readRegister(&intDataRead, LIS3DH_INT1_SRC);//really clear interrupt
|
||||
|
||||
#ifdef ENABLE_WIFI
|
||||
wifihandler.turnOff();
|
||||
// Power down modem
|
||||
WiFi.disconnect();
|
||||
WiFi.mode(WIFI_OFF);
|
||||
#endif
|
||||
|
||||
display.turnOff();
|
||||
|
||||
// Save settings to internal flash memory
|
||||
preferences.putBool("wkpByIMU", wakeupByIMUEnabled);
|
||||
preferences.putUChar("currentDevice", currentDevice);
|
||||
if(!preferences.getBool("alreadySetUp")) preferences.putBool("alreadySetUp", true);
|
||||
preferences.end();
|
||||
// Prepare IO states
|
||||
digitalWrite(LCD_DC, LOW); // LCD control signals off
|
||||
digitalWrite(LCD_CS, LOW);
|
||||
digitalWrite(LCD_MOSI, LOW);
|
||||
digitalWrite(LCD_SCK, LOW);
|
||||
digitalWrite(LCD_EN, HIGH); // LCD logic off
|
||||
digitalWrite(LCD_BL, HIGH); // LCD backlight off
|
||||
pinMode(CRG_STAT, INPUT); // Disable Pull-Up
|
||||
digitalWrite(IR_VCC, LOW); // IR Receiver off
|
||||
|
||||
|
@ -363,10 +337,6 @@ void enterSleep(){
|
|||
gpio_hold_en((gpio_num_t)SW_5);
|
||||
// Force display pins to high impedance
|
||||
// Without this the display might not wake up from sleep
|
||||
pinMode(LCD_BL, INPUT);
|
||||
pinMode(LCD_EN, INPUT);
|
||||
gpio_hold_en((gpio_num_t)LCD_BL);
|
||||
gpio_hold_en((gpio_num_t)LCD_EN);
|
||||
gpio_deep_sleep_hold_en();
|
||||
|
||||
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, ESP_EXT1_WAKEUP_ANY_HIGH);
|
||||
|
@ -376,24 +346,6 @@ void enterSleep(){
|
|||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WIFI
|
||||
// WiFi status event
|
||||
void WiFiEvent(WiFiEvent_t event){
|
||||
//Serial.printf("[WiFi-event] event: %d\n", event);
|
||||
if(event == ARDUINO_EVENT_WIFI_STA_GOT_IP){
|
||||
client.setServer(MQTT_SERVER, 1883); // MQTT initialization
|
||||
client.connect("OMOTE"); // Connect using a client id
|
||||
}
|
||||
// Set status bar icon based on WiFi status
|
||||
if(event == ARDUINO_EVENT_WIFI_STA_GOT_IP || event == ARDUINO_EVENT_WIFI_STA_GOT_IP6){
|
||||
lv_label_set_text(WifiLabel, LV_SYMBOL_WIFI);
|
||||
}
|
||||
else{
|
||||
lv_label_set_text(WifiLabel, "");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Setup ----------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void setup() {
|
||||
|
@ -423,9 +375,7 @@ void setup() {
|
|||
pinMode(SW_D, INPUT);
|
||||
pinMode(SW_E, INPUT);
|
||||
|
||||
// Power Pin Definition
|
||||
pinMode(CRG_STAT, INPUT_PULLUP);
|
||||
pinMode(ADC_BAT, INPUT);
|
||||
battery.setup();
|
||||
|
||||
// IR Pin Definition
|
||||
pinMode(IR_RX, INPUT);
|
||||
|
@ -434,12 +384,6 @@ void setup() {
|
|||
digitalWrite(IR_LED, HIGH); // HIGH off - LOW on
|
||||
digitalWrite(IR_VCC, LOW); // HIGH on - LOW off
|
||||
|
||||
// LCD Pin Definition
|
||||
pinMode(LCD_EN, OUTPUT);
|
||||
digitalWrite(LCD_EN, HIGH);
|
||||
pinMode(LCD_BL, OUTPUT);
|
||||
digitalWrite(LCD_BL, HIGH);
|
||||
|
||||
// Other Pin Definition
|
||||
pinMode(ACC_INT, INPUT);
|
||||
pinMode(USER_LED, OUTPUT);
|
||||
|
@ -455,485 +399,30 @@ void setup() {
|
|||
gpio_hold_dis((gpio_num_t)LCD_BL);
|
||||
gpio_deep_sleep_hold_dis();
|
||||
|
||||
// Configure the backlight PWM
|
||||
// Manual setup because ledcSetup() briefly turns on the backlight
|
||||
ledc_channel_config_t ledc_channel_left;
|
||||
ledc_channel_left.gpio_num = (gpio_num_t)LCD_BL;
|
||||
ledc_channel_left.speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
ledc_channel_left.channel = LEDC_CHANNEL_5;
|
||||
ledc_channel_left.intr_type = LEDC_INTR_DISABLE;
|
||||
ledc_channel_left.timer_sel = LEDC_TIMER_1;
|
||||
ledc_channel_left.flags.output_invert = 1; // Can't do this with ledcSetup()
|
||||
ledc_channel_left.duty = 0;
|
||||
|
||||
ledc_timer_config_t ledc_timer;
|
||||
ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
ledc_timer.duty_resolution = LEDC_TIMER_8_BIT;
|
||||
ledc_timer.timer_num = LEDC_TIMER_1;
|
||||
ledc_timer.freq_hz = 640;
|
||||
|
||||
ledc_channel_config(&ledc_channel_left);
|
||||
ledc_timer_config(&ledc_timer);
|
||||
Serial.begin(115200);
|
||||
|
||||
// --- Startup ---
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
// Restore settings from internal flash memory
|
||||
preferences.begin("settings", false);
|
||||
if(preferences.getBool("alreadySetUp")){
|
||||
wakeupByIMUEnabled = preferences.getBool("wkpByIMU");
|
||||
backlight_brightness = preferences.getUChar("blBrightness");
|
||||
currentDevice = preferences.getUChar("currentDevice");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WIFI
|
||||
wifihandler.begin();
|
||||
#endif
|
||||
|
||||
display.setup();
|
||||
// Setup TFT
|
||||
|
||||
// Slowly charge the VSW voltage to prevent a brownout
|
||||
// Workaround for hardware rev 1!
|
||||
for(int i = 0; i < 100; i++){
|
||||
digitalWrite(LCD_EN, HIGH); // LCD Logic off
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(LCD_EN, LOW); // LCD Logic on
|
||||
}
|
||||
|
||||
delay(100); // Wait for the LCD driver to power on
|
||||
tft.init();
|
||||
tft.initDMA();
|
||||
tft.setRotation(0);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setSwapBytes(true);
|
||||
|
||||
// Setup touchscreen
|
||||
Wire.begin(SDA, SCL, 400000); // Configure i2c pins and set frequency to 400kHz
|
||||
touch.begin(128); // Initialize touchscreen and set sensitivity threshold
|
||||
|
||||
// Setup LVGL
|
||||
lv_init();
|
||||
lv_disp_draw_buf_init( &draw_buf, bufA, bufB, screenWidth * screenHeight / 10 );
|
||||
|
||||
// Initialize the display driver
|
||||
static lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init( &disp_drv );
|
||||
disp_drv.hor_res = screenWidth;
|
||||
disp_drv.ver_res = screenHeight;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.draw_buf = &draw_buf;
|
||||
lv_disp_drv_register( &disp_drv );
|
||||
|
||||
// Initialize the touchscreen driver
|
||||
static lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init( &indev_drv );
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = my_touchpad_read;
|
||||
lv_indev_drv_register( &indev_drv );
|
||||
|
||||
// --- LVGL UI Configuration ---
|
||||
|
||||
// Set the background color
|
||||
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN);
|
||||
|
||||
// Setup a scrollable tabview for devices and settings
|
||||
lv_obj_t* tabview;
|
||||
tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0
|
||||
lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_size(tabview, screenWidth, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
|
||||
lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20);
|
||||
|
||||
// Add 4 tabs (names are irrelevant since the labels are hidden)
|
||||
lv_obj_t* tab1 = lv_tabview_add_tab(tabview, "Settings");
|
||||
lv_obj_t* tab2 = lv_tabview_add_tab(tabview, "Technisat");
|
||||
lv_obj_t* tab3 = lv_tabview_add_tab(tabview, "Apple TV");
|
||||
lv_obj_t* tab4 = lv_tabview_add_tab(tabview, "Smart Home");
|
||||
|
||||
// Configure number button grid
|
||||
static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST }; // equal x distribution
|
||||
static lv_coord_t row_dsc[] = { 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST }; // manual y distribution to compress the grid a bit
|
||||
|
||||
// Create a container with grid for tab2
|
||||
lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN);
|
||||
lv_obj_t* cont = lv_obj_create(tab2);
|
||||
lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_grid_column_dsc_array(cont, col_dsc, 0);
|
||||
lv_obj_set_style_grid_row_dsc_array(cont, row_dsc, 0);
|
||||
lv_obj_set_size(cont, 240, 270);
|
||||
lv_obj_set_layout(cont, LV_LAYOUT_GRID);
|
||||
lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_radius(cont, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* buttonLabel;
|
||||
lv_obj_t* obj;
|
||||
|
||||
// Iterate through grid buttons configure them
|
||||
for (int i = 0; i < 12; i++) {
|
||||
uint8_t col = i % 3;
|
||||
uint8_t row = i / 3;
|
||||
// Create the button object
|
||||
if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button
|
||||
obj = lv_btn_create(cont);
|
||||
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1);
|
||||
lv_obj_set_style_bg_color(obj, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(obj, 14, LV_PART_MAIN);
|
||||
lv_obj_set_style_shadow_color(obj, lv_color_hex(0x404040), LV_PART_MAIN);
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes a event in its container
|
||||
// Create Labels for each button
|
||||
buttonLabel = lv_label_create(obj);
|
||||
if(i < 9){
|
||||
lv_label_set_text_fmt(buttonLabel, std::to_string(i+1).c_str(), col, row);
|
||||
lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event
|
||||
}
|
||||
else{
|
||||
lv_label_set_text_fmt(buttonLabel, "0", col, row);
|
||||
lv_obj_set_user_data(obj, (void*)9);
|
||||
}
|
||||
lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, LV_PART_MAIN);
|
||||
lv_obj_center(buttonLabel);
|
||||
}
|
||||
// Create a shared event for all button inside container
|
||||
lv_obj_add_event_cb(cont, virtualKeypad_event_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
|
||||
// Add content to the Apple TV tab (3)
|
||||
// Add a nice apple tv logo
|
||||
lv_obj_t* appleImg = lv_img_create(tab3);
|
||||
lv_img_set_src(appleImg, &appleTvIcon);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, -60);
|
||||
// create two buttons and add their icons accordingly
|
||||
lv_obj_t* button = lv_btn_create(tab3);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0);
|
||||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)1);
|
||||
|
||||
appleImg = lv_img_create(button);
|
||||
lv_img_set_src(appleImg, &appleBackIcon);
|
||||
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0);
|
||||
|
||||
button = lv_btn_create(tab3);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_RIGHT, -10, 0);
|
||||
lv_obj_set_size(button, 60, 60);
|
||||
lv_obj_set_style_radius(button, 30, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)2);
|
||||
|
||||
appleImg = lv_img_create(button);
|
||||
lv_img_set_src(appleImg, &appleDisplayIcon);
|
||||
lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
|
||||
|
||||
|
||||
// Add content to the settings tab
|
||||
// With a flex layout, setting groups/boxes will position themselves automatically
|
||||
lv_obj_set_layout(tab1, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(tab1, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(tab1, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
// Add a label, then a box for the display settings
|
||||
lv_obj_t* menuLabel = lv_label_create(tab1);
|
||||
lv_label_set_text(menuLabel, "Display");
|
||||
|
||||
lv_obj_t* menuBox = lv_obj_create(tab1);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 109);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* brightnessIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(brightnessIcon, &low_brightness);
|
||||
lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_t* slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 60, 255);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, backlight_brightness, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(66), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3);
|
||||
brightnessIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(brightnessIcon, &high_brightness);
|
||||
lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1);
|
||||
lv_obj_add_event_cb(slider, bl_slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Lift to Wake");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
|
||||
lv_obj_t* wakeToggle = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(wakeToggle, 40, 22);
|
||||
lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29);
|
||||
lv_obj_set_style_bg_color(wakeToggle, lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(wakeToggle, WakeEnableSetting_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(wakeupByIMUEnabled) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Timeout");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64);
|
||||
lv_obj_t* drop = lv_dropdown_create(menuBox);
|
||||
lv_dropdown_set_options(drop, "10s\n"
|
||||
"30s\n"
|
||||
"1m\n"
|
||||
"3m");
|
||||
lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61);
|
||||
lv_obj_set_size(drop, 70, 22);
|
||||
//lv_obj_set_style_text_font(drop, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
//lv_obj_set_style_text_font(lv_dropdown_get_list(drop), &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_color(lv_dropdown_get_list(drop), lv_color_hex(0x505050), LV_PART_MAIN);
|
||||
|
||||
// Add another label, then a settings box for WiFi
|
||||
menuLabel = lv_label_create(tab1);
|
||||
lv_label_set_text(menuLabel, "Wi-Fi");
|
||||
menuBox = lv_obj_create(tab1);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 80);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Network");
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT);
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Password");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32);
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT);
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 32);
|
||||
|
||||
// Another setting for the battery
|
||||
menuLabel = lv_label_create(tab1);
|
||||
lv_label_set_text(menuLabel, "Battery");
|
||||
menuBox = lv_obj_create(tab1);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 125);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Add content to the smart home tab (4)
|
||||
lv_obj_set_layout(tab4, LV_LAYOUT_FLEX);
|
||||
lv_obj_set_flex_flow(tab4, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE);
|
||||
|
||||
// Add a label, then a box for the light controls
|
||||
menuLabel = lv_label_create(tab4);
|
||||
lv_label_set_text(menuLabel, "Living Room");
|
||||
|
||||
menuBox = lv_obj_create(tab4);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_t* bulbIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(bulbIcon, &lightbulb);
|
||||
lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Floor Lamp");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleA = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleA, 40, 22);
|
||||
lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleA, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
|
||||
slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1);
|
||||
|
||||
// Add another menu box for a second appliance
|
||||
menuBox = lv_obj_create(tab4);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
bulbIcon = lv_img_create(menuBox);
|
||||
lv_img_set_src(bulbIcon, &lightbulb);
|
||||
lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
menuLabel = lv_label_create(menuBox);
|
||||
lv_label_set_text(menuLabel, "Ceiling Light");
|
||||
lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3);
|
||||
lv_obj_t* lightToggleB = lv_switch_create(menuBox);
|
||||
lv_obj_set_size(lightToggleB, 40, 22);
|
||||
lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||
lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR);
|
||||
lv_obj_add_event_cb(lightToggleB, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
|
||||
slider = lv_slider_create(menuBox);
|
||||
lv_slider_set_range(slider, 0, 100);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB);
|
||||
lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN);
|
||||
lv_slider_set_value(slider, 255, LV_ANIM_OFF);
|
||||
lv_obj_set_size(slider, lv_pct(90), 10);
|
||||
lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37);
|
||||
lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2);
|
||||
|
||||
|
||||
// Add another room (empty for now)
|
||||
menuLabel = lv_label_create(tab4);
|
||||
lv_label_set_text(menuLabel, "Kitchen");
|
||||
|
||||
menuBox = lv_obj_create(tab4);
|
||||
lv_obj_set_size(menuBox, lv_pct(100), 79);
|
||||
lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN);
|
||||
|
||||
|
||||
// Set current page according to the current Device
|
||||
lv_tabview_set_act(tabview, currentDevice, LV_ANIM_OFF);
|
||||
|
||||
|
||||
// Create a page indicator
|
||||
panel = lv_obj_create(lv_scr_act());
|
||||
lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // This indicator will not be clickable
|
||||
lv_obj_set_size(panel, screenWidth, 30);
|
||||
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF);
|
||||
// This small hidden button enables the page indicator to scroll further
|
||||
lv_obj_t* btn = lv_btn_create(panel);
|
||||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
// Create actual (non-clickable) buttons for every tab
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
lv_obj_t* label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Settings");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Technisat");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Apple TV");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_set_size(btn, 150, lv_pct(100));
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text_fmt(label, "Smart Home");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN);
|
||||
// This small hidden button enables the page indicator to scroll further
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_set_size(btn, 50, lv_pct(100));
|
||||
lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN);
|
||||
|
||||
// Make the indicator scroll together with the tabs by creating a scroll event
|
||||
lv_obj_add_event_cb(lv_tabview_get_content(tabview), store_scroll_value_event_cb, LV_EVENT_SCROLL, NULL);
|
||||
lv_obj_add_event_cb(tabview, tabview_device_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
// Initialize scroll position for the indicator
|
||||
lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL);
|
||||
|
||||
// Style the panel background
|
||||
static lv_style_t style_btn;
|
||||
lv_style_init(&style_btn);
|
||||
lv_style_set_pad_all(&style_btn, 3);
|
||||
lv_style_set_border_width(&style_btn, 0);
|
||||
lv_style_set_bg_opa(&style_btn, LV_OPA_TRANSP);
|
||||
lv_obj_add_style(panel, &style_btn, 0);
|
||||
|
||||
// Make the indicator fade out at the sides using gradient bitmaps
|
||||
lv_obj_t* img1 = lv_img_create(lv_scr_act());
|
||||
lv_img_set_src(img1, &gradientLeft);
|
||||
lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px
|
||||
lv_obj_t* img2 = lv_img_create(lv_scr_act());
|
||||
lv_img_set_src(img2, &gradientRight);
|
||||
lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||
lv_obj_set_size(img2, 30, 30);
|
||||
|
||||
|
||||
// Create a status bar
|
||||
lv_obj_t* statusbar = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_size(statusbar, 240, 20);
|
||||
lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(statusbar, 0, LV_PART_MAIN);
|
||||
lv_obj_align(statusbar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
|
||||
WifiLabel = lv_label_create(statusbar);
|
||||
lv_label_set_text(WifiLabel, "");
|
||||
lv_obj_align(WifiLabel, LV_ALIGN_LEFT_MID, -8, 0);
|
||||
lv_obj_set_style_text_font(WifiLabel, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
objBattPercentage = lv_label_create(statusbar);
|
||||
lv_label_set_text(objBattPercentage, "");
|
||||
lv_obj_align(objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0);
|
||||
lv_obj_set_style_text_font(objBattPercentage, &lv_font_montserrat_12, LV_PART_MAIN);
|
||||
|
||||
objBattIcon = lv_label_create(statusbar);
|
||||
lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
lv_obj_align(objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0);
|
||||
lv_obj_set_style_text_font(objBattIcon, &lv_font_montserrat_16, LV_PART_MAIN);
|
||||
|
||||
display.setup_ui();
|
||||
// --- End of LVGL configuration ---
|
||||
|
||||
|
||||
#ifdef ENABLE_WIFI
|
||||
// Setup WiFi
|
||||
WiFi.setHostname("OMOTE"); //define hostname
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
WiFi.setSleep(true);
|
||||
#endif
|
||||
|
||||
// Setup IMU
|
||||
IMU.settings.accelSampleRate = 50; //Hz. Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
|
||||
IMU.settings.accelRange = 2; //Max G force readable. Can be: 2, 4, 8, 16
|
||||
|
@ -965,19 +454,7 @@ void setup() {
|
|||
|
||||
void loop() {
|
||||
|
||||
// Update Backlight brightness
|
||||
static int fadeInTimer = millis(); // fadeInTimer = time after setup
|
||||
if(millis() < fadeInTimer + backlight_brightness){ // Fade in the backlight brightness
|
||||
ledcWrite(5, millis()-fadeInTimer);
|
||||
}
|
||||
else { // Dim Backlight before entering standby
|
||||
if(standbyTimer < 2000) ledcWrite(5, 85); // Backlight dim
|
||||
else ledcWrite(5, backlight_brightness); // Backlight on
|
||||
}
|
||||
|
||||
// Update LVGL UI
|
||||
lv_timer_handler();
|
||||
|
||||
display.update();
|
||||
// Blink debug LED at 1 Hz
|
||||
digitalWrite(USER_LED, millis() % 1000 > 500);
|
||||
|
||||
|
@ -992,9 +469,11 @@ void loop() {
|
|||
IMUTaskTimer = millis();
|
||||
}
|
||||
|
||||
#if 1
|
||||
// Update battery stats at 1Hz
|
||||
static unsigned long batteryTaskTimer = millis() + 1000; // add 1s to start immediately
|
||||
if(millis() - batteryTaskTimer >= 1000){
|
||||
#if 0
|
||||
battery_voltage = analogRead(ADC_BAT)*2*3300/4095 + 350; // 350mV ADC offset
|
||||
battery_percentage = constrain(map(battery_voltage, 3700, 4200, 0, 100), 0, 100);
|
||||
batteryTaskTimer = millis();
|
||||
|
@ -1013,7 +492,12 @@ void loop() {
|
|||
else if(battery_percentage > 25) lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_1);
|
||||
else lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
|
||||
}
|
||||
#else
|
||||
batteryTaskTimer = millis();
|
||||
battery.update();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Keypad Handling
|
||||
customKeypad.getKey(); // Populate key list
|
||||
|
@ -1035,9 +519,4 @@ void loop() {
|
|||
// //tft.drawString(String(results.command) + " ", 80, 90, 1);
|
||||
// IrReceiver.resume(); // Enable receiving of the next value
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
152
Platformio/src/wifiHandler/wifiHandler.cpp
Normal file
152
Platformio/src/wifiHandler/wifiHandler.cpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* @file wifiHandler.cpp
|
||||
* @author Thomas Bittner
|
||||
* @brief Wifi handler is a wrapper for the arduino wifi function. This wrapper provides handling of wifi credetials and
|
||||
* storing it over reset.
|
||||
* @version 0.1
|
||||
* @date 2023-08-01
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#include "wifiHandler.hpp"
|
||||
#include <Preferences.h>
|
||||
#include <WiFi.h>
|
||||
#include "display.hpp"
|
||||
#include <PubSubClient.h>
|
||||
|
||||
/*TODO: rework to not use global variables*/
|
||||
extern wifiHandler wifihandler;
|
||||
extern Preferences preferences;
|
||||
extern Display display;
|
||||
extern PubSubClient client;
|
||||
const char* temporary_ssid;
|
||||
const char* temporary_password;
|
||||
|
||||
#define MQTT_SERVER "YOUR_MQTT_SERVER_IP"
|
||||
// WiFi status event
|
||||
void WiFiEvent(WiFiEvent_t event){
|
||||
int no_networks = 0;
|
||||
switch (event)
|
||||
{
|
||||
case ARDUINO_EVENT_WIFI_SCAN_DONE:
|
||||
Serial.println("WIFI scan done\n");
|
||||
no_networks = WiFi.scanComplete();
|
||||
if (no_networks < 0)
|
||||
{
|
||||
Serial.println("Scan failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
display.clear_wifi_networks();
|
||||
Serial.print(no_networks);
|
||||
Serial.print(" found\n");
|
||||
String SSIDS[no_networks];
|
||||
int RSSIS[no_networks];
|
||||
for (int i = 0; i < no_networks; i++)
|
||||
{
|
||||
SSIDS[i] = WiFi.SSID(i);
|
||||
RSSIS[i] = WiFi.RSSI(i);
|
||||
}
|
||||
display.add_wifi_networks(SSIDS, RSSIS, no_networks);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
client.setServer(MQTT_SERVER, 1883); // MQTT initialization
|
||||
client.connect("OMOTE"); // Connect using a client id
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||
display.update_wifi(true);
|
||||
wifihandler.update_credetials(temporary_ssid, temporary_password);
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||
case ARDUINO_EVENT_WIFI_STA_STOP:
|
||||
display.update_wifi(false);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
wifiHandler::wifiHandler()
|
||||
{
|
||||
this->password[0] = '\0';
|
||||
this->SSID[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
void wifiHandler::update_credetials(const char* temporary_ssid, const char* temporary_password)
|
||||
{
|
||||
if (strcmp(temporary_password, this->password) != 0 || strcmp(temporary_ssid, this->SSID) != 0)
|
||||
{
|
||||
strcpy(this->password, temporary_password);
|
||||
strcpy(this->SSID, temporary_ssid);
|
||||
|
||||
String tempString = this->password;
|
||||
preferences.putString("password", tempString);
|
||||
tempString = this->SSID;
|
||||
preferences.putString("SSID", tempString);
|
||||
}
|
||||
}
|
||||
|
||||
void wifiHandler::scan()
|
||||
{
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
|
||||
void wifiHandler::begin()
|
||||
{
|
||||
WiFi.setHostname("OMOTE");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
|
||||
String ssid = preferences.getString("SSID");
|
||||
String password = preferences.getString("password");
|
||||
|
||||
/* If the SSID is not empty, there was a value stored in the preferences and we try to use it.*/
|
||||
if (!ssid.isEmpty())
|
||||
{
|
||||
Serial.print("Connecting to wifi ");
|
||||
Serial.println(ssid);
|
||||
strcpy(this->SSID, ssid.c_str());
|
||||
strcpy(this->password, password.c_str());
|
||||
this->connect(this->SSID, this->password);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("no SSID or password stored");
|
||||
/*Set first character to \0 indicates an empty string*/
|
||||
this->SSID[0] = '\0';
|
||||
this->password[0] = '\0';
|
||||
WiFi.disconnect();
|
||||
}
|
||||
|
||||
WiFi.setSleep(true);
|
||||
}
|
||||
|
||||
void wifiHandler::connect(const char* SSID, const char* password)
|
||||
{
|
||||
temporary_password = password;
|
||||
temporary_ssid = SSID;
|
||||
WiFi.begin(SSID, password);
|
||||
}
|
||||
|
||||
void wifiHandler::turnOff()
|
||||
{
|
||||
WiFi.disconnect();
|
||||
WiFi.mode(WIFI_OFF);
|
||||
}
|
||||
|
||||
bool wifiHandler::isConnected()
|
||||
{
|
||||
return WiFi.isConnected();
|
||||
}
|
||||
|
||||
char* wifiHandler::getSSID()
|
||||
{
|
||||
return this->SSID;
|
||||
}
|
||||
|
||||
String wifiHandler::getIP()
|
||||
{
|
||||
return WiFi.localIP().toString();
|
||||
}
|
83
Platformio/src/wifiHandler/wifiHandler.hpp
Normal file
83
Platformio/src/wifiHandler/wifiHandler.hpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
class wifiHandler {
|
||||
public:
|
||||
wifiHandler();
|
||||
/**
|
||||
* @brief Function to initialize the wifi handler
|
||||
*
|
||||
*/
|
||||
void begin();
|
||||
|
||||
/**
|
||||
* @brief Connect to the wifi using the provided credetials
|
||||
*
|
||||
* @param SSID
|
||||
* @param password
|
||||
*/
|
||||
void connect(const char* SSID, const char* password);
|
||||
|
||||
/**
|
||||
* @brief Function to disconnect from the network
|
||||
*
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* @brief Function to determine wether or not we are connected to a network
|
||||
*
|
||||
* @return true Device is connected to wifi network
|
||||
* @return false Device is not connected to wifi network
|
||||
*/
|
||||
bool isConnected();
|
||||
|
||||
/**
|
||||
* @brief Function to turn off wifi
|
||||
*
|
||||
*/
|
||||
void turnOff();
|
||||
|
||||
/**
|
||||
* @brief function to trigger asynchronous scan for wifi networks
|
||||
*
|
||||
*/
|
||||
void scan();
|
||||
|
||||
/**
|
||||
* @brief Function to get SSID of the currently connected wifi network
|
||||
*
|
||||
* @return char* SSID of the currently connected network
|
||||
*/
|
||||
char* getSSID();
|
||||
|
||||
/**
|
||||
* @brief Function to update the wifi credentials. This function is called in the wifi event callback function
|
||||
* after a connection is established. Only then is the new credentials stored and the old stored credentials
|
||||
* overwritten.
|
||||
*
|
||||
* @param temporary_ssid
|
||||
* @param temporary_password
|
||||
*/
|
||||
void update_credetials(const char* temporary_ssid, const char* temporary_password);
|
||||
|
||||
/**
|
||||
* @brief Function to get the IP address of this device
|
||||
*
|
||||
* @return String IP Address of the device
|
||||
*/
|
||||
String getIP();
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Internal variable to store the wifi password
|
||||
*
|
||||
*/
|
||||
char password[50];
|
||||
|
||||
/**
|
||||
* @brief Internal variable to store the wifi SSID
|
||||
*
|
||||
*/
|
||||
char SSID[50];
|
||||
|
||||
};
|
Loading…
Add table
Reference in a new issue