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 "defines.h" |
|||
//#include <MyDebug.h>
|
|||
#include "vars.h" |
|||
#include "esp_log.h" |
|||
#include "uiDefines.h" |
|||
#include "uiVars.h" |
|||
|
|||
void lvgl_task(void *pvParameters) { |
|||
|
|||
vTaskSuspend(NULL); |
|||
|
|||
Serial.printf("UI manager: Task running on core %d", xPortGetCoreID()); |
|||
Serial.println(); |
|||
ESP_LOGI("UI manager: Task running on core %d", xPortGetCoreID()); |
|||
|
|||
while (1) { |
|||
lv_timer_handler(); |
|||
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 |
|||
#define DEFINES_h |
|||
|
|||
#include "configuration.h" |
|||
#include "uiConfiguration.h" |
|||
|
|||
#define BUTTONS_ON_SCREEN 7 |
|||
|
|||
#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_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} |
|||
-I./include |
|||
-D${PIOENV} |
|||
-D USE_MODULE_SWITCHES |
|||
-D CORE_DEBUG_LEVEL=2 |
|||
-D CORE_DEBUG_LEVEL=4 ; 0: None, 1: Error, 2: Warn, 3: Info, 4: Debug, 5: Verbose |
|||
-D LV_CONF_PATH=lv_conf.h |
|||
-D ELECROW_DISPLAY_50 |
|||
-D USE_MODULE_SWITCHES |
|||
-D CLIENT_WITHOUT_LORA |
|||
-D USE_OPEN_WEATHER |
|||
-D ADVERT_NAME='"Elecrow Terminal"' |
|||
-D MAX_CONTACTS=350 |
|||
-D MAX_GROUP_CHANNELS=8 |
|||
-D MESH_DEBUG=1 |
|||
-D BOARD_HAS_PSRAM=1 |
|||
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> |
|||
+<UI/*.c> |
|||
lib_deps = |
|||
@ -43,5 +43,6 @@ lib_deps = |
|||
adafruit/Adafruit SSD1306 @ ^2.5.15 |
|||
lvgl/[email protected] |
|||
lovyan03/LovyanGFX@^1.1.16 |
|||
bitbank2/PNGdec@^1.1.6 |
|||
tamctec/TAMC_GT911@^1.0.2 |
|||
densaugeo/base64 @ ~1.4.0 |
|||
|
|||
Loading…
Reference in new issue