mirror of https://github.com/meshcore-dev/MeshCore
21 changed files with 467 additions and 125 deletions
@ -0,0 +1,46 @@ |
|||||
|
#include <Arduino.h> |
||||
|
|
||||
|
#include "esp_log.h" |
||||
|
#include "uiDefines.h" |
||||
|
#include "uiVars.h" |
||||
|
|
||||
|
void clock_task(void *pvParameters) { |
||||
|
|
||||
|
vTaskSuspend(NULL); |
||||
|
|
||||
|
ESP_LOGI("Clock manager: Task running on core %d", xPortGetCoreID()); |
||||
|
|
||||
|
bool ntpResult = false; |
||||
|
|
||||
|
uiManager->clearDateTime(); |
||||
|
|
||||
|
while (!ntpResult) { |
||||
|
|
||||
|
myWiFi->ensureConnection(); |
||||
|
if (myWiFi->isConnected()) { |
||||
|
ntpResult = myClock->setTimeFromNTP(); |
||||
|
|
||||
|
if (!ntpResult) { |
||||
|
vTaskDelay(DELAY_NTP_TASK / portTICK_PERIOD_MS); |
||||
|
} else { |
||||
|
uiManager->updateInfo("", COLOR_WHITE); |
||||
|
} |
||||
|
} else { |
||||
|
ESP_LOGE("No internet connection"); |
||||
|
vTaskDelay(DELAY_WIFI_RECONNECT_TASK / portTICK_PERIOD_MS); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#ifdef USE_OPEN_WEATHER |
||||
|
vTaskResume(t_core1_openWeather); |
||||
|
#endif |
||||
|
|
||||
|
while (1) { |
||||
|
uiManager->updateDateTime( |
||||
|
myClock->getTimeStruct() |
||||
|
); |
||||
|
uiManager->updateValues(); |
||||
|
vTaskDelay(DELAY_CLOCK_TASK / portTICK_PERIOD_MS); |
||||
|
} |
||||
|
} |
||||
@ -1,20 +1,17 @@ |
|||||
#include <Arduino.h> |
#include <Arduino.h> |
||||
|
|
||||
#include "defines.h" |
#include "esp_log.h" |
||||
//#include <MyDebug.h>
|
#include "uiDefines.h" |
||||
#include "vars.h" |
#include "uiVars.h" |
||||
|
|
||||
void lvgl_task(void *pvParameters) { |
void lvgl_task(void *pvParameters) { |
||||
|
|
||||
vTaskSuspend(NULL); |
vTaskSuspend(NULL); |
||||
|
|
||||
Serial.printf("UI manager: Task running on core %d", xPortGetCoreID()); |
ESP_LOGI("UI manager: Task running on core %d", xPortGetCoreID()); |
||||
Serial.println(); |
|
||||
|
|
||||
while (1) { |
while (1) { |
||||
lv_timer_handler(); |
lv_timer_handler(); |
||||
vTaskDelay(DELAY_LVGL_TASK / portTICK_PERIOD_MS); |
vTaskDelay(DELAY_LVGL_TASK / portTICK_PERIOD_MS); |
||||
} |
} |
||||
// myDebug->println(DEBUG_LEVEL_INFO, "Terminating UI manager");
|
|
||||
// vTaskDelete(NULL);
|
|
||||
} |
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
#include <Arduino.h> |
||||
|
|
||||
|
#include "esp_log.h" |
||||
|
#include "uiDefines.h" |
||||
|
|
||||
|
#ifdef USE_OPEN_WEATHER |
||||
|
#include "uiVars.h" |
||||
|
|
||||
|
void openWeather_task(void *pvParameters) { |
||||
|
|
||||
|
vTaskSuspend(NULL); |
||||
|
|
||||
|
ESP_LOGI("openWeather manager: Task running on core %d", xPortGetCoreID()); |
||||
|
|
||||
|
int errors = 0; |
||||
|
|
||||
|
for (;;) { |
||||
|
myWiFi->ensureConnection(); |
||||
|
if (myWiFi->isConnected()) { |
||||
|
if (openWeather->fetchData()) { |
||||
|
vTaskDelay(DELAY_OPEN_WEATHER_TASK / portTICK_PERIOD_MS); |
||||
|
} else { |
||||
|
vTaskDelay(DELAY_OPEN_WEATHER_SHORT_TASK / portTICK_PERIOD_MS); |
||||
|
} |
||||
|
} else { |
||||
|
ESP_LOGE("No internet connection"); |
||||
|
vTaskDelay(DELAY_WIFI_RECONNECT_TASK / portTICK_PERIOD_MS); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,60 @@ |
|||||
|
#ifndef OPEN_WEATHER_h |
||||
|
#define OPEN_WEATHER_h |
||||
|
|
||||
|
#include <Arduino.h> |
||||
|
#include "uiDefines.h" |
||||
|
|
||||
|
#ifdef USE_OPEN_WEATHER |
||||
|
|
||||
|
#include <HttpClient.h> |
||||
|
#include <ArduinoJson.h> |
||||
|
#include <PNGdec.h> |
||||
|
#include "user_setup.h" |
||||
|
|
||||
|
// Weather Image
|
||||
|
#define IMG_WIDTH 200 |
||||
|
#define IMG_HEIGHT 200 |
||||
|
#define PNG_PIXELS_PER_LINE 2048 |
||||
|
|
||||
|
class OpenWeather { |
||||
|
private: |
||||
|
// functions
|
||||
|
static int renderPNGToBuffer(PNGDRAW *pDraw); // static callback
|
||||
|
int renderPNGToBufferImpl(PNGDRAW *pDraw); // normal method
|
||||
|
void downloadImageToMemory(const char *url); |
||||
|
|
||||
|
// User setup
|
||||
|
String town = USER_WeatherTown; |
||||
|
String myAPI = USER_WeatherAPI; |
||||
|
String units = USER_WeatherUnits; |
||||
|
|
||||
|
// vars
|
||||
|
PNG png; |
||||
|
uint8_t *imageBuffer = nullptr; |
||||
|
uint16_t *rgb565_buffer = nullptr; |
||||
|
int bufferSize; |
||||
|
lv_img_dsc_t img_dsc; |
||||
|
|
||||
|
String openWeatherServer; |
||||
|
s_openWeatherData data; |
||||
|
String oldIconUrl; |
||||
|
|
||||
|
SemaphoreHandle_t semaphoreData; |
||||
|
bool dataUpdated; |
||||
|
String lastUpdate; |
||||
|
HTTPClient http; |
||||
|
char* tmp_buf; |
||||
|
public: |
||||
|
OpenWeather(); |
||||
|
// functions
|
||||
|
void init(); |
||||
|
bool fetchData(); |
||||
|
bool isDataUpdated(); |
||||
|
void setDataUpdated(bool updated); |
||||
|
s_openWeatherData getData(); |
||||
|
bool decodePngToRgb565(uint8_t *png_data, int png_size); |
||||
|
}; |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
#endif |
||||
@ -1,24 +0,0 @@ |
|||||
#ifndef structs_h |
|
||||
#define structs_h |
|
||||
|
|
||||
#include <Arduino.h> |
|
||||
#include "../lvgl/lvgl.h" |
|
||||
|
|
||||
typedef struct s_espNow { |
|
||||
uint8_t type; |
|
||||
uint8_t id; |
|
||||
int16_t value; |
|
||||
} s_espNow; |
|
||||
|
|
||||
typedef struct s_espNowButtons { |
|
||||
bool enabled; |
|
||||
bool needsUpdate; |
|
||||
int16_t state; |
|
||||
lv_obj_t *obj; |
|
||||
uint32_t colorOn; |
|
||||
uint32_t colorOff; |
|
||||
lv_obj_t *uiLabel; |
|
||||
char *uiLabelText; |
|
||||
} s_espNowButtons; |
|
||||
|
|
||||
#endif |
|
||||
@ -1,10 +1,19 @@ |
|||||
#ifndef DEFINES_h |
#ifndef DEFINES_h |
||||
#define DEFINES_h |
#define DEFINES_h |
||||
|
|
||||
#include "configuration.h" |
#include "uiConfiguration.h" |
||||
|
|
||||
#define BUTTONS_ON_SCREEN 7 |
#define BUTTONS_ON_SCREEN 7 |
||||
|
|
||||
#define DELAY_LVGL_TASK 10 |
#define DELAY_LVGL_TASK 10 |
||||
|
#define DELAY_MAIN_TASK 500 |
||||
|
#define DELAY_CLOCK_TASK 1000 |
||||
|
#define DELAY_NTP_TASK 30000 |
||||
|
#define DELAY_WIFI_RECONNECT_TASK 5000 |
||||
|
// every 5 minutes on success
|
||||
|
#define DELAY_OPEN_WEATHER_TASK 300000 |
||||
|
// every 1 minute on failure
|
||||
|
#define DELAY_OPEN_WEATHER_SHORT_TASK 60000 |
||||
|
|
||||
#define STATE_OFF HIGH |
#define STATE_OFF HIGH |
||||
#define STATE_ON LOW |
#define STATE_ON LOW |
||||
@ -0,0 +1,28 @@ |
|||||
|
#ifndef VARS_h |
||||
|
#define VARS_h |
||||
|
|
||||
|
#include <Arduino.h> |
||||
|
#include "openWeather.h" |
||||
|
#include "lvgl.h" |
||||
|
|
||||
|
extern void createTasks(); |
||||
|
|
||||
|
extern TaskHandle_t t_core1_tft; |
||||
|
extern TaskHandle_t t_core0_lvgl; |
||||
|
extern TaskHandle_t t_core1_clock; |
||||
|
|
||||
|
extern SemaphoreHandle_t semaphoreData; |
||||
|
|
||||
|
extern UIManager *uiManager; |
||||
|
extern MyClock *myClock; |
||||
|
extern MyWiFi *myWiFi; |
||||
|
|
||||
|
#ifdef USE_OPEN_WEATHER |
||||
|
extern OpenWeather *openWeather; |
||||
|
extern TaskHandle_t t_core1_openWeather; |
||||
|
#endif |
||||
|
#ifdef USE_MAIN_TAB_VIEW |
||||
|
extern lv_obj_t * ui_MainTabView; |
||||
|
#endif |
||||
|
|
||||
|
#endif |
||||
@ -1,21 +0,0 @@ |
|||||
#ifndef VARS_h |
|
||||
#define VARS_h |
|
||||
|
|
||||
#include <Arduino.h> |
|
||||
|
|
||||
#include "structs.h" |
|
||||
|
|
||||
#ifdef USE_MULTI_THREAD |
|
||||
extern SemaphoreHandle_t semaphoreData; |
|
||||
|
|
||||
// Tasks
|
|
||||
#ifdef DISPLAY_AT_CORE1 |
|
||||
extern TaskHandle_t t_core1_tft; |
|
||||
#endif |
|
||||
|
|
||||
#ifdef USE_MAIN_TAB_VIEW |
|
||||
extern lv_obj_t * ui_MainTabView; |
|
||||
#endif |
|
||||
#endif |
|
||||
|
|
||||
#endif |
|
||||
@ -0,0 +1,51 @@ |
|||||
|
#ifndef WIFI_h |
||||
|
#define WIFI_h |
||||
|
|
||||
|
#include <Arduino.h> |
||||
|
#include <WiFi.h> |
||||
|
#include "esp_wifi.h" |
||||
|
#include <esp_now.h> |
||||
|
|
||||
|
typedef struct s_espNow { |
||||
|
uint8_t type; |
||||
|
uint8_t id; |
||||
|
int16_t value; |
||||
|
} s_espNow; |
||||
|
|
||||
|
class MyWiFi { |
||||
|
private: |
||||
|
// functions
|
||||
|
void notInitialized(); |
||||
|
|
||||
|
using OnDataSentCallback = void (*)(const uint8_t *mac_addr, esp_now_send_status_t status); |
||||
|
using OnDataRecvCallback = void (*)(const uint8_t *mac_addr, const uint8_t *incomingData, int len); |
||||
|
|
||||
|
//Vars
|
||||
|
uint8_t WiFiChannel; |
||||
|
bool initDone; |
||||
|
|
||||
|
esp_now_peer_info_t peerInfo; |
||||
|
s_espNow espNowPacket; |
||||
|
|
||||
|
SemaphoreHandle_t semaphoreData; |
||||
|
|
||||
|
char *tmp_buf; |
||||
|
char *savedSSID; |
||||
|
char *savedPassword; |
||||
|
public: |
||||
|
MyWiFi(); |
||||
|
// functions
|
||||
|
void init(wifi_mode_t mode, char *ssid, char *password); |
||||
|
void stop(); |
||||
|
bool initESPNow(int channel, bool encrypted, OnDataSentCallback onSent, OnDataRecvCallback onRecv); |
||||
|
void addEspNowPeer(uint8_t address[6]); |
||||
|
esp_err_t sendEspNow(const uint8_t *peer_addr, uint8_t type, uint8_t id, uint16_t value); |
||||
|
void connect(); |
||||
|
void disconnect(); |
||||
|
void ensureConnection(); |
||||
|
bool isConnected(); |
||||
|
wl_status_t getStatus(); |
||||
|
uint8_t getChannel(); |
||||
|
}; |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,191 @@ |
|||||
|
#include <Arduino.h> |
||||
|
#include <WiFi.h> |
||||
|
|
||||
|
#include "esp_log.h" |
||||
|
#include "MyWiFi.h" |
||||
|
|
||||
|
MyWiFi::MyWiFi() { |
||||
|
ESP_LOGD("[WiFi]"); |
||||
|
|
||||
|
initDone = false; |
||||
|
tmp_buf = (char*)malloc(128); |
||||
|
|
||||
|
semaphoreData = xSemaphoreCreateMutex(); |
||||
|
xSemaphoreGive(semaphoreData); |
||||
|
} |
||||
|
|
||||
|
void MyWiFi::init(wifi_mode_t mode, char *ssid, char *password) { |
||||
|
ESP_LOGD("Initializing WiFi"); |
||||
|
|
||||
|
savedSSID = (char*)malloc(strlen(ssid) + 1); |
||||
|
strcpy(savedSSID, ssid); |
||||
|
|
||||
|
savedPassword = (char*)malloc(strlen(password) + 1); |
||||
|
strcpy(savedPassword, password); |
||||
|
|
||||
|
ESP_LOGD("SSID: '%s', password:'%s'", savedSSID, savedPassword); |
||||
|
|
||||
|
WiFi.mode(mode); |
||||
|
ESP_LOGI("MAC Address: %s", WiFi.macAddress()); |
||||
|
initDone = true; |
||||
|
} |
||||
|
|
||||
|
void MyWiFi::stop() { |
||||
|
if (!initDone) { |
||||
|
notInitialized(); |
||||
|
return; |
||||
|
} |
||||
|
disconnect(); |
||||
|
initDone = false; |
||||
|
free(savedSSID); |
||||
|
free(savedPassword); |
||||
|
} |
||||
|
|
||||
|
void MyWiFi::notInitialized() { |
||||
|
ESP_LOGE("WiFi not initialized"); |
||||
|
} |
||||
|
|
||||
|
void MyWiFi::connect() { |
||||
|
ESP_LOGI("WiFi disconnected, reconnecting..."); |
||||
|
|
||||
|
if (!initDone) { |
||||
|
notInitialized(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
xSemaphoreTake(semaphoreData, portMAX_DELAY); |
||||
|
WiFi.disconnect(); |
||||
|
WiFi.begin(savedSSID, savedPassword); |
||||
|
unsigned long startAttemptTime = millis(); |
||||
|
|
||||
|
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) { |
||||
|
delay(500); |
||||
|
} |
||||
|
|
||||
|
wifi_ap_record_t ap_info; |
||||
|
if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { |
||||
|
ESP_LOGD("WiFi connected"); |
||||
|
WiFiChannel = ap_info.primary; |
||||
|
ESP_LOGD("WiFi channel: %d", WiFiChannel); |
||||
|
} else { |
||||
|
WiFiChannel = 0; |
||||
|
ESP_LOGD("Not connected to any WiFi network."); |
||||
|
} |
||||
|
xSemaphoreGive(semaphoreData); |
||||
|
} |
||||
|
|
||||
|
void MyWiFi::ensureConnection() { |
||||
|
if (!initDone) { |
||||
|
notInitialized(); |
||||
|
return; |
||||
|
} |
||||
|
if (!isConnected()) { |
||||
|
connect(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool MyWiFi::isConnected() { |
||||
|
if (!initDone) { |
||||
|
notInitialized(); |
||||
|
return false; |
||||
|
} |
||||
|
bool ret; |
||||
|
xSemaphoreTake(semaphoreData, portMAX_DELAY); |
||||
|
ret = WiFi.status() == WL_CONNECTED; |
||||
|
xSemaphoreGive(semaphoreData); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
void MyWiFi::disconnect() { |
||||
|
ESP_LOGD("WiFi disconnecting..."); |
||||
|
if (!initDone) { |
||||
|
notInitialized(); |
||||
|
return; |
||||
|
} |
||||
|
xSemaphoreTake(semaphoreData, portMAX_DELAY); |
||||
|
WiFi.disconnect(); |
||||
|
xSemaphoreGive(semaphoreData); |
||||
|
} |
||||
|
|
||||
|
wl_status_t MyWiFi::getStatus() { |
||||
|
if (!initDone) { |
||||
|
notInitialized(); |
||||
|
return WL_DISCONNECTED; |
||||
|
} |
||||
|
wl_status_t ret; |
||||
|
xSemaphoreTake(semaphoreData, portMAX_DELAY); |
||||
|
ret = WiFi.status(); |
||||
|
xSemaphoreGive(semaphoreData); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
uint8_t MyWiFi::getChannel() { |
||||
|
if (!initDone) { |
||||
|
notInitialized(); |
||||
|
return 0; |
||||
|
} |
||||
|
uint8_t ret; |
||||
|
xSemaphoreTake(semaphoreData, portMAX_DELAY); |
||||
|
ret = WiFiChannel; |
||||
|
xSemaphoreGive(semaphoreData); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
////////////
|
||||
|
// ESPNow //
|
||||
|
////////////
|
||||
|
void MyWiFi::addEspNowPeer(uint8_t address[6]) { |
||||
|
ESP_LOGD("Adding ESPNow peer"); |
||||
|
memcpy(peerInfo.peer_addr, address, 6); |
||||
|
if (esp_now_add_peer(&peerInfo) != ESP_OK) { |
||||
|
ESP_LOGE("Failed to add peer"); |
||||
|
} else { |
||||
|
ESP_LOGD("ESPNow peer added"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool MyWiFi::initESPNow(int channel, bool encrypted, OnDataSentCallback onSent, OnDataRecvCallback onRecv) { |
||||
|
|
||||
|
ESP_LOGI("Initializing ESP-NOW..."); |
||||
|
|
||||
|
if (onRecv == nullptr) { |
||||
|
ESP_LOGE("register_recv_cb is null"); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
WiFi.mode(WIFI_STA); |
||||
|
|
||||
|
ESP_LOGI("MAC Address: %s", WiFi.macAddress()); |
||||
|
|
||||
|
// Init ESP-NOW
|
||||
|
if (esp_now_init() != ESP_OK) { |
||||
|
ESP_LOGE("Error initializing ESP-NOW"); |
||||
|
return false; |
||||
|
} else { |
||||
|
ESP_LOGD("Initializing ESP-NOW ok"); |
||||
|
} |
||||
|
|
||||
|
// preper register peer
|
||||
|
peerInfo.channel = channel; |
||||
|
peerInfo.encrypt = encrypted; |
||||
|
peerInfo.ifidx = WIFI_IF_STA; |
||||
|
|
||||
|
// Once ESPNow is successfully Init, we will register for Send CB to
|
||||
|
// get the status of Trasnmitted packet
|
||||
|
if (onSent != nullptr) { |
||||
|
esp_now_register_send_cb(onSent); |
||||
|
} |
||||
|
|
||||
|
// Register for a callback function that will be called when data is received
|
||||
|
esp_now_register_recv_cb(onRecv); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
esp_err_t MyWiFi::sendEspNow(const uint8_t *peer_addr, uint8_t type, uint8_t id, uint16_t value) { |
||||
|
espNowPacket.type = type; |
||||
|
espNowPacket.id = id; |
||||
|
espNowPacket.value = value; |
||||
|
return esp_now_send(peer_addr, (uint8_t *) &espNowPacket, sizeof(s_espNow)); |
||||
|
} |
||||
|
|
||||
@ -23,19 +23,19 @@ build_flags = |
|||||
${Elecrow_ESPNOW.build_flags} |
${Elecrow_ESPNOW.build_flags} |
||||
-I./include |
-I./include |
||||
-D${PIOENV} |
-D${PIOENV} |
||||
-D USE_MODULE_SWITCHES |
-D CORE_DEBUG_LEVEL=4 ; 0: None, 1: Error, 2: Warn, 3: Info, 4: Debug, 5: Verbose |
||||
-D CORE_DEBUG_LEVEL=2 |
|
||||
-D LV_CONF_PATH=lv_conf.h |
-D LV_CONF_PATH=lv_conf.h |
||||
-D ELECROW_DISPLAY_50 |
-D ELECROW_DISPLAY_50 |
||||
-D USE_MODULE_SWITCHES |
|
||||
-D CLIENT_WITHOUT_LORA |
-D CLIENT_WITHOUT_LORA |
||||
|
-D USE_OPEN_WEATHER |
||||
-D ADVERT_NAME='"Elecrow Terminal"' |
-D ADVERT_NAME='"Elecrow Terminal"' |
||||
-D MAX_CONTACTS=350 |
-D MAX_CONTACTS=350 |
||||
-D MAX_GROUP_CHANNELS=8 |
-D MAX_GROUP_CHANNELS=8 |
||||
-D MESH_DEBUG=1 |
-D MESH_DEBUG=1 |
||||
-D BOARD_HAS_PSRAM=1 |
-D BOARD_HAS_PSRAM=1 |
||||
build_src_filter = ${Elecrow_ESPNOW.build_src_filter} |
build_src_filter = ${Elecrow_ESPNOW.build_src_filter} |
||||
+<../examples/simple_secure_chat/*.cpp> |
+<../examples/simple_secure_chat_ui/*.cpp> |
||||
|
+<helpers/wifi/myWiFi.cpp> |
||||
+<fonts/*.c> |
+<fonts/*.c> |
||||
+<UI/*.c> |
+<UI/*.c> |
||||
lib_deps = |
lib_deps = |
||||
@ -43,5 +43,6 @@ lib_deps = |
|||||
adafruit/Adafruit SSD1306 @ ^2.5.15 |
adafruit/Adafruit SSD1306 @ ^2.5.15 |
||||
lvgl/[email protected] |
lvgl/[email protected] |
||||
lovyan03/LovyanGFX@^1.1.16 |
lovyan03/LovyanGFX@^1.1.16 |
||||
|
bitbank2/PNGdec@^1.1.6 |
||||
tamctec/TAMC_GT911@^1.0.2 |
tamctec/TAMC_GT911@^1.0.2 |
||||
densaugeo/base64 @ ~1.4.0 |
densaugeo/base64 @ ~1.4.0 |
||||
|
|||||
Loading…
Reference in new issue