Browse Source

Update main.cpp

pull/2568/head
Christos Themelis 5 months ago
parent
commit
95fb9d6882
  1. 418
      examples/simple_secure_chat/main.cpp

418
examples/simple_secure_chat/main.cpp

@ -42,27 +42,6 @@
#include <helpers/BaseChatMesh.h>
#include <lvgl.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include "UI/ui.h"
#include "../src/fonts/fonts.h"
#include "../lvgl/lvgl.h"
#include "../include/externals.h"
#include "../include/lgfx.h"
#include "../include/defines.h"
#include "../include/structs.h"
#include "../include/uiManager.h"
#ifdef USE_MULTI_THREAD
#include "../include/tasks.h"
#endif
#include "touch.h"
#define SEND_TIMEOUT_BASE_MILLIS 500
#define FLOOD_SEND_TIMEOUT_FACTOR 16.0f
#define DIRECT_SEND_PERHOP_FACTOR 6.0f
@ -70,354 +49,6 @@
#define PUBLIC_GROUP_PSK "izOH6cXN6mrJ5e26oRXNcg=="
#define MAX_CHAT_MESSAGES 50
static lv_obj_t *chat_items[MAX_CHAT_MESSAGES];
static int chat_count = 0;
static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t disp_draw_buf[800 * 480 / 10];
//static lv_color_t disp_draw_buf;
static lv_disp_drv_t disp_drv;
s_espNow espNowPacket;
UIManager *uiManager;
#ifdef USE_MULTI_THREAD
// Tasks
#ifdef DISPLAY_AT_CORE1
TaskHandle_t t_core1_tft;
#endif
// Semaphores
SemaphoreHandle_t semaphoreData;
#endif
TwoWire I2Cone = TwoWire(0);
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &I2Cone, OLED_RESET);
SPIClass& spi = SPI;
uint16_t touchCalibration_x0 = 300, touchCalibration_x1 = 3600, touchCalibration_y0 = 300, touchCalibration_y1 = 3600;
uint8_t touchCalibration_rotate = 1, touchCalibration_invert_x = 2, touchCalibration_invert_y = 0;
void format_time(uint32_t ts, char *buf, size_t len)
{
time_t t = ts;
struct tm *tm_info = localtime(&t);
strftime(buf, len, "%H:%M:%S", tm_info);
}
void parse_group_message(const char *input,
char *sender_out, size_t sender_len,
char *msg_out, size_t msg_len)
{
const char *sep = strchr(input, ':');
if (!sep) {
strncpy(sender_out, "Unknown", sender_len);
strncpy(msg_out, input, msg_len);
return;
}
size_t name_len = sep - input;
if (name_len >= sender_len) name_len = sender_len - 1;
strncpy(sender_out, input, name_len);
sender_out[name_len] = 0;
// Skip ": "
const char *msg_start = sep + 1;
if (*msg_start == ' ') msg_start++;
strncpy(msg_out, msg_start, msg_len);
}
void add_chat_bubble(lv_obj_t *list,
const char *time_str,
const char *sender,
const char *msg,
bool is_self)
{
// Remove oldest
if (chat_count >= MAX_CHAT_MESSAGES) {
lv_obj_del(chat_items[0]);
memmove(&chat_items[0], &chat_items[1], sizeof(lv_obj_t*) * (MAX_CHAT_MESSAGES - 1));
chat_count--;
}
// Row container (align bubble left/right)
lv_obj_t *row = lv_obj_create(list);
lv_obj_set_width(row, lv_pct(100));
lv_obj_set_height(row, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(row, 0, 0);
lv_obj_set_style_pad_all(row, 0, 0);
lv_obj_set_style_border_width(row, 0, 0);
lv_obj_set_style_outline_width(row, 0, 0);
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row,
is_self ? LV_FLEX_ALIGN_END : LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START);
// Bubble container (COLUMN)
lv_obj_t *bubble = lv_obj_create(row);
lv_obj_set_width(bubble, lv_pct(85));
lv_obj_set_height(bubble, LV_SIZE_CONTENT);
lv_obj_set_style_radius(bubble, 12, 0);
lv_obj_set_style_pad_all(bubble, 10, 0);
lv_obj_set_style_bg_color(bubble,
is_self ? lv_color_hex(0x1E88E5) : lv_color_hex(0x2C2C2C), 0);
// IMPORTANT: vertical layout inside bubble
lv_obj_set_flex_flow(bubble, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(bubble,
LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START);
// Header row (sender + time)
lv_obj_t *hdr = lv_obj_create(bubble);
lv_obj_set_width(hdr, lv_pct(100));
lv_obj_set_height(hdr, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(hdr, 0, 0);
lv_obj_set_style_border_width(hdr, 0, 0);
lv_obj_set_style_pad_all(hdr, 0, 0);
lv_obj_set_style_outline_width(hdr, 0, 0);
lv_obj_set_flex_flow(hdr, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(hdr,
LV_FLEX_ALIGN_SPACE_BETWEEN,
LV_FLEX_ALIGN_START, //LV_FLEX_ALIGN_CENTER, // Ευθυγράμμιση ονόματος/ώρας στον κάθετο άξονα
LV_FLEX_ALIGN_START);
lv_obj_t *lbl_sender = lv_label_create(hdr);
lv_label_set_text(lbl_sender, sender);
lv_obj_set_style_text_color(lbl_sender,
is_self ? lv_color_hex(0xE3F2FD) : lv_color_hex(0x90CAF9), 0);
lv_obj_set_style_text_font(lbl_sender, &lv_font_arial_22, 0);
lv_obj_t *lbl_time = lv_label_create(hdr);
lv_label_set_text(lbl_time, time_str);
lv_obj_set_style_text_color(lbl_time, lv_color_hex(0xB0B0B0), 0);
lv_obj_set_style_text_font(lbl_time, &lv_font_arial_20, 0);
// Message body (below header)
lv_obj_t *lbl_msg = lv_label_create(bubble);
lv_label_set_text(lbl_msg, msg);
lv_label_set_long_mode(lbl_msg, LV_LABEL_LONG_WRAP);
lv_obj_set_width(lbl_msg, lv_pct(100));
lv_obj_set_style_text_color(lbl_msg, lv_color_hex(0xFFFFFF), 0);
lv_obj_set_style_text_font(lbl_msg, &lv_font_arial_26, 0);
// Spacing between header and text
//lv_obj_set_style_margin_top(lbl_msg, 6, 0);
lv_obj_set_style_pad_row(bubble, 6, 0);
chat_items[chat_count++] = row;
lv_obj_scroll_to_view(row, LV_ANIM_ON);
}
void add_private_chat_bubble(lv_obj_t *list, const char *time_str, const char *msg, bool is_self) {
lv_obj_set_style_pad_bottom(list, 20, 0);
// 1. Row container
lv_obj_t *row = lv_obj_create(list);
lv_obj_set_width(row, lv_pct(100));
lv_obj_set_height(row, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(row, 0, 0);
lv_obj_set_style_border_width(row, 0, 0);
lv_obj_set_style_pad_all(row, 4, 0);
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row,
is_self ? LV_FLEX_ALIGN_END : LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START);
// 2. Aligner (Column) - Κρατάει το Label και την Ώρα
lv_obj_t *aligner = lv_obj_create(row);
lv_obj_set_width(aligner, LV_SIZE_CONTENT);
lv_obj_set_height(aligner, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(aligner, 0, 0);
lv_obj_set_style_border_width(aligner, 0, 0);
lv_obj_set_style_pad_all(aligner, 0, 0);
lv_obj_set_flex_flow(aligner, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(aligner,
is_self ? LV_FLEX_ALIGN_END : LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_row(aligner, 4, 0);
// 3. Το Label-Bubble (Ενοποιημένο)
lv_obj_t *lbl_msg = lv_label_create(aligner);
// Long mode για wrap
lv_label_set_long_mode(lbl_msg, LV_LABEL_LONG_WRAP);
lv_label_set_text(lbl_msg, msg);
lv_obj_set_style_text_font(lbl_msg, &lv_font_arial_22, 0);
// Fixed max width για wrap
lv_obj_set_width(lbl_msg, 400); // max πλάτος
lv_obj_set_height(lbl_msg, LV_SIZE_CONTENT); // αυτόματο ύψος
// Bubble style
lv_obj_set_style_bg_opa(lbl_msg, LV_OPA_COVER, 0);
lv_obj_set_style_radius(lbl_msg, 12, 0);
lv_obj_set_style_pad_all(lbl_msg, 12, 0);
if(is_self) {
lv_obj_set_style_bg_color(lbl_msg, lv_color_hex(0x1E88E5), 0);
lv_obj_set_style_text_color(lbl_msg, lv_color_hex(0xFFFFFF), 0);
} else {
lv_obj_set_style_bg_color(lbl_msg, lv_color_hex(0xFFFFFF), 0);
lv_obj_set_style_text_color(lbl_msg, lv_color_hex(0x000000), 0);
}
// 4. Η Ώρα
lv_obj_t *lbl_time = lv_label_create(aligner);
lv_label_set_text(lbl_time, time_str);
lv_obj_set_style_text_color(lbl_time, lv_color_hex(0x808080), 0);
lv_obj_set_style_text_font(lbl_time, &lv_font_arial_14, 0);
lv_obj_scroll_to_view(row, LV_ANIM_ON);
}
// Elecrow Display callbacks
/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
//lcd.fillScreen(TFT_WHITE);
#if (LV_COLOR_16_SWAP != 0)
lcd.pushImageDMA(area->x1, area->y1, w, h,(lgfx::rgb565_t*)&color_p->full);
#else
lcd.pushImageDMA(area->x1, area->y1, w, h,(lgfx::rgb565_t*)&color_p->full);//
#endif
lv_disp_flush_ready(disp);
}
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
if (touch_has_signal())
{
if (touch_touched())
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touch_last_x;
data->point.y = touch_last_y;
// #ifndef MODE_RELEASE
// Serial.printf("Data x: %d, Data y: %d", touch_last_x, touch_last_y);
// Serial.println();
// #endif
}
else if (touch_released())
{
data->state = LV_INDEV_STATE_REL;
}
}
else
{
data->state = LV_INDEV_STATE_REL;
}
delay(15);
}
void initializeUI() {
Serial.println("initialize UI...");
ui_init();
//ui_init_screen_events();
/*
#ifdef ENABLE_STARTUP_LOGO
lv_disp_load_scr(ui_ScreenLogo);
for( int i=0; i < 100; i++ ){
lv_task_handler();
delay(10);
}
lv_scr_load_anim(ui_Screen1, LV_SCR_LOAD_ANIM_MOVE_TOP, 500, 0, true);
#else
ui_init();
#endif
*/
uiManager = new UIManager();
}
void configureDisplay() {
Serial.println("Configuring display...");
screenWidth = lcd.width();
screenHeight = lcd.height();
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 10);
/* Initialize the display */
lv_disp_drv_init(&disp_drv);
/* Change the following line to your display resolution */
disp_drv.hor_res = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
/* Initialize the (dummy) input device driver */
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
#ifdef TFT_BL
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH);
#endif
lcd.fillScreen(0x000000u);
}
void onWaitRelayPressed(bool pressed) {
//mySettings->writeBool(PREF_WAIT_RELAY, pressed);
}
void initializeDisplay() {
Serial.println("Initializing display...");
lcd.begin();
lcd.fillScreen(0x000000u);
lcd.setTextSize(2);
//lcd.setBrightness(127);
}
void initializeTouchScreen() {
Serial.println("Initializing touch screen...");
touch_init();
}
void initializeLVGL() {
Serial.println("Initializing LVGL...");
lv_init();
}
void createSemaphores() {
#ifdef USE_MULTI_THREAD
semaphoreData = xSemaphoreCreateMutex();
xSemaphoreGive(semaphoreData);
#endif
}
// Believe it or not, this std C function is busted on some platforms!
static uint32_t _atoi(const char* sp) {
uint32_t n = 0;
@ -607,20 +238,11 @@ protected:
if (strcmp(text, "clock sync") == 0) { // special text command
setClock(sender_timestamp + 1);
}
char time_buf[16];
format_time(sender_timestamp, time_buf, sizeof(time_buf));
bool is_self = (strcmp(from.name, _prefs.node_name) == 0);
add_private_chat_bubble(ui_ContactMessages, time_buf, text, is_self);
}
void onCommandDataRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override {
MESH_DEBUG_PRINTLN("onCommandDataRecv");
}
void onSignedMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override {
MESH_DEBUG_PRINTLN("onSignedMessageRecv");
}
void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) override {
@ -630,34 +252,13 @@ protected:
Serial.printf("PUBLIC CHANNEL MSG -> (Flood) hops %d\n", pkt->path_len);
}
Serial.printf(" %s\n", text);
// Μόνο public
// if (strcmp(channel.secret, PUBLIC_GROUP_PSK) != 0)
// return;
if (pkt->getPayloadType() != PAYLOAD_TYPE_GRP_TXT)
return;
char time_buf[16];
format_time(timestamp, time_buf, sizeof(time_buf));
char sender[32];
char msg[192];
parse_group_message(text, sender, sizeof(sender), msg, sizeof(msg));
bool is_self = (strcmp(sender, _prefs.node_name) == 0);
add_chat_bubble(ui_ChannelMessages, time_buf, sender, msg, is_self);
}
uint8_t onContactRequest(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t* data, uint8_t len, uint8_t* reply) override {
MESH_DEBUG_PRINTLN("onContactRequest");
return 0; // unknown
}
void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) override {
MESH_DEBUG_PRINTLN("onContactResponse");
// not supported
}
@ -982,28 +583,9 @@ void setup() {
// send out initial Advertisement to the mesh
the_mesh.sendSelfAdvert(1200); // add slight delay
initializeDisplay();
delay(200);
initializeLVGL();
initializeTouchScreen();
configureDisplay();
createSemaphores();
initializeUI();
createTasks();
Serial.println("Setup completed");
}
void loop() {
the_mesh.loop();
rtc_clock.tick();
}
// void loop() {
// vTaskDelete(NULL);
// }
Loading…
Cancel
Save