Initial commit
This commit is contained in:
commit
2282b7b8a6
|
|
@ -0,0 +1 @@
|
|||
build
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"sketch": "main.ino",
|
||||
"configuration": "FlashFreq=80,PartitionScheme=default,UploadSpeed=921600,DebugLevel=none,EraseFlash=none",
|
||||
"board": "esp32:esp32:mhetesp32minikit",
|
||||
"output": "../build",
|
||||
"port": "COM10"
|
||||
}
|
||||
|
|
@ -0,0 +1,594 @@
|
|||
{
|
||||
"version": 4,
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Arduino",
|
||||
"compilerPath": "C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\bin\\xtensa-esp32-elf-g++",
|
||||
"compilerArgs": [
|
||||
"-mlongcalls",
|
||||
"-Wno-frame-address",
|
||||
"-ffunction-sections",
|
||||
"-fdata-sections",
|
||||
"-Wno-error=unused-function",
|
||||
"-Wno-error=unused-variable",
|
||||
"-Wno-error=deprecated-declarations",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-sign-compare",
|
||||
"-freorder-blocks",
|
||||
"-Wwrite-strings",
|
||||
"-fstack-protector",
|
||||
"-fstrict-volatile-bitfields",
|
||||
"-Wno-error=unused-but-set-variable",
|
||||
"-fno-jump-tables",
|
||||
"-fno-tree-switch-conversion",
|
||||
"-std=gnu++11",
|
||||
"-fexceptions",
|
||||
"-fno-rtti"
|
||||
],
|
||||
"intelliSenseMode": "gcc-x64",
|
||||
"includePath": [
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\newlib\\platform_include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\freertos\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\freertos\\include\\esp_additions\\freertos",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\freertos\\port\\xtensa\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\freertos\\include\\esp_additions",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_hw_support\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_hw_support\\include\\soc",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_hw_support\\include\\soc\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_hw_support\\port\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_hw_support\\port\\esp32\\private_include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\heap\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\log\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\lwip\\include\\apps",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\lwip\\include\\apps\\sntp",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\lwip\\lwip\\src\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\lwip\\port\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\lwip\\port\\esp32\\include\\arch",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\soc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\soc\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\soc\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\hal\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\hal\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\hal\\platform_port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_rom\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_rom\\include\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_rom\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_common\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_system\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_system\\port\\soc",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_system\\port\\public_compat",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\xtensa\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\xtensa\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\driver\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\driver\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_pm\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_ringbuf\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\efuse\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\efuse\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\vfs\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_wifi\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_event\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_netif\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_eth\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\tcpip_adapter\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_phy\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_phy\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_ipc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\app_trace\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_timer\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\mbedtls\\port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\mbedtls\\mbedtls\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\mbedtls\\esp_crt_bundle\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\app_update\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\spi_flash\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bootloader_support\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\nvs_flash\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\pthread\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_gdbstub\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_gdbstub\\xtensa",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_gdbstub\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espcoredump\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espcoredump\\include\\port\\xtensa",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\wpa_supplicant\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\wpa_supplicant\\port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\wpa_supplicant\\esp_supplicant\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\ieee802154\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\console",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\asio\\asio\\asio\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\asio\\port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\common\\osi\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\include\\esp32\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\common\\api\\include\\api",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\common\\btc\\profile\\esp\\blufi\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\common\\btc\\profile\\esp\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\host\\bluedroid\\api\\include\\api",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_common\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_common\\tinycrypt\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_core",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_core\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_core\\storage",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\btc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_models\\common\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_models\\client\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\mesh_models\\server\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\api\\core\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\api\\models\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\bt\\esp_ble_mesh\\api",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\cbor\\port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\unity\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\unity\\unity\\src",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\cmock\\CMock\\src",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\coap\\port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\coap\\libcoap\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\nghttp\\port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\nghttp\\nghttp2\\lib\\includes",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-tls",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-tls\\esp-tls-crypto",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_adc_cal\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_hid\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\tcp_transport\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_http_client\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_http_server\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_https_ota\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_https_server\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_lcd\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_lcd\\interface",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\protobuf-c\\protobuf-c",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\protocomm\\include\\common",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\protocomm\\include\\security",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\protocomm\\include\\transports",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\mdns\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_local_ctrl\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\sdmmc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_serial_slave_link\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_websocket_client\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\expat\\expat\\expat\\lib",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\expat\\port\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\wear_levelling\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\fatfs\\diskio",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\fatfs\\vfs",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\fatfs\\src",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\freemodbus\\freemodbus\\common\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\idf_test\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\idf_test\\include\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\jsmn\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\json\\cJSON",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\libsodium\\libsodium\\src\\libsodium\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\libsodium\\port_include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\mqtt\\esp-mqtt\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\openssl\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\perfmon\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\spiffs\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\ulp\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\wifi_provisioning\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\rmaker_common\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_diagnostics\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\rtc_store\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_insights\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\json_parser\\upstream\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\json_parser\\upstream",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\json_generator\\upstream",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_schedule\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp_secure_cert_mgr\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_rainmaker\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\gpio_button\\button\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\qrcode\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\ws2812_led",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp_littlefs\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\tool",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\typedef",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\image",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\math",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\nn",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\layer",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\detect",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp-dl\\include\\model_zoo",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp32-camera\\driver\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\esp32-camera\\conversions\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\dotprod\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\support\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\support\\mem\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\windows\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\windows\\hann\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\windows\\blackman\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\windows\\blackman_harris\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\windows\\blackman_nuttall\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\windows\\nuttall\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\windows\\flat_top\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\iir\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\fir\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\math\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\math\\add\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\math\\sub\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\math\\mul\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\math\\addc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\math\\mulc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\math\\sqrt\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\matrix\\mul\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\matrix\\add\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\matrix\\addc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\matrix\\mulc\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\matrix\\sub\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\matrix\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\fft\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\dct\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\conv\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\common\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\matrix\\mul\\test\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\kalman\\ekf\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\espressif__esp-dsp\\modules\\kalman\\ekf_imu13states\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\include\\fb_gfx\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\tools\\sdk\\esp32\\dio_qspi\\include",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\cores\\esp32",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\variants\\mhetesp32minikit",
|
||||
"C:\\Users\\menxm\\Documents\\Arduino\\libraries\\GxEPD2\\src",
|
||||
"C:\\Users\\menxm\\Documents\\Arduino\\libraries\\Adafruit_GFX_Library",
|
||||
"C:\\Users\\menxm\\Documents\\Arduino\\libraries\\Adafruit_BusIO",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\libraries\\Wire\\src",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\libraries\\SPI\\src",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\libraries\\WiFi\\src",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\libraries\\HTTPClient\\src",
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\libraries\\WiFiClientSecure\\src",
|
||||
"C:\\Users\\menxm\\Documents\\Arduino\\libraries\\ArduinoJson\\src",
|
||||
"c:\\users\\menxm\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\xtensa-esp32-elf\\include\\c++\\8.4.0",
|
||||
"c:\\users\\menxm\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\xtensa-esp32-elf\\include\\c++\\8.4.0\\xtensa-esp32-elf",
|
||||
"c:\\users\\menxm\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\xtensa-esp32-elf\\include\\c++\\8.4.0\\backward",
|
||||
"c:\\users\\menxm\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\lib\\gcc\\xtensa-esp32-elf\\8.4.0\\include",
|
||||
"c:\\users\\menxm\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\lib\\gcc\\xtensa-esp32-elf\\8.4.0\\include-fixed",
|
||||
"c:\\users\\menxm\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\xtensa-esp32-elf\\sys-include",
|
||||
"c:\\users\\menxm\\appdata\\local\\arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\esp-2021r2-patch5-8.4.0\\xtensa-esp32-elf\\include"
|
||||
],
|
||||
"forcedInclude": [
|
||||
"C:\\Users\\menxm\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\2.0.16\\cores\\esp32\\Arduino.h"
|
||||
],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++11",
|
||||
"defines": [
|
||||
"HAVE_CONFIG_H",
|
||||
"MBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\"",
|
||||
"UNITY_INCLUDE_CONFIG_H",
|
||||
"WITH_POSIX",
|
||||
"_GNU_SOURCE",
|
||||
"IDF_VER=\"v4.4.7-dirty\"",
|
||||
"ESP_PLATFORM",
|
||||
"_POSIX_READER_WRITER_LOCKS",
|
||||
"F_CPU=240000000L",
|
||||
"ARDUINO=10607",
|
||||
"ARDUINO_MH_ET_LIVE_ESP32MINIKIT",
|
||||
"ARDUINO_ARCH_ESP32",
|
||||
"ARDUINO_BOARD=\"MH_ET_LIVE_ESP32MINIKIT\"",
|
||||
"ARDUINO_VARIANT=\"mhetesp32minikit\"",
|
||||
"ARDUINO_PARTITION_default",
|
||||
"ESP32",
|
||||
"CORE_DEBUG_LEVEL=0",
|
||||
"ARDUINO_USB_CDC_ON_BOOT=0",
|
||||
"__DBL_MIN_EXP__=(-1021)",
|
||||
"__FLT32X_MAX_EXP__=1024",
|
||||
"__cpp_attributes=200809",
|
||||
"__UINT_LEAST16_MAX__=0xffff",
|
||||
"__ATOMIC_ACQUIRE=2",
|
||||
"__FLT_MIN__=1.1754943508222875e-38F",
|
||||
"__GCC_IEC_559_COMPLEX=0",
|
||||
"__cpp_aggregate_nsdmi=201304",
|
||||
"__UINT_LEAST8_TYPE__=unsigned char",
|
||||
"__INTMAX_C(c)=c ## LL",
|
||||
"__CHAR_BIT__=8",
|
||||
"__UINT8_MAX__=0xff",
|
||||
"__WINT_MAX__=0xffffffffU",
|
||||
"__FLT32_MIN_EXP__=(-125)",
|
||||
"__cpp_static_assert=200410",
|
||||
"__ORDER_LITTLE_ENDIAN__=1234",
|
||||
"__SIZE_MAX__=0xffffffffU",
|
||||
"__WCHAR_MAX__=0xffff",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1=1",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2=1",
|
||||
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4=1",
|
||||
"__DBL_DENORM_MIN__=double(4.9406564584124654e-324L)",
|
||||
"__GCC_ATOMIC_CHAR_LOCK_FREE=2",
|
||||
"__GCC_IEC_559=0",
|
||||
"__FLT32X_DECIMAL_DIG__=17",
|
||||
"__FLT_EVAL_METHOD__=0",
|
||||
"__cpp_binary_literals=201304",
|
||||
"__FLT64_DECIMAL_DIG__=17",
|
||||
"__GCC_ATOMIC_CHAR32_T_LOCK_FREE=2",
|
||||
"__cpp_variadic_templates=200704",
|
||||
"__UINT_FAST64_MAX__=0xffffffffffffffffULL",
|
||||
"__SIG_ATOMIC_TYPE__=int",
|
||||
"__DBL_MIN_10_EXP__=(-307)",
|
||||
"__FINITE_MATH_ONLY__=0",
|
||||
"__cpp_variable_templates=201304",
|
||||
"__GNUC_PATCHLEVEL__=0",
|
||||
"__FLT32_HAS_DENORM__=1",
|
||||
"__UINT_FAST8_MAX__=0xffffffffU",
|
||||
"__has_include(STR)=__has_include__(STR)",
|
||||
"__DEC64_MAX_EXP__=385",
|
||||
"__INT8_C(c)=c",
|
||||
"__INT_LEAST8_WIDTH__=8",
|
||||
"__UINT_LEAST64_MAX__=0xffffffffffffffffULL",
|
||||
"__SHRT_MAX__=0x7fff",
|
||||
"__LDBL_MAX__=1.7976931348623157e+308L",
|
||||
"__UINT_LEAST8_MAX__=0xff",
|
||||
"__GCC_ATOMIC_BOOL_LOCK_FREE=2",
|
||||
"__UINTMAX_TYPE__=long long unsigned int",
|
||||
"__DEC32_EPSILON__=1E-6DF",
|
||||
"__FLT_EVAL_METHOD_TS_18661_3__=0",
|
||||
"__CHAR_UNSIGNED__=1",
|
||||
"__UINT32_MAX__=0xffffffffU",
|
||||
"__GXX_EXPERIMENTAL_CXX0X__=1",
|
||||
"__LDBL_MAX_EXP__=1024",
|
||||
"__WINT_MIN__=0U",
|
||||
"__INT_LEAST16_WIDTH__=16",
|
||||
"__SCHAR_MAX__=0x7f",
|
||||
"__WCHAR_MIN__=0",
|
||||
"__INT64_C(c)=c ## LL",
|
||||
"__DBL_DIG__=15",
|
||||
"__GCC_ATOMIC_POINTER_LOCK_FREE=2",
|
||||
"__SIZEOF_INT__=4",
|
||||
"__SIZEOF_POINTER__=4",
|
||||
"__GCC_ATOMIC_CHAR16_T_LOCK_FREE=2",
|
||||
"__USER_LABEL_PREFIX__",
|
||||
"__STDC_HOSTED__=1",
|
||||
"__LDBL_HAS_INFINITY__=1",
|
||||
"__XTENSA_EL__=1",
|
||||
"__FLT32_DIG__=6",
|
||||
"__FLT_EPSILON__=1.1920928955078125e-7F",
|
||||
"__GXX_WEAK__=1",
|
||||
"__SHRT_WIDTH__=16",
|
||||
"__LDBL_MIN__=2.2250738585072014e-308L",
|
||||
"__DEC32_MAX__=9.999999E96DF",
|
||||
"__cpp_threadsafe_static_init=200806",
|
||||
"__FLT32X_HAS_INFINITY__=1",
|
||||
"__INT32_MAX__=0x7fffffff",
|
||||
"__INT_WIDTH__=32",
|
||||
"__SIZEOF_LONG__=4",
|
||||
"__UINT16_C(c)=c",
|
||||
"__PTRDIFF_WIDTH__=32",
|
||||
"__DECIMAL_DIG__=17",
|
||||
"__FLT64_EPSILON__=2.2204460492503131e-16F64",
|
||||
"__INTMAX_WIDTH__=64",
|
||||
"__FLT64_MIN_EXP__=(-1021)",
|
||||
"__has_include_next(STR)=__has_include_next__(STR)",
|
||||
"__LDBL_HAS_QUIET_NAN__=1",
|
||||
"__FLT64_MANT_DIG__=53",
|
||||
"__GNUC__=8",
|
||||
"__GXX_RTTI=1",
|
||||
"__cpp_delegating_constructors=200604",
|
||||
"__FLT_HAS_DENORM__=1",
|
||||
"__SIZEOF_LONG_DOUBLE__=8",
|
||||
"__BIGGEST_ALIGNMENT__=16",
|
||||
"__STDC_UTF_16__=1",
|
||||
"__FLT64_MAX_10_EXP__=308",
|
||||
"__FLT32_HAS_INFINITY__=1",
|
||||
"__DBL_MAX__=double(1.7976931348623157e+308L)",
|
||||
"__cpp_raw_strings=200710",
|
||||
"__INT_FAST32_MAX__=0x7fffffff",
|
||||
"__DBL_HAS_INFINITY__=1",
|
||||
"__DEC32_MIN_EXP__=(-94)",
|
||||
"__INTPTR_WIDTH__=32",
|
||||
"__FLT32X_HAS_DENORM__=1",
|
||||
"__INT_FAST16_TYPE__=int",
|
||||
"__LDBL_HAS_DENORM__=1",
|
||||
"__cplusplus=201402L",
|
||||
"__cpp_ref_qualifiers=200710",
|
||||
"__DEC128_MAX__=9.999999999999999999999999999999999E6144DL",
|
||||
"__INT_LEAST32_MAX__=0x7fffffff",
|
||||
"__DEC32_MIN__=1E-95DF",
|
||||
"__DEPRECATED=1",
|
||||
"__cpp_rvalue_references=200610",
|
||||
"__DBL_MAX_EXP__=1024",
|
||||
"__WCHAR_WIDTH__=16",
|
||||
"__FLT32_MAX__=3.4028234663852886e+38F32",
|
||||
"__DEC128_EPSILON__=1E-33DL",
|
||||
"__PTRDIFF_MAX__=0x7fffffff",
|
||||
"__FLT32_HAS_QUIET_NAN__=1",
|
||||
"__GNUG__=8",
|
||||
"__LONG_LONG_MAX__=0x7fffffffffffffffLL",
|
||||
"__SIZEOF_SIZE_T__=4",
|
||||
"__cpp_rvalue_reference=200610",
|
||||
"__cpp_nsdmi=200809",
|
||||
"__SIZEOF_WINT_T__=4",
|
||||
"__LONG_LONG_WIDTH__=64",
|
||||
"__cpp_initializer_lists=200806",
|
||||
"__FLT32_MAX_EXP__=128",
|
||||
"__cpp_hex_float=201603",
|
||||
"__GXX_ABI_VERSION=1013",
|
||||
"__FLT_MIN_EXP__=(-125)",
|
||||
"__cpp_lambdas=200907",
|
||||
"__INT_FAST64_TYPE__=long long int",
|
||||
"__FP_FAST_FMAF=1",
|
||||
"__FLT64_DENORM_MIN__=4.9406564584124654e-324F64",
|
||||
"__DBL_MIN__=double(2.2250738585072014e-308L)",
|
||||
"__FLT32X_EPSILON__=2.2204460492503131e-16F32x",
|
||||
"__FLT64_MIN_10_EXP__=(-307)",
|
||||
"__DEC128_MIN__=1E-6143DL",
|
||||
"__REGISTER_PREFIX__",
|
||||
"__UINT16_MAX__=0xffff",
|
||||
"__DBL_HAS_DENORM__=1",
|
||||
"__FLT32_MIN__=1.1754943508222875e-38F32",
|
||||
"__UINT8_TYPE__=unsigned char",
|
||||
"__NO_INLINE__=1",
|
||||
"__FLT_MANT_DIG__=24",
|
||||
"__LDBL_DECIMAL_DIG__=17",
|
||||
"__VERSION__=\"8.4.0\"",
|
||||
"__UINT64_C(c)=c ## ULL",
|
||||
"__cpp_unicode_characters=200704",
|
||||
"__cpp_decltype_auto=201304",
|
||||
"__GCC_ATOMIC_INT_LOCK_FREE=2",
|
||||
"__FLT32_MANT_DIG__=24",
|
||||
"__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__",
|
||||
"__SCHAR_WIDTH__=8",
|
||||
"__INT32_C(c)=c",
|
||||
"__DEC64_EPSILON__=1E-15DD",
|
||||
"__ORDER_PDP_ENDIAN__=3412",
|
||||
"__DEC128_MIN_EXP__=(-6142)",
|
||||
"__FLT32_MAX_10_EXP__=38",
|
||||
"__INT_FAST32_TYPE__=int",
|
||||
"__UINT_LEAST16_TYPE__=short unsigned int",
|
||||
"__INT16_MAX__=0x7fff",
|
||||
"__cpp_rtti=199711",
|
||||
"__SIZE_TYPE__=unsigned int",
|
||||
"__UINT64_MAX__=0xffffffffffffffffULL",
|
||||
"__INT8_TYPE__=signed char",
|
||||
"__cpp_digit_separators=201309",
|
||||
"__ELF__=1",
|
||||
"__xtensa__=1",
|
||||
"__FLT_RADIX__=2",
|
||||
"__INT_LEAST16_TYPE__=short int",
|
||||
"__LDBL_EPSILON__=2.2204460492503131e-16L",
|
||||
"__UINTMAX_C(c)=c ## ULL",
|
||||
"__SIG_ATOMIC_MAX__=0x7fffffff",
|
||||
"__GCC_ATOMIC_WCHAR_T_LOCK_FREE=2",
|
||||
"__SIZEOF_PTRDIFF_T__=4",
|
||||
"__FLT32X_MANT_DIG__=53",
|
||||
"__FLT32X_MIN_EXP__=(-1021)",
|
||||
"__DEC32_SUBNORMAL_MIN__=0.000001E-95DF",
|
||||
"__INT_FAST16_MAX__=0x7fffffff",
|
||||
"__FLT64_DIG__=15",
|
||||
"__UINT_FAST32_MAX__=0xffffffffU",
|
||||
"__UINT_LEAST64_TYPE__=long long unsigned int",
|
||||
"__FLT_HAS_QUIET_NAN__=1",
|
||||
"__FLT_MAX_10_EXP__=38",
|
||||
"__LONG_MAX__=0x7fffffffL",
|
||||
"__DEC128_SUBNORMAL_MIN__=0.000000000000000000000000000000001E-6143DL",
|
||||
"__FLT_HAS_INFINITY__=1",
|
||||
"__cpp_unicode_literals=200710",
|
||||
"__UINT_FAST16_TYPE__=unsigned int",
|
||||
"__DEC64_MAX__=9.999999999999999E384DD",
|
||||
"__INT_FAST32_WIDTH__=32",
|
||||
"__CHAR16_TYPE__=short unsigned int",
|
||||
"__PRAGMA_REDEFINE_EXTNAME=1",
|
||||
"__SIZE_WIDTH__=32",
|
||||
"__INT_LEAST16_MAX__=0x7fff",
|
||||
"__DEC64_MANT_DIG__=16",
|
||||
"__INT64_MAX__=0x7fffffffffffffffLL",
|
||||
"__UINT_LEAST32_MAX__=0xffffffffU",
|
||||
"__FLT32_DENORM_MIN__=1.4012984643248171e-45F32",
|
||||
"__GCC_ATOMIC_LONG_LOCK_FREE=2",
|
||||
"__SIG_ATOMIC_WIDTH__=32",
|
||||
"__INT_LEAST64_TYPE__=long long int",
|
||||
"__INT16_TYPE__=short int",
|
||||
"__INT_LEAST8_TYPE__=signed char",
|
||||
"__DEC32_MAX_EXP__=97",
|
||||
"__INT_FAST8_MAX__=0x7fffffff",
|
||||
"__INTPTR_MAX__=0x7fffffff",
|
||||
"__cpp_sized_deallocation=201309",
|
||||
"__cpp_range_based_for=200907",
|
||||
"__FLT64_HAS_QUIET_NAN__=1",
|
||||
"__FLT32_MIN_10_EXP__=(-37)",
|
||||
"__EXCEPTIONS=1",
|
||||
"__LDBL_MANT_DIG__=53",
|
||||
"__DBL_HAS_QUIET_NAN__=1",
|
||||
"__FLT64_HAS_INFINITY__=1",
|
||||
"__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)",
|
||||
"__cpp_return_type_deduction=201304",
|
||||
"__INTPTR_TYPE__=int",
|
||||
"__UINT16_TYPE__=short unsigned int",
|
||||
"__WCHAR_TYPE__=short unsigned int",
|
||||
"__SIZEOF_FLOAT__=4",
|
||||
"__UINTPTR_MAX__=0xffffffffU",
|
||||
"__INT_FAST64_WIDTH__=64",
|
||||
"__DEC64_MIN_EXP__=(-382)",
|
||||
"__cpp_decltype=200707",
|
||||
"__FLT32_DECIMAL_DIG__=9",
|
||||
"__INT_FAST64_MAX__=0x7fffffffffffffffLL",
|
||||
"__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1",
|
||||
"__FLT_DIG__=6",
|
||||
"__UINT_FAST64_TYPE__=long long unsigned int",
|
||||
"__INT_MAX__=0x7fffffff",
|
||||
"__INT64_TYPE__=long long int",
|
||||
"__FLT_MAX_EXP__=128",
|
||||
"__DBL_MANT_DIG__=53",
|
||||
"__cpp_inheriting_constructors=201511",
|
||||
"__INT_LEAST64_MAX__=0x7fffffffffffffffLL",
|
||||
"__FP_FAST_FMAF32=1",
|
||||
"__DEC64_MIN__=1E-383DD",
|
||||
"__WINT_TYPE__=unsigned int",
|
||||
"__UINT_LEAST32_TYPE__=unsigned int",
|
||||
"__SIZEOF_SHORT__=2",
|
||||
"__LDBL_MIN_EXP__=(-1021)",
|
||||
"__FLT64_MAX__=1.7976931348623157e+308F64",
|
||||
"__WINT_WIDTH__=32",
|
||||
"__INT_LEAST8_MAX__=0x7f",
|
||||
"__FLT32X_MAX_10_EXP__=308",
|
||||
"__WCHAR_UNSIGNED__=1",
|
||||
"__LDBL_MAX_10_EXP__=308",
|
||||
"__ATOMIC_RELAXED=0",
|
||||
"__DBL_EPSILON__=double(2.2204460492503131e-16L)",
|
||||
"__XTENSA_WINDOWED_ABI__=1",
|
||||
"__UINT8_C(c)=c",
|
||||
"__FLT64_MAX_EXP__=1024",
|
||||
"__INT_LEAST32_TYPE__=int",
|
||||
"__SIZEOF_WCHAR_T__=2",
|
||||
"__INT_FAST8_TYPE__=int",
|
||||
"__GNUC_STDC_INLINE__=1",
|
||||
"__FLT64_HAS_DENORM__=1",
|
||||
"__FLT32_EPSILON__=1.1920928955078125e-7F32",
|
||||
"__DBL_DECIMAL_DIG__=17",
|
||||
"__STDC_UTF_32__=1",
|
||||
"__INT_FAST8_WIDTH__=32",
|
||||
"__DEC_EVAL_METHOD__=2",
|
||||
"__FLT32X_MAX__=1.7976931348623157e+308F32x",
|
||||
"__XTENSA__=1",
|
||||
"__ORDER_BIG_ENDIAN__=4321",
|
||||
"__cpp_runtime_arrays=198712",
|
||||
"__UINT64_TYPE__=long long unsigned int",
|
||||
"__UINT32_C(c)=c ## U",
|
||||
"__INTMAX_MAX__=0x7fffffffffffffffLL",
|
||||
"__cpp_alias_templates=200704",
|
||||
"__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
|
||||
"__FLT_DENORM_MIN__=1.4012984643248171e-45F",
|
||||
"__INT8_MAX__=0x7f",
|
||||
"__LONG_WIDTH__=32",
|
||||
"__UINT_FAST32_TYPE__=unsigned int",
|
||||
"__CHAR32_TYPE__=unsigned int",
|
||||
"__FLT_MAX__=3.4028234663852886e+38F",
|
||||
"__cpp_constexpr=201304",
|
||||
"__INT32_TYPE__=int",
|
||||
"__SIZEOF_DOUBLE__=8",
|
||||
"__cpp_exceptions=199711",
|
||||
"__FLT_MIN_10_EXP__=(-37)",
|
||||
"__FLT64_MIN__=2.2250738585072014e-308F64",
|
||||
"__INT_LEAST32_WIDTH__=32",
|
||||
"__INTMAX_TYPE__=long long int",
|
||||
"__DEC128_MAX_EXP__=6145",
|
||||
"__FLT32X_HAS_QUIET_NAN__=1",
|
||||
"__ATOMIC_CONSUME=1",
|
||||
"__GNUC_MINOR__=4",
|
||||
"__INT_FAST16_WIDTH__=32",
|
||||
"__UINTMAX_MAX__=0xffffffffffffffffULL",
|
||||
"__DEC32_MANT_DIG__=7",
|
||||
"__FLT32X_DENORM_MIN__=4.9406564584124654e-324F32x",
|
||||
"__DBL_MAX_10_EXP__=308",
|
||||
"__LDBL_DENORM_MIN__=4.9406564584124654e-324L",
|
||||
"__INT16_C(c)=c",
|
||||
"__cpp_generic_lambdas=201304",
|
||||
"__STDC__=1",
|
||||
"__FLT32X_DIG__=15",
|
||||
"__PTRDIFF_TYPE__=int",
|
||||
"__ATOMIC_SEQ_CST=5",
|
||||
"__UINT32_TYPE__=unsigned int",
|
||||
"__FLT32X_MIN_10_EXP__=(-307)",
|
||||
"__UINTPTR_TYPE__=unsigned int",
|
||||
"__DEC64_SUBNORMAL_MIN__=0.000000000000001E-383DD",
|
||||
"__DEC128_MANT_DIG__=34",
|
||||
"__LDBL_MIN_10_EXP__=(-307)",
|
||||
"__SIZEOF_LONG_LONG__=8",
|
||||
"__cpp_user_defined_literals=200809",
|
||||
"__GCC_ATOMIC_LLONG_LOCK_FREE=1",
|
||||
"__FLT32X_MIN__=2.2250738585072014e-308F32x",
|
||||
"__LDBL_DIG__=15",
|
||||
"__FLT_DECIMAL_DIG__=9",
|
||||
"__UINT_FAST16_MAX__=0xffffffffU",
|
||||
"__GCC_ATOMIC_SHORT_LOCK_FREE=2",
|
||||
"__INT_LEAST64_WIDTH__=64",
|
||||
"__UINT_FAST8_TYPE__=unsigned int",
|
||||
"__cpp_init_captures=201304",
|
||||
"__ATOMIC_ACQ_REL=4",
|
||||
"__ATOMIC_RELEASE=3",
|
||||
"USBCON"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"*.ejs": "html",
|
||||
".env": "env",
|
||||
".env.*": "env",
|
||||
"weather.h": "c",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ranges": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"Fira"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#define WIFI_SSID "your_ssid"
|
||||
#define WIFI_PASS "your_password"
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
#include "dow.h"
|
||||
|
||||
bool firstRender = true;
|
||||
uint16_t reRenders = 0;
|
||||
int16_t tbx, tby;
|
||||
uint16_t tbw, tbh;
|
||||
|
||||
const GFXfont* DOW_FONTS[] = {
|
||||
&FreeSans12pt7b,
|
||||
&FreeSans24pt7b,
|
||||
&FiraCode_Bold62pt7b,
|
||||
&FreeSans9pt7b
|
||||
};
|
||||
|
||||
void dow_apply_font(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, uint8_t font)
|
||||
{
|
||||
if (font > 3) {
|
||||
font = 3;
|
||||
}
|
||||
|
||||
display.setFont(DOW_FONTS[font]);
|
||||
}
|
||||
|
||||
void dow_get_text_item_rect(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item, bool forText, int *rx, int *ry, int *rw, int *rh)
|
||||
{
|
||||
dow_apply_font(display, item->font);
|
||||
display.getTextBounds(item->contents, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||
|
||||
int x = item->x;
|
||||
int y = item->y;
|
||||
int w = tbw;
|
||||
int h = tbh;
|
||||
|
||||
switch (item->horizontalAlign)
|
||||
{
|
||||
case ITEM_ALIGN_CENTER:
|
||||
{
|
||||
x -= round((double)w / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_ALIGN_END:
|
||||
{
|
||||
x -= w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (item->verticalAlign)
|
||||
{
|
||||
case ITEM_ALIGN_CENTER:
|
||||
{
|
||||
y += round((double)h / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_ALIGN_START:
|
||||
{
|
||||
y += h;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!forText)
|
||||
{
|
||||
display.getTextBounds(item->contents, x, y, &tbx, &tby, &tbw, &tbh);
|
||||
|
||||
*rx = tbx;
|
||||
*ry = tby;
|
||||
*rw = tbw;
|
||||
*rh = tbh;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
*rx = x;
|
||||
*ry = y;
|
||||
*rw = w;
|
||||
*rh = h;
|
||||
}
|
||||
|
||||
void dow_get_item_rect(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item, int *rx, int *ry, int *rw, int *rh)
|
||||
{
|
||||
switch (item->type)
|
||||
{
|
||||
case ITEM_TYPE_TEXT:
|
||||
{
|
||||
dow_get_text_item_rect(display, item, false, rx, ry, rw, rh);
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_LINE:
|
||||
{
|
||||
int minX = min(item->x, item->x2);
|
||||
int minY = min(item->y, item->y2);
|
||||
int maxX = max(item->x, item->x2);
|
||||
int maxY = max(item->y, item->y2);
|
||||
*rx = minX;
|
||||
*ry = minY;
|
||||
*rw = (maxX - minX);
|
||||
*rh = (maxY - minY);
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_CIRCLE:
|
||||
{
|
||||
*rx = item->x - item->radius;
|
||||
*ry = item->y - item->radius;
|
||||
*rw = item->radius * 2;
|
||||
*rh = item->radius * 2;
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_CIRCLE_FILL:
|
||||
{
|
||||
*rx = item->x - item->radius;
|
||||
*ry = item->y - item->radius;
|
||||
*rw = item->radius * 2;
|
||||
*rh = item->radius * 2;
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_RECT:
|
||||
{
|
||||
*rx = item->x;
|
||||
*ry = item->y;
|
||||
*rw = item->x2;
|
||||
*rh = item->y2;
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_RECT_FILL:
|
||||
{
|
||||
*rx = item->x;
|
||||
*ry = item->y;
|
||||
*rw = item->x2;
|
||||
*rh = item->y2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dow_render_text_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
dow_get_text_item_rect(display, item, true, &x, &y, &w, &h);
|
||||
|
||||
display.setCursor(x, y);
|
||||
display.print(item->contents);
|
||||
}
|
||||
|
||||
void dow_render_rectangle_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||||
{
|
||||
display.drawRect(item->x, item->y, item->x2, item->y2, GxEPD_BLACK);
|
||||
}
|
||||
|
||||
void dow_render_filled_rectangle_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||||
{
|
||||
display.fillRect(item->x, item->y, item->x2, item->y2, GxEPD_BLACK);
|
||||
}
|
||||
|
||||
void dow_render_circle_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||||
{
|
||||
display.drawCircle(item->x, item->y, item->radius, GxEPD_BLACK);
|
||||
}
|
||||
|
||||
void dow_render_filled_circle_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||||
{
|
||||
display.fillCircle(item->x, item->y, item->radius, GxEPD_BLACK);
|
||||
}
|
||||
|
||||
void dow_render_line_item(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, dow_item_t *item)
|
||||
{
|
||||
display.drawLine(item->x, item->y, item->x2, item->y2, GxEPD_BLACK);
|
||||
}
|
||||
|
||||
void dow_render(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, std::vector<dow_item_t> &data)
|
||||
{
|
||||
bool needsFullRender = reRenders > 5*60*6;
|
||||
|
||||
if (needsFullRender || firstRender)
|
||||
{
|
||||
display.setFullWindow();
|
||||
display.setRotation(0);
|
||||
display.setTextColor(GxEPD_BLACK);
|
||||
display.firstPage();
|
||||
|
||||
reRenders = 0;
|
||||
firstRender = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
display.setPartialWindow(0, 0, display.width(), display.height());
|
||||
display.setRotation(0);
|
||||
display.firstPage();
|
||||
|
||||
reRenders++;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
display.fillScreen(GxEPD_WHITE);
|
||||
display.setTextColor(GxEPD_BLACK);
|
||||
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
dow_item_t *item = &data[i];
|
||||
|
||||
switch (item->type)
|
||||
{
|
||||
case ITEM_TYPE_TEXT:
|
||||
{
|
||||
dow_render_text_item(display, item);
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_CIRCLE:
|
||||
{
|
||||
dow_render_circle_item(display, item);
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_CIRCLE_FILL:
|
||||
{
|
||||
dow_render_filled_circle_item(display, item);
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_RECT:
|
||||
{
|
||||
dow_render_rectangle_item(display, item);
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_RECT_FILL:
|
||||
{
|
||||
dow_render_filled_rectangle_item(display, item);
|
||||
break;
|
||||
}
|
||||
case ITEM_TYPE_LINE:
|
||||
{
|
||||
dow_render_line_item(display, item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
DEBUG: Draw bounding box
|
||||
int x1, y1, w1, h1;
|
||||
dow_get_text_item_rect(display, item, false, &x1, &y1, &w1, &h1);
|
||||
display.drawRect(x1, y1, w1, h1, GxEPD_BLACK);
|
||||
*/
|
||||
}
|
||||
} while (display.nextPage());
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef _DOW_H
|
||||
#define _DOW_H
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <vector>
|
||||
#include <GxEPD2_BW.h>
|
||||
#include "dow_fonts.h"
|
||||
|
||||
#define ITEM_TYPE_TEXT 0
|
||||
#define ITEM_TYPE_LINE 1
|
||||
#define ITEM_TYPE_CIRCLE 2
|
||||
#define ITEM_TYPE_CIRCLE_FILL 3
|
||||
#define ITEM_TYPE_RECT 4
|
||||
#define ITEM_TYPE_RECT_FILL 5
|
||||
|
||||
#define ITEM_ALIGN_START 0
|
||||
#define ITEM_ALIGN_CENTER 1
|
||||
#define ITEM_ALIGN_END 2
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int x2;
|
||||
int y2;
|
||||
float radius;
|
||||
uint8_t type;
|
||||
uint8_t font;
|
||||
uint8_t verticalAlign;
|
||||
uint8_t horizontalAlign;
|
||||
String contents;
|
||||
} dow_item_t;
|
||||
|
||||
void dow_render(GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> &display, std::vector<dow_item_t> &data);
|
||||
#endif // _DOW_H
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#include "dow_fetch.h"
|
||||
|
||||
int dow_fetch(const char *url, std::vector<dow_item_t> &target)
|
||||
{
|
||||
int responseCode = -1;
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http;
|
||||
|
||||
http.useHTTP10(true);
|
||||
http.begin(client, url);
|
||||
|
||||
responseCode = http.GET();
|
||||
|
||||
if (responseCode != 200)
|
||||
{
|
||||
Serial.print("HTTPClient error:");
|
||||
Serial.println(responseCode);
|
||||
http.end();
|
||||
return -1;
|
||||
}
|
||||
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, http.getStream());
|
||||
|
||||
target.clear();
|
||||
|
||||
dow_item_t dow_item;
|
||||
uint32_t i = 0;
|
||||
for (JsonObject item : doc.as<JsonArray>())
|
||||
{
|
||||
i++;
|
||||
|
||||
if (!item.containsKey("x") || !item.containsKey("y") || !item.containsKey("t"))
|
||||
{
|
||||
Serial.print("Invalid item at index ");
|
||||
Serial.println(i - 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// These are required
|
||||
dow_item.x = item["x"].as<int>();
|
||||
dow_item.y = item["y"].as<int>();
|
||||
dow_item.type = item["t"].as<int>();
|
||||
|
||||
// Reset to default values
|
||||
dow_item.verticalAlign = 0;
|
||||
dow_item.horizontalAlign = 0;
|
||||
dow_item.font = 0;
|
||||
dow_item.radius = 0;
|
||||
dow_item.contents = "";
|
||||
|
||||
if (item.containsKey("x2"))
|
||||
dow_item.x2 = item["x2"].as<int>();
|
||||
if (item.containsKey("y2"))
|
||||
dow_item.y2 = item["y2"].as<int>();
|
||||
if (item.containsKey("r"))
|
||||
dow_item.radius = item["r"].as<float>();
|
||||
if (item.containsKey("f"))
|
||||
dow_item.font = item["f"].as<int>();
|
||||
if (item.containsKey("va"))
|
||||
dow_item.verticalAlign = item["va"].as<int>();
|
||||
if (item.containsKey("ha"))
|
||||
dow_item.horizontalAlign = item["ha"].as<int>();
|
||||
if (item.containsKey("c"))
|
||||
dow_item.contents = item["c"].as<String>();
|
||||
|
||||
/*
|
||||
Serial.print("x: ");
|
||||
Serial.print(dow_item.x);
|
||||
Serial.print(" y: ");
|
||||
Serial.print(dow_item.y);
|
||||
Serial.print(" x2: ");
|
||||
Serial.print(dow_item.x2);
|
||||
Serial.print(" y2: ");
|
||||
Serial.print(dow_item.y2);
|
||||
Serial.print(" r: ");
|
||||
Serial.print(dow_item.radius);
|
||||
Serial.print(" t: ");
|
||||
Serial.print(dow_item.type);
|
||||
Serial.print(" f: ");
|
||||
Serial.print(dow_item.font);
|
||||
Serial.print(" va: ");
|
||||
Serial.print(dow_item.verticalAlign);
|
||||
Serial.print(" ha: ");
|
||||
Serial.print(dow_item.horizontalAlign);
|
||||
Serial.print(" c: ");
|
||||
Serial.println(dow_item.contents);
|
||||
*/
|
||||
|
||||
target.push_back(dow_item);
|
||||
}
|
||||
|
||||
http.end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _DOW_FETCH_H
|
||||
#define _DOW_FETCH_H
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "dow.h"
|
||||
|
||||
int dow_fetch(const char * url, std::vector<dow_item_t> &target);
|
||||
#endif // _DOW_FETCH_H
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _DOW_FONTS_H
|
||||
#define _DOW_FONTS_H
|
||||
|
||||
#include <Fonts/FreeSans9pt7b.h>
|
||||
#include <Fonts/FreeSans12pt7b.h>
|
||||
#include <Fonts/FreeSans24pt7b.h>
|
||||
#include "fonts/fira_code_62.h"
|
||||
#endif // _DOW_FONTS_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,78 @@
|
|||
#define ENABLE_GxEPD2_GFX 0
|
||||
|
||||
#include <GxEPD2_BW.h>
|
||||
#include <WiFi.h>
|
||||
#include "creds.h"
|
||||
#include "dow_fetch.h"
|
||||
#include "dow.h"
|
||||
|
||||
#define DOW_ENDPOINT "http://screen-data.lan/api/dow"
|
||||
// #define DOW_ENDPOINT "http://192.168.0.210:8062/api/dow"
|
||||
|
||||
GxEPD2_BW<GxEPD2_583_GDEQ0583T31, GxEPD2_583_GDEQ0583T31::HEIGHT> display(GxEPD2_583_GDEQ0583T31(/*CS=*/GPIO_NUM_5, /*DC=*/GPIO_NUM_17, /*RST=*/GPIO_NUM_16, /*BUSY=*/GPIO_NUM_4)); // GDEQ0583T31 648x480, UC8179, (P583010-MF1-B)
|
||||
|
||||
const char *ssid = WIFI_SSID;
|
||||
const char *password = WIFI_PASS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println("setup");
|
||||
|
||||
delay(100);
|
||||
|
||||
Serial.println("Display power ON");
|
||||
|
||||
display.init(115200);
|
||||
display.fillScreen(GxEPD_WHITE);
|
||||
|
||||
display.setFont(&FreeSans12pt7b);
|
||||
|
||||
int16_t tbx, tby;
|
||||
uint16_t tbw, tbh;
|
||||
display.getTextBounds("connecting...", 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||
// center bounding box by transposition of origin:
|
||||
uint16_t x = ((display.width() - tbw) / 2) - tbx;
|
||||
uint16_t y = ((display.height() - tbh) / 2) - tby;
|
||||
|
||||
display.setFullWindow();
|
||||
display.setRotation(0);
|
||||
display.setTextColor(GxEPD_BLACK);
|
||||
display.firstPage();
|
||||
do
|
||||
{
|
||||
display.fillScreen(GxEPD_WHITE);
|
||||
display.setCursor(x, y);
|
||||
display.print("connecting...");
|
||||
} while (display.nextPage());
|
||||
|
||||
Serial.print("Connecting to wifi: ");
|
||||
|
||||
delay(500);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.print("Connected");
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
std::vector<dow_item_t> current_items;
|
||||
|
||||
void loop()
|
||||
{
|
||||
dow_fetch(DOW_ENDPOINT, current_items);
|
||||
dow_render(display, current_items);
|
||||
|
||||
display.powerOff();
|
||||
|
||||
delay(10000);
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
node_modules
|
||||
cache/
|
||||
|
||||
npm-debug.log
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[*]
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
|
|
@ -0,0 +1 @@
|
|||
PORT=8062
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
plugins: [],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
indent: 'off',
|
||||
curly: ['warn', 'all'],
|
||||
'padding-line-between-statements': [
|
||||
'warn',
|
||||
{
|
||||
blankLine: 'always',
|
||||
prev: '*',
|
||||
next: [
|
||||
'block-like',
|
||||
'multiline-expression',
|
||||
'multiline-const',
|
||||
'return',
|
||||
],
|
||||
},
|
||||
{
|
||||
blankLine: 'always',
|
||||
prev: ['block-like', 'multiline-expression', 'multiline-const'],
|
||||
next: '*',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/indent': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/explicit-member-accessibility': [
|
||||
'warn',
|
||||
{ accessibility: 'no-public' },
|
||||
],
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/member-delimiter-style': [
|
||||
'warn',
|
||||
{ multiline: { delimiter: 'none' } },
|
||||
],
|
||||
'@typescript-eslint/no-object-literal-type-assertion': 'off',
|
||||
'@typescript-eslint/prefer-interface': 'off',
|
||||
'prettier/prettier': 'warn',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
cache/
|
||||
static/build
|
||||
data/
|
||||
.env
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
useTabs: true,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
FROM node:20-alpine
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install app dependencies
|
||||
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
||||
# where available (npm@5+)
|
||||
COPY package.json ./
|
||||
COPY yarn.lock ./
|
||||
|
||||
# Bundle app source
|
||||
COPY src ./src
|
||||
COPY static ./static
|
||||
COPY tsconfig.json ./tsconfig.json
|
||||
|
||||
|
||||
RUN yarn install
|
||||
# If you are building your code for production
|
||||
# RUN npm ci --only=production
|
||||
|
||||
ENV DATA_PATH=/data
|
||||
VOLUME [ "/data" ]
|
||||
|
||||
EXPOSE 8080
|
||||
CMD [ "yarn", "start" ]
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"name": "watches-server",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts",
|
||||
"start": "cross-env NODE_ENV=production ts-node src/index.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@google-cloud/local-auth": "2.1.0",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"csvtojson": "^2.0.10",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.17.1",
|
||||
"googleapis": "105",
|
||||
"json5": "^2.1.3",
|
||||
"luxon": "^3.4.4",
|
||||
"node-fetch": "^2.6.1",
|
||||
"sunrise-sunset-js": "^2.2.1",
|
||||
"systeminformation": "^5.7.13",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.9",
|
||||
"@types/json5": "0.0.30",
|
||||
"@types/node": "^14.14.10",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@typescript-eslint/eslint-plugin": "^7.11.0",
|
||||
"@typescript-eslint/parser": "^7.11.0",
|
||||
"eslint": "^8",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"nodemon": "^2.0.7",
|
||||
"prettier": "^3.2.5"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
export type AppConfig = Awaited<ReturnType<typeof loadConfig>>
|
||||
|
||||
export const loadConfig = async () => {
|
||||
const port = process.env.PORT || '80'
|
||||
const staticPath = process.env.STATIC || 'static'
|
||||
const cache = process.env.CACHE || 'cache'
|
||||
const dataPath = process.env.DATA_PATH || 'data'
|
||||
const timeZone = process.env.TIME_ZONE || 'Europe/Prague'
|
||||
|
||||
return {
|
||||
port: parseInt(port),
|
||||
static: staticPath,
|
||||
dataPath,
|
||||
timeZone,
|
||||
cache: {
|
||||
path: cache,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import { cachedFetch } from '../lib/cached-fetch'
|
||||
import { Logger } from '../lib/logger'
|
||||
import { AppConfig } from './config'
|
||||
|
||||
type PromiseReturnType<T extends Promise<unknown>> =
|
||||
T extends Promise<infer U> ? U : never
|
||||
|
||||
export type AppContext = PromiseReturnType<ReturnType<typeof createContext>>
|
||||
|
||||
export const createContext = async (config: AppConfig) => {
|
||||
return {
|
||||
createLogger: (ctx: string) => new Logger(ctx),
|
||||
config,
|
||||
fetch: cachedFetch(config.cache),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { Request, Response } from 'express'
|
||||
|
||||
export const corsMiddleware =
|
||||
() => (req: Request, res: Response, next: () => void) => {
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
|
||||
res.header(
|
||||
'Access-Control-Allow-Methods',
|
||||
'POST, GET, PUT, OPTIONS, DELETE',
|
||||
)
|
||||
|
||||
res.header(
|
||||
'Access-Control-Allow-Headers',
|
||||
'Accept-Language, ev-user, Content-type, x-session, authorization',
|
||||
)
|
||||
|
||||
if (req.method.toLowerCase() === 'options') {
|
||||
res.send()
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { NextFunction, Request, Response } from 'express'
|
||||
|
||||
export const route =
|
||||
<R>(cb: (req: Request, res: Response, next: NextFunction) => Promise<R>) =>
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
cb(req, res, next).catch(next)
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { Router } from 'express'
|
||||
import { AppContext } from './context'
|
||||
|
||||
export const router = (cb: (router: Router, ctx: AppContext) => void) => {
|
||||
return (context: AppContext) => {
|
||||
const router = Router()
|
||||
|
||||
cb(router, context)
|
||||
|
||||
return router
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
import { DateTime } from 'luxon'
|
||||
import { route } from '../route'
|
||||
import { router } from '../router'
|
||||
import { calendarService } from '../services/calendar'
|
||||
import { weatherService } from '../services/weather'
|
||||
// import { getSunrise, getSunset } from 'sunrise-sunset-js'
|
||||
|
||||
const TYPES = {
|
||||
TEXT: 0,
|
||||
LINE: 1,
|
||||
CIRCLE: 2,
|
||||
CIRCLE_FILL: 3,
|
||||
RECT: 4,
|
||||
RECT_FILL: 5,
|
||||
}
|
||||
|
||||
const ALIGN = {
|
||||
START: 0,
|
||||
CENTER: 1,
|
||||
END: 2,
|
||||
}
|
||||
|
||||
const weekdaysInCs = [
|
||||
'Pondeli',
|
||||
'Utery',
|
||||
'Streda',
|
||||
'Ctvrtek',
|
||||
'Patek',
|
||||
'Sobota',
|
||||
'Nedele',
|
||||
]
|
||||
|
||||
const CALENDARS = [
|
||||
'honza.zipek@momence.com',
|
||||
'2os54ac003off9sbgbnepq2q5k@group.calendar.google.com',
|
||||
'family05419723423556202215@group.calendar.google.com',
|
||||
'primary',
|
||||
]
|
||||
|
||||
type Widget = {
|
||||
x: number
|
||||
y: number
|
||||
x2?: number
|
||||
y2?: number
|
||||
c?: string
|
||||
t: number
|
||||
va?: number
|
||||
ha?: number
|
||||
f?: number
|
||||
}
|
||||
|
||||
export const dowRoutes = router((router, ctx) => {
|
||||
router.get(
|
||||
'/',
|
||||
route(async (req, res) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const WIDTH = 648
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const HEIGHT = 480
|
||||
|
||||
const now = DateTime.now().setZone(ctx.config.timeZone)
|
||||
|
||||
const hours = now.hour.toString().padStart(2, '0')
|
||||
const minutes = now.minute.toString().padStart(2, '0')
|
||||
const dayOfWeek = weekdaysInCs[now.weekday - 1]
|
||||
const month = now.month
|
||||
const day = now.day
|
||||
|
||||
const weather = await weatherService(ctx)()
|
||||
const calendar = await calendarService(ctx)()
|
||||
|
||||
const events = (await calendar.events(CALENDARS))
|
||||
.filter((e) => e.status === 'confirmed')
|
||||
.slice(0, 10)
|
||||
|
||||
events.sort((a, b) => {
|
||||
if (a.start?.dateTime && !b.start?.dateTime) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if (!a.start?.dateTime && b.start?.dateTime) {
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
})
|
||||
|
||||
let summary = weather.now?.summary ?? ''
|
||||
|
||||
if (summary.endsWith('_day') || summary.endsWith('_night')) {
|
||||
summary = summary.replace(/_day|_night/, '')
|
||||
}
|
||||
|
||||
const widgets: Widget[] = [
|
||||
{
|
||||
x: WIDTH / 2,
|
||||
y: 30,
|
||||
t: TYPES.TEXT,
|
||||
c: `${hours}:${minutes}`,
|
||||
va: ALIGN.START,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 2,
|
||||
},
|
||||
{
|
||||
x: WIDTH / 2,
|
||||
y: 145,
|
||||
c: `${
|
||||
Math.round((weather.now?.temperature as number) ?? 0) ?? '-'
|
||||
} C ${summary}`,
|
||||
t: TYPES.TEXT,
|
||||
va: ALIGN.START,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 1,
|
||||
},
|
||||
]
|
||||
|
||||
// #region CALENDAR
|
||||
|
||||
const calendarY = 210
|
||||
const calendarX = 330
|
||||
const calendarW = WIDTH - calendarX - 30
|
||||
const calendarH = HEIGHT - calendarY - 10
|
||||
const calendarEventMaxLength = 27
|
||||
|
||||
const calendarEventsY = calendarY + 40
|
||||
|
||||
widgets.push({
|
||||
x: Math.round(calendarX + calendarW / 2),
|
||||
y: calendarY + 15,
|
||||
c: `${dayOfWeek} ${day}.${month}`,
|
||||
t: TYPES.TEXT,
|
||||
va: ALIGN.CENTER,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 0,
|
||||
})
|
||||
|
||||
widgets.push({
|
||||
x: calendarX,
|
||||
y: calendarY + 30,
|
||||
x2: calendarX + calendarW,
|
||||
y2: calendarY + 30,
|
||||
t: TYPES.LINE,
|
||||
})
|
||||
|
||||
widgets.push({
|
||||
x: calendarX,
|
||||
y: calendarY,
|
||||
x2: calendarW,
|
||||
y2: calendarH,
|
||||
t: TYPES.RECT,
|
||||
})
|
||||
|
||||
if (events.length === 0) {
|
||||
widgets.push({
|
||||
x: calendarX,
|
||||
y: calendarEventsY,
|
||||
c: 'Zadne udalosti',
|
||||
t: TYPES.TEXT,
|
||||
f: 3,
|
||||
})
|
||||
}
|
||||
|
||||
for (const [i, e] of events.entries()) {
|
||||
const start = e.start?.dateTime
|
||||
? DateTime.fromISO(e.start?.dateTime as string).setZone(
|
||||
ctx.config.timeZone,
|
||||
)
|
||||
: null
|
||||
|
||||
// Replace czech characters with their latin counterparts
|
||||
let title = (e.summary ?? 'Prace').replace(
|
||||
/[áéíóúýčďěňřšťžÁÉÍÓÚÝČĎĚŇŘŠŤŽ]/g,
|
||||
(c) =>
|
||||
'aeiouycdenrstzAEIOUYCDENRSTZ'[
|
||||
'áéíóúýčďěňřšťžÁÉÍÓÚÝČĎĚŇŘŠŤŽ'.indexOf(c)
|
||||
],
|
||||
)
|
||||
|
||||
if (title.length > calendarEventMaxLength) {
|
||||
title = title.slice(0, calendarEventMaxLength - 3) + '...'
|
||||
}
|
||||
|
||||
if (start) {
|
||||
widgets.push({
|
||||
x: calendarX + 48,
|
||||
y: calendarEventsY + i * 28,
|
||||
c: start.toFormat('HH:mm'),
|
||||
t: TYPES.TEXT,
|
||||
ha: ALIGN.END,
|
||||
f: 3,
|
||||
})
|
||||
}
|
||||
|
||||
widgets.push({
|
||||
x: calendarX + 55,
|
||||
y: calendarEventsY + i * 28,
|
||||
c: title,
|
||||
t: TYPES.TEXT,
|
||||
f: 3,
|
||||
})
|
||||
}
|
||||
|
||||
//#endregion CALENDAR
|
||||
|
||||
const next12Hours = Object.entries(weather.hours).slice(1, 13)
|
||||
|
||||
const minTemp =
|
||||
Math.min(...next12Hours.map(([, h]) => h.temperature as number)) - 5
|
||||
|
||||
const maxTemp = Math.max(
|
||||
...next12Hours.map(([, h]) => h.temperature as number),
|
||||
)
|
||||
|
||||
const tempRange = maxTemp - minTemp
|
||||
|
||||
const tempY = 250
|
||||
const tempX = 30
|
||||
const tempW = 280
|
||||
const tempH = 120
|
||||
const tempGraphP = 10
|
||||
const tempGraphW = tempW - tempGraphP * 2
|
||||
|
||||
widgets.push({
|
||||
x: tempX,
|
||||
y: tempY - 40,
|
||||
x2: tempW,
|
||||
y2: tempH,
|
||||
t: TYPES.RECT,
|
||||
})
|
||||
|
||||
widgets.push({
|
||||
x: tempX,
|
||||
y: tempY - 20,
|
||||
x2: tempX + tempW,
|
||||
y2: tempY - 20,
|
||||
t: TYPES.LINE,
|
||||
})
|
||||
|
||||
widgets.push({
|
||||
x: Math.floor(tempX + tempW / 2),
|
||||
y: tempY - 30,
|
||||
t: TYPES.TEXT,
|
||||
ha: ALIGN.CENTER,
|
||||
va: ALIGN.CENTER,
|
||||
c: 'Teplota',
|
||||
f: 3,
|
||||
})
|
||||
|
||||
for (const [offset, hour] of next12Hours) {
|
||||
const x = Math.floor(
|
||||
tempX +
|
||||
tempGraphP +
|
||||
(+offset - 1) * (tempGraphW / next12Hours.length),
|
||||
)
|
||||
|
||||
const y = tempY
|
||||
const temperature = hour.temperature as number
|
||||
const ratio = (temperature - minTemp) / tempRange
|
||||
const height = Math.floor(50 * ratio)
|
||||
const t = now.plus({ hours: +offset }).hour
|
||||
|
||||
widgets.push({
|
||||
x: x + 7,
|
||||
y: y + 5 + 50 - height,
|
||||
x2: 6,
|
||||
y2: height,
|
||||
t: TYPES.RECT_FILL,
|
||||
})
|
||||
|
||||
if (temperature === maxTemp || temperature === minTemp + 5) {
|
||||
widgets.push({
|
||||
x: x + 10,
|
||||
y: y,
|
||||
c: Math.floor(hour.temperature as number).toString(),
|
||||
t: TYPES.TEXT,
|
||||
va: ALIGN.END,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 3,
|
||||
})
|
||||
}
|
||||
|
||||
widgets.push({
|
||||
x: x + 10,
|
||||
y: y + 60,
|
||||
c: t.toString().padStart(2, '0'),
|
||||
t: TYPES.TEXT,
|
||||
va: ALIGN.START,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 3,
|
||||
})
|
||||
}
|
||||
|
||||
const minPre = Math.min(
|
||||
...next12Hours.map(([, h]) => h.precipitationAmount as number),
|
||||
)
|
||||
|
||||
const maxPre = Math.max(
|
||||
...next12Hours.map(([, h]) => h.precipitationAmount as number),
|
||||
)
|
||||
|
||||
const displayedMaxPre = Math.max(maxPre, 1)
|
||||
const preRange = displayedMaxPre - minPre
|
||||
|
||||
const preY = 250 + 120 + 20
|
||||
const preX = 30
|
||||
const preW = 280
|
||||
const preH = 120
|
||||
const preGraphP = 10
|
||||
const preGraphW = preW - preGraphP * 2
|
||||
|
||||
widgets.push({
|
||||
x: preX,
|
||||
y: preY - 40,
|
||||
x2: preW,
|
||||
y2: preH,
|
||||
t: TYPES.RECT,
|
||||
})
|
||||
|
||||
widgets.push({
|
||||
x: preX,
|
||||
y: preY - 20,
|
||||
x2: preX + preW,
|
||||
y2: preY - 20,
|
||||
t: TYPES.LINE,
|
||||
})
|
||||
|
||||
widgets.push({
|
||||
x: Math.floor(preX + preW / 2),
|
||||
y: preY - 30,
|
||||
t: TYPES.TEXT,
|
||||
ha: ALIGN.CENTER,
|
||||
va: ALIGN.CENTER,
|
||||
c: 'Dest',
|
||||
f: 3,
|
||||
})
|
||||
|
||||
for (const [offset, hour] of next12Hours) {
|
||||
const x = Math.floor(
|
||||
preX + preGraphP + (+offset - 1) * (preGraphW / next12Hours.length),
|
||||
)
|
||||
|
||||
const y = preY
|
||||
const pre = hour.precipitationAmount as number
|
||||
const ratio = (pre - minPre) / preRange
|
||||
const height = Math.floor(50 * ratio)
|
||||
const t = now.plus({ hours: +offset }).hour
|
||||
|
||||
widgets.push({
|
||||
x: x + 7,
|
||||
y: y + 5 + 50 - height,
|
||||
x2: 6,
|
||||
y2: height,
|
||||
t: TYPES.RECT_FILL,
|
||||
})
|
||||
|
||||
if (pre === maxPre && maxPre > 0.01) {
|
||||
widgets.push({
|
||||
x: x + 10,
|
||||
y: y,
|
||||
c: (hour.precipitationAmount as number).toFixed(1) + 'mm',
|
||||
t: TYPES.TEXT,
|
||||
va: ALIGN.END,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 3,
|
||||
})
|
||||
}
|
||||
|
||||
widgets.push({
|
||||
x: x + 10,
|
||||
y: y + 60,
|
||||
c: t.toString().padStart(2, '0'),
|
||||
t: TYPES.TEXT,
|
||||
va: ALIGN.START,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 3,
|
||||
})
|
||||
}
|
||||
|
||||
res.json(widgets)
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import { OAuth2Client } from 'google-auth-library'
|
||||
import { route } from '../route'
|
||||
import { router } from '../router'
|
||||
import { googleAuthService } from '../services/googleAuth'
|
||||
|
||||
export const googleAuthRoutes = router((router, ctx) => {
|
||||
const getClient = async () => {
|
||||
const googleAuth = await googleAuthService(ctx)()
|
||||
const credentials = await googleAuth.getCredentials()
|
||||
|
||||
const redirectUri = new URL(
|
||||
credentials.redirect_uris[0] ?? 'http://localhost',
|
||||
)
|
||||
|
||||
return {
|
||||
googleAuth,
|
||||
credentials,
|
||||
redirectUri,
|
||||
client: new OAuth2Client({
|
||||
clientId: credentials.client_id,
|
||||
clientSecret: credentials.client_secret,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
router.get(
|
||||
'/begin',
|
||||
route(async (req, res) => {
|
||||
const { client, redirectUri, googleAuth } = await getClient()
|
||||
const scopes = googleAuth.getScopes()
|
||||
|
||||
res.redirect(
|
||||
client.generateAuthUrl({
|
||||
redirect_uri: redirectUri.toString(),
|
||||
access_type: 'offline',
|
||||
scope: scopes.join(' '),
|
||||
}),
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/auth',
|
||||
route(async (req, res) => {
|
||||
const { client, credentials, redirectUri, googleAuth } = await getClient()
|
||||
const code = req.query.code as string
|
||||
|
||||
const { tokens } = await client.getToken({
|
||||
code: code,
|
||||
redirect_uri: redirectUri.toString(),
|
||||
})
|
||||
|
||||
console.log({ tokens })
|
||||
|
||||
googleAuth.writeAuth({
|
||||
type: 'authorized_user',
|
||||
client_id: credentials.client_id,
|
||||
client_secret: credentials.client_secret,
|
||||
refresh_token: tokens.refresh_token as string,
|
||||
})
|
||||
|
||||
res.send('OK')
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { AppContext } from './context'
|
||||
|
||||
export const scrapper = (cb: (context: AppContext) => void) => cb
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { AppContext } from './context'
|
||||
|
||||
export type ServiceCallback<T> = () => Promise<T>
|
||||
|
||||
export const service =
|
||||
<T>(init: (ctx: AppContext) => ServiceCallback<T>) =>
|
||||
(context: AppContext) =>
|
||||
init(context)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import { google } from 'googleapis'
|
||||
import { DateTime } from 'luxon'
|
||||
import { service } from '../service'
|
||||
import { googleAuthService } from './googleAuth'
|
||||
|
||||
export type CalendarService = Awaited<
|
||||
ReturnType<ReturnType<typeof calendarService>>
|
||||
>
|
||||
|
||||
export const calendarService = service((ctx) => async () => {
|
||||
const googleAuth = await googleAuthService(ctx)()
|
||||
const auth = await googleAuth.getAuth()
|
||||
const calendar = google.calendar({ version: 'v3', auth })
|
||||
|
||||
return {
|
||||
calendars: async () => {
|
||||
const calendars = await calendar.calendarList.list()
|
||||
|
||||
return calendars.data.items
|
||||
},
|
||||
|
||||
events: async (calendars: string[]) => {
|
||||
const results = []
|
||||
const timeMin = DateTime.now().setZone(ctx.config.timeZone).startOf('day')
|
||||
const timeMax = DateTime.now().setZone(ctx.config.timeZone).endOf('day')
|
||||
|
||||
if (!timeMin.isValid) {
|
||||
throw new Error('Invalid time')
|
||||
}
|
||||
|
||||
if (!timeMax.isValid) {
|
||||
throw new Error('Invalid time')
|
||||
}
|
||||
|
||||
for (const calendarId of calendars) {
|
||||
const res = await calendar.events.list({
|
||||
calendarId,
|
||||
timeMin: timeMin.toISO(),
|
||||
timeMax: timeMax.toISO(),
|
||||
maxResults: 10,
|
||||
singleEvents: true,
|
||||
orderBy: 'startTime',
|
||||
})
|
||||
|
||||
if (res.data.items) {
|
||||
results.push(...res.data.items)
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
},
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { service } from '../service'
|
||||
|
||||
const API_URL =
|
||||
'https://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt'
|
||||
|
||||
export const exchangeRateService = service(({ fetch }) => async () => {
|
||||
const data = await fetch(API_URL, { cache: { ttl: 3600 * 12 } })
|
||||
|
||||
const lines = data
|
||||
.replace(/\r/g, '')
|
||||
.split('\n')
|
||||
.slice(2)
|
||||
.filter((v) => v.length > 0)
|
||||
|
||||
const rates = {} as Record<string, number>
|
||||
|
||||
lines.forEach((line) => {
|
||||
const [, , amount, code, rate] = line.split('|')
|
||||
|
||||
rates[code] = +rate.replace(',', '.') / +amount
|
||||
})
|
||||
|
||||
return rates
|
||||
})
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import { readFile, writeFile } from 'fs/promises'
|
||||
import { OAuth2Client } from 'google-auth-library'
|
||||
import { google } from 'googleapis'
|
||||
import { join } from 'path'
|
||||
import { service } from '../service'
|
||||
|
||||
export type GoogleAuthService = Awaited<
|
||||
ReturnType<ReturnType<typeof googleAuthService>>
|
||||
>
|
||||
|
||||
const CREDENTIALS_FILE = 'credentials.json'
|
||||
const TOKEN_FILE = 'token.json'
|
||||
const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
||||
|
||||
export type AuthData = {
|
||||
type: string
|
||||
client_id: string
|
||||
client_secret: string
|
||||
refresh_token: string
|
||||
}
|
||||
|
||||
export const googleAuthService = service(({ config }) => async () => {
|
||||
const credentialsPath = join(config.dataPath, CREDENTIALS_FILE)
|
||||
const tokenPath = join(config.dataPath, TOKEN_FILE)
|
||||
|
||||
return {
|
||||
writeAuth: async (data: AuthData) => {
|
||||
await writeFile(tokenPath, JSON.stringify(data))
|
||||
},
|
||||
|
||||
getAuth: async () => {
|
||||
try {
|
||||
const contentRaw = await readFile(tokenPath, 'utf-8')
|
||||
const content = JSON.parse(contentRaw)
|
||||
|
||||
return google.auth.fromJSON(content) as OAuth2Client
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
console.warn('No credentials found, please authenticate')
|
||||
}
|
||||
},
|
||||
|
||||
getCredentials: async () => {
|
||||
const content = await readFile(credentialsPath, 'utf-8')
|
||||
const parsed = JSON.parse(content)
|
||||
|
||||
return parsed.installed || parsed.web
|
||||
},
|
||||
|
||||
getScopes: () => SCOPES,
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
import { service } from '../service'
|
||||
import { ForecastData, TimeseriesData } from './weather/types'
|
||||
|
||||
type WeatherItem = DetailedWeatherItem | SummaryWeatherItem
|
||||
|
||||
interface SummaryWeatherItem {
|
||||
date: string
|
||||
temperature: { min: number; max: number }
|
||||
summary: null | string
|
||||
precipitationAmount: number
|
||||
}
|
||||
|
||||
interface DetailedWeatherItem {
|
||||
date: string
|
||||
|
||||
summary: null | string
|
||||
precipitationAmount: null | number
|
||||
|
||||
temperature: number
|
||||
|
||||
windDirection: number
|
||||
windSpeed: number
|
||||
|
||||
relativeHumidity: number
|
||||
|
||||
airPressure: number
|
||||
}
|
||||
|
||||
const API_URL = 'https://api.met.no/weatherapi'
|
||||
const API_USER_AGENT = 'KamenWatch 1.0 jan@zipek.cz'
|
||||
|
||||
const API_PARAMS = {
|
||||
lat: '50.070219',
|
||||
lon: '14.414034',
|
||||
}
|
||||
|
||||
const getSummaryItem = (date: string, item: TimeseriesData) => {
|
||||
if (item.next_6_hours) {
|
||||
return {
|
||||
date,
|
||||
temperature: {
|
||||
min: item.next_6_hours.details.air_temperature_min,
|
||||
max: item.next_6_hours.details.air_temperature_max,
|
||||
},
|
||||
summary: item.next_6_hours.summary.symbol_code,
|
||||
precipitationAmount: item.next_6_hours.details.precipitation_amount,
|
||||
} as SummaryWeatherItem
|
||||
}
|
||||
}
|
||||
|
||||
const getDetailedItem = (date: string, item: TimeseriesData) => {
|
||||
const detail = item.instant?.details
|
||||
|
||||
if (!detail) {
|
||||
return
|
||||
}
|
||||
|
||||
const result: DetailedWeatherItem = {
|
||||
date,
|
||||
temperature: detail.air_temperature,
|
||||
airPressure: detail.air_pressure_at_sea_level,
|
||||
relativeHumidity: detail.relative_humidity,
|
||||
windDirection: detail.wind_from_direction,
|
||||
windSpeed: detail.wind_speed,
|
||||
precipitationAmount: null,
|
||||
summary: null,
|
||||
}
|
||||
|
||||
if (item.next_1_hours) {
|
||||
result.summary = item.next_1_hours.summary.symbol_code
|
||||
result.precipitationAmount = item.next_1_hours.details.precipitation_amount
|
||||
} else if (item.next_6_hours) {
|
||||
result.summary = item.next_6_hours.summary.symbol_code
|
||||
} else if (item.next_12_hours) {
|
||||
result.summary = item.next_12_hours.summary.symbol_code
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export const weatherService = service(({ fetch }) => {
|
||||
return async () => {
|
||||
const forecast: ForecastData = JSON.parse(
|
||||
await fetch(
|
||||
`${API_URL}/locationforecast/2.0/complete?lat=${API_PARAMS.lat}&lon=${API_PARAMS.lon}`,
|
||||
{
|
||||
headers: {
|
||||
'User-agent': API_USER_AGENT,
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
const result = {
|
||||
now: null as WeatherItem | null,
|
||||
hours: {} as Record<number, WeatherItem>,
|
||||
days: {} as Record<number, WeatherItem>,
|
||||
}
|
||||
|
||||
let recordedHours = 0
|
||||
const nowDays = Math.floor(Date.now() / 1000 / 3600 / 24)
|
||||
const nowHours = Math.floor(Date.now() / 1000 / 3600)
|
||||
|
||||
forecast.properties.timeseries.forEach((item, index) => {
|
||||
const date = new Date(item['time'])
|
||||
const converted = getDetailedItem(item.time, item.data)
|
||||
|
||||
if (!converted) {
|
||||
return
|
||||
}
|
||||
|
||||
if (index === 0) {
|
||||
result.now = converted
|
||||
}
|
||||
|
||||
if (date.getHours() === 14) {
|
||||
const dayData = getSummaryItem(item.time, item.data)
|
||||
|
||||
if (dayData) {
|
||||
const daysDiff =
|
||||
Math.floor(date.getTime() / 1000 / 3600 / 24) - nowDays
|
||||
|
||||
result.days[daysDiff] = dayData
|
||||
}
|
||||
}
|
||||
|
||||
if (recordedHours < 23) {
|
||||
const hoursDiff = Math.floor(date.getTime() / 1000 / 3600) - nowHours
|
||||
|
||||
result.hours[hoursDiff] = converted
|
||||
recordedHours += 1
|
||||
}
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
export interface Geometry {
|
||||
type: string
|
||||
coordinates: number[]
|
||||
}
|
||||
|
||||
export interface Units {
|
||||
air_pressure_at_sea_level: string
|
||||
air_temperature: string
|
||||
air_temperature_max: string
|
||||
air_temperature_min: string
|
||||
cloud_area_fraction: string
|
||||
cloud_area_fraction_high: string
|
||||
cloud_area_fraction_low: string
|
||||
cloud_area_fraction_medium: string
|
||||
dew_point_temperature: string
|
||||
fog_area_fraction: string
|
||||
precipitation_amount: string
|
||||
relative_humidity: string
|
||||
ultraviolet_index_clear_sky: string
|
||||
wind_from_direction: string
|
||||
wind_speed: string
|
||||
}
|
||||
|
||||
export interface Meta {
|
||||
updated_at: Date
|
||||
units: Units
|
||||
}
|
||||
|
||||
export interface Details {
|
||||
air_pressure_at_sea_level: number
|
||||
air_temperature: number
|
||||
cloud_area_fraction: number
|
||||
cloud_area_fraction_high: number
|
||||
cloud_area_fraction_low: number
|
||||
cloud_area_fraction_medium: number
|
||||
dew_point_temperature: number
|
||||
fog_area_fraction: number
|
||||
relative_humidity: number
|
||||
ultraviolet_index_clear_sky: number
|
||||
wind_from_direction: number
|
||||
wind_speed: number
|
||||
}
|
||||
|
||||
export interface InstantData {
|
||||
details: Details
|
||||
}
|
||||
|
||||
export interface Summary {
|
||||
symbol_code: string
|
||||
}
|
||||
|
||||
export interface Next12Hours {
|
||||
summary: Summary
|
||||
}
|
||||
|
||||
export interface Summary2 {
|
||||
symbol_code: string
|
||||
}
|
||||
|
||||
export interface Details2 {
|
||||
precipitation_amount: number
|
||||
}
|
||||
|
||||
export interface Next1Hours {
|
||||
summary: Summary2
|
||||
details: Details2
|
||||
}
|
||||
|
||||
export interface Summary3 {
|
||||
symbol_code: string
|
||||
}
|
||||
|
||||
export interface Details3 {
|
||||
air_temperature_max: number
|
||||
air_temperature_min: number
|
||||
precipitation_amount: number
|
||||
}
|
||||
|
||||
export interface Next6Hours {
|
||||
summary: Summary3
|
||||
details: Details3
|
||||
}
|
||||
|
||||
export interface TimeseriesData {
|
||||
instant: InstantData
|
||||
next_12_hours?: Next12Hours
|
||||
next_1_hours?: Next1Hours
|
||||
next_6_hours?: Next6Hours
|
||||
}
|
||||
|
||||
export interface TimeseriesItem {
|
||||
time: string
|
||||
data: TimeseriesData
|
||||
}
|
||||
|
||||
export interface Properties {
|
||||
meta: Meta
|
||||
timeseries: TimeseriesItem[]
|
||||
}
|
||||
|
||||
export interface ForecastData {
|
||||
type: string
|
||||
geometry: Geometry
|
||||
properties: Properties
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import dotenv from 'dotenv'
|
||||
dotenv.config()
|
||||
|
||||
import express from 'express'
|
||||
import { loadConfig } from './app/config'
|
||||
import { createContext } from './app/context'
|
||||
import { corsMiddleware } from './app/middleware/cors'
|
||||
import { dowRoutes } from './app/routes/dow'
|
||||
import { googleAuthRoutes } from './app/routes/googleAuth'
|
||||
|
||||
async function main() {
|
||||
const config = await loadConfig()
|
||||
const context = await createContext(config)
|
||||
|
||||
const logger = context.createLogger('express')
|
||||
const app = express()
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
app.use(corsMiddleware())
|
||||
}
|
||||
|
||||
app.use(express.static(config.static))
|
||||
app.use(express.json())
|
||||
app.use('/api/dow', dowRoutes(context))
|
||||
app.use('/api/google', googleAuthRoutes(context))
|
||||
|
||||
app.listen(config.port, () => {
|
||||
logger.log('Listening on', config.port)
|
||||
})
|
||||
}
|
||||
|
||||
main().catch(console.error)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export const wait = (time: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, time))
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import crypto from 'crypto'
|
||||
import { promises as fs } from 'fs'
|
||||
import fetch, { RequestInit } from 'node-fetch'
|
||||
import { join } from 'path'
|
||||
|
||||
interface Options {
|
||||
path: string
|
||||
}
|
||||
|
||||
interface CachedRequestInit extends RequestInit {
|
||||
cache?: {
|
||||
ttl?: number
|
||||
}
|
||||
}
|
||||
|
||||
export const cachedFetch = (options: Options) => {
|
||||
return async (url: string, requestOptions?: CachedRequestInit) => {
|
||||
const { cache, ...fetchOptions } = requestOptions ?? {}
|
||||
const { ttl: cacheTTL = 3600 } = cache ?? {}
|
||||
|
||||
const cacheKey = crypto
|
||||
.createHash('md5')
|
||||
.update(JSON.stringify({ url, options: fetchOptions }))
|
||||
.digest('hex')
|
||||
|
||||
try {
|
||||
const cached = await fs.readFile(join(options.path, cacheKey))
|
||||
const data = JSON.parse(cached.toString())
|
||||
|
||||
if (data.created < Date.now() - cacheTTL * 1000) {
|
||||
throw new Error('Cache expired')
|
||||
}
|
||||
|
||||
return data.response as string
|
||||
} catch (e) {
|
||||
const response = await (await fetch(url, fetchOptions)).text()
|
||||
|
||||
fs.mkdir(options.path, { recursive: true }).then(() => {
|
||||
fs.writeFile(
|
||||
join(options.path, cacheKey),
|
||||
JSON.stringify({
|
||||
created: Date.now(),
|
||||
response,
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
return response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
export function shuffle<T>(a: T[]) {
|
||||
let j, x, i
|
||||
|
||||
for (i = a.length - 1; i > 0; i--) {
|
||||
j = Math.floor(Math.random() * (i + 1))
|
||||
x = a[i]
|
||||
a[i] = a[j]
|
||||
a[j] = x
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
type BusListener<Data> = (data: Data) => void
|
||||
|
||||
export class BusDispatcher<Data> {
|
||||
protected listeners = [] as BusListener<Data>[]
|
||||
|
||||
dispatch(data: Data) {
|
||||
this.listeners.forEach((l) => l(data))
|
||||
}
|
||||
|
||||
listen(listener: BusListener<Data>) {
|
||||
this.listeners.push(listener)
|
||||
|
||||
return listener
|
||||
}
|
||||
|
||||
stopListening(listener: BusListener<Data>) {
|
||||
const index = this.listeners.indexOf(listener)
|
||||
|
||||
if (index < 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.listeners.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
export class Logger {
|
||||
context = ''
|
||||
|
||||
constructor(context: string) {
|
||||
this.context = context
|
||||
}
|
||||
|
||||
log(...args: any[]) {
|
||||
console.log(new Date().toISOString(), `[${this.context}]`, ...args)
|
||||
}
|
||||
|
||||
error(...args: any[]) {
|
||||
console.error(new Date().toISOString(), `[${this.context}]`, ...args)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
display: block;
|
||||
margin: 1rem auto;
|
||||
background: #fff;
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/** @type {HTMLCanvasElement} */
|
||||
const $canvas = document.getElementById('canvas')
|
||||
|
||||
const TYPES = {
|
||||
TEXT: 0,
|
||||
LINE: 1,
|
||||
CIRCLE: 2,
|
||||
CIRCLE_FILL: 3,
|
||||
RECT: 4,
|
||||
RECT_FILL: 5,
|
||||
}
|
||||
|
||||
const ALIGN = {
|
||||
START: 0,
|
||||
CENTER: 1,
|
||||
END: 2,
|
||||
}
|
||||
|
||||
const FONTS = {
|
||||
0: '24px FreeSans',
|
||||
1: '48px FreeSans',
|
||||
2: 'bold 124px "Fira Code"',
|
||||
3: '18px FreeSans',
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ x: number; y: number; t: number; c?: number; va?: number; ha?: number; f?: number; x2?: number; y2?: number; w?: number; h?: number; r?: number }[]} data
|
||||
*/
|
||||
function render(data) {
|
||||
const ctx = $canvas.getContext('2d')
|
||||
|
||||
if (!ctx) {
|
||||
throw new Error('Canvas 2D context is not available')
|
||||
}
|
||||
|
||||
ctx.imageSmoothingEnabled = false
|
||||
ctx.clearRect(0, 0, $canvas.width * 2, $canvas.height * 2)
|
||||
ctx.textBaseline = 'alphabetic'
|
||||
ctx.fillStyle = '#222'
|
||||
ctx.strokeStyle = '#222'
|
||||
|
||||
for (const item of data) {
|
||||
switch (item.t) {
|
||||
case TYPES.TEXT: {
|
||||
const content = item.c
|
||||
const x = item.x
|
||||
const y = item.y
|
||||
const verticalAlign = item.va ?? 0
|
||||
const horizontalAlign = item.ha ?? 0
|
||||
const font = item.f ?? 0
|
||||
|
||||
ctx.font = FONTS[font]
|
||||
|
||||
const measured = ctx.measureText(content)
|
||||
|
||||
let xx = x
|
||||
let yy = y
|
||||
|
||||
switch (verticalAlign) {
|
||||
case ALIGN.START:
|
||||
yy = y + measured.actualBoundingBoxAscent
|
||||
break
|
||||
case ALIGN.CENTER:
|
||||
yy = y + measured.actualBoundingBoxAscent / 2
|
||||
break
|
||||
case ALIGN.END:
|
||||
yy = y
|
||||
break
|
||||
}
|
||||
|
||||
switch (horizontalAlign) {
|
||||
case ALIGN.START:
|
||||
xx = x
|
||||
break
|
||||
case ALIGN.CENTER:
|
||||
xx = x - measured.width / 2
|
||||
break
|
||||
case ALIGN.END:
|
||||
xx = x - measured.width
|
||||
break
|
||||
}
|
||||
|
||||
ctx.fillText(content, Math.round(xx), Math.round(yy))
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case TYPES.LINE: {
|
||||
const x = item.x
|
||||
const y = item.y
|
||||
const x2 = item.x2
|
||||
const y2 = item.y2
|
||||
|
||||
ctx.moveTo(x, y)
|
||||
ctx.lineTo(x2, y2)
|
||||
ctx.stroke()
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case TYPES.CIRCLE: {
|
||||
const x = item.x
|
||||
const y = item.y
|
||||
const radius = item.r
|
||||
|
||||
ctx.beginPath()
|
||||
ctx.arc(x, y, radius, 0, 2 * Math.PI)
|
||||
ctx.stroke()
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case TYPES.CIRCLE_FILL: {
|
||||
const x = item.x
|
||||
const y = item.y
|
||||
const radius = item.r
|
||||
|
||||
ctx.beginPath()
|
||||
ctx.arc(x, y, radius, 0, 2 * Math.PI)
|
||||
ctx.fill()
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case TYPES.RECT: {
|
||||
const x = item.x
|
||||
const y = item.y
|
||||
const w = item.x2
|
||||
const h = item.y2
|
||||
|
||||
ctx.strokeRect(x, y, w, h)
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case TYPES.RECT_FILL: {
|
||||
const x = item.x
|
||||
const y = item.y
|
||||
const w = item.x2
|
||||
const h = item.y2
|
||||
|
||||
ctx.fillRect(x, y, w, h)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const WIDTH = 648
|
||||
const HEIGHT = 480
|
||||
|
||||
const hours = new Date().getHours().toString().padStart(2, '0')
|
||||
const minutes = new Date().getMinutes().toString().padStart(2, '0')
|
||||
|
||||
setInterval(() => {
|
||||
fetch('/api/dow').then((r) => r.json().then((data) => render(data)))
|
||||
}, 1000)
|
||||
|
||||
render([
|
||||
{
|
||||
x: Math.round(WIDTH / 2),
|
||||
y: 20,
|
||||
t: TYPES.TEXT,
|
||||
c: `...`,
|
||||
va: ALIGN.START,
|
||||
ha: ALIGN.CENTER,
|
||||
f: 2,
|
||||
},
|
||||
])
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>DOW Debug</title>
|
||||
<link href="app.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<noscript><strong>Javascript is required</strong></noscript>
|
||||
|
||||
<canvas id="canvas" width="648" height="480"></canvas>
|
||||
|
||||
<script src="dow-emulator.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
|
||||
/* Advanced Options */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue