mirror of
https://github.com/espressif/esp-rainmaker.git
synced 2026-01-15 08:19:59 +00:00
300 lines
12 KiB
C
300 lines
12 KiB
C
/*
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
*/
|
|
|
|
#include "m5display.h"
|
|
|
|
#if CONFIG_M5STACK_THREAD_BR_BOARD
|
|
#include <app_insights.h>
|
|
#include <app_thread_config.h>
|
|
#include <app_wifi.h>
|
|
#include <bsp/esp-bsp.h>
|
|
#include <esp_openthread_lock.h>
|
|
#include <esp_rmaker_thread_br.h>
|
|
#include <esp_rmaker_utils.h>
|
|
#include <esp_wifi.h>
|
|
#include <lvgl.h>
|
|
|
|
static const char *TAG = "m5_display";
|
|
static lv_obj_t *page = NULL;
|
|
static lv_obj_t *qrcode = NULL;
|
|
static lv_obj_t *tips_label = NULL;
|
|
static lv_obj_t *thread_panid_text = NULL;
|
|
static lv_obj_t *waiting_label = NULL;
|
|
static lv_obj_t *wifi_ssid_text = NULL;
|
|
static char *qr_data = NULL;
|
|
static bool br_info_gotten_flag = false;
|
|
static lv_obj_t *br_info_label = NULL;
|
|
TaskHandle_t xRefresh_Ui_Handle = NULL;
|
|
LV_IMG_DECLARE(Thread)
|
|
LV_IMG_DECLARE(wifi)
|
|
LV_IMG_DECLARE(logo)
|
|
#define LV_SYMBOL_EXTRA_SYNC "\xef\x80\xA1"
|
|
|
|
typedef struct border_router_info {
|
|
const char *network_name;
|
|
otPanId pan_id;
|
|
uint64_t ext_pan_id;
|
|
uint8_t channel;
|
|
wifi_config_t stationConfig;
|
|
} border_router_info_t;
|
|
|
|
static border_router_info_t *get_border_router_info()
|
|
{
|
|
static border_router_info_t info;
|
|
if (!br_info_gotten_flag) {
|
|
esp_openthread_lock_acquire(portMAX_DELAY);
|
|
otInstance *instance = esp_openthread_get_instance();
|
|
info.network_name = otThreadGetNetworkName(instance);
|
|
info.channel = otLinkGetChannel(instance);
|
|
info.pan_id = otLinkGetPanId(instance);
|
|
const otExtendedPanId *extended_pan_id = otThreadGetExtendedPanId(instance);
|
|
esp_openthread_lock_release();
|
|
info.ext_pan_id = 0;
|
|
for (size_t i = 0; i < OT_EXT_PAN_ID_SIZE; ++i) {
|
|
info.ext_pan_id |= (uint64_t)(extended_pan_id->m8[i]) << (56 - 8 * i);
|
|
}
|
|
br_info_gotten_flag = true;
|
|
esp_wifi_get_config(WIFI_IF_STA, &info.stationConfig);
|
|
}
|
|
return &info;
|
|
}
|
|
|
|
static void msg_btn_event_cb(lv_event_t *e)
|
|
{
|
|
lv_obj_t *btn = lv_event_get_target(e);
|
|
lv_obj_t *mbox = lv_obj_get_parent(lv_obj_get_parent(btn));
|
|
lv_obj_t *label = lv_obj_get_child(btn, 0);
|
|
static bool factory_reset = false;
|
|
if (strcmp(lv_label_get_text(label), "Ok") == 0) {
|
|
if (!factory_reset) {
|
|
lv_obj_t *content = lv_msgbox_get_content(mbox);
|
|
lv_obj_t *label = lv_label_create(content);
|
|
lv_label_set_text_static(label, "Reseting");
|
|
lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_RED), LV_STATE_DEFAULT);
|
|
esp_rmaker_factory_reset(1, 0);
|
|
factory_reset = true;
|
|
}
|
|
} else {
|
|
lv_msgbox_close(mbox);
|
|
}
|
|
}
|
|
|
|
static void btn_event_cb(lv_event_t *e)
|
|
{
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
if (code == LV_EVENT_CLICKED) {
|
|
lv_obj_t *msgbox = lv_msgbox_create(NULL);
|
|
lv_msgbox_add_title(msgbox, "Setting");
|
|
lv_msgbox_add_text(msgbox, "Are you sure to reset BR?");
|
|
lv_obj_t *btn = lv_msgbox_add_footer_button(msgbox, "Ok");
|
|
lv_obj_set_size(btn, 80, 40);
|
|
lv_obj_add_event_cb(btn, msg_btn_event_cb, LV_EVENT_CLICKED, NULL);
|
|
btn = lv_msgbox_add_footer_button(msgbox, "Cancel");
|
|
lv_obj_set_size(btn, 80, 40);
|
|
lv_obj_add_event_cb(btn, msg_btn_event_cb, LV_EVENT_CLICKED, NULL);
|
|
}
|
|
}
|
|
|
|
static void msgbox_event_cb(lv_event_t *e)
|
|
{
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
if (code == LV_EVENT_DELETE) {
|
|
br_info_label = NULL;
|
|
}
|
|
}
|
|
|
|
static void show_border_router_info_cb(lv_event_t *e)
|
|
{
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
if (code == LV_EVENT_CLICKED) {
|
|
lv_obj_t *msgbox = lv_msgbox_create(NULL);
|
|
lv_msgbox_add_title(msgbox, "Thread border router info");
|
|
lv_obj_t *content = lv_msgbox_get_content(msgbox);
|
|
br_info_label = lv_label_create(content);
|
|
border_router_info_t *info = get_border_router_info();
|
|
lv_label_set_text_fmt(br_info_label, "name: %s\rchannel: %d\rpanid: 0x%x\rextpanid: %llx", info->network_name,
|
|
info->channel, info->pan_id, info->ext_pan_id);
|
|
lv_msgbox_add_close_button(msgbox);
|
|
lv_obj_add_event_cb(msgbox, msgbox_event_cb, LV_EVENT_DELETE, NULL);
|
|
}
|
|
}
|
|
|
|
static void animation_opa_ready_callback(lv_anim_t *anim)
|
|
{
|
|
lv_anim_start(lv_anim_get_user_data(anim));
|
|
}
|
|
|
|
static void animation_move_ready_callback(lv_anim_t *anim)
|
|
{
|
|
if (xRefresh_Ui_Handle) {
|
|
xTaskNotifyGive(xRefresh_Ui_Handle);
|
|
}
|
|
}
|
|
|
|
static void anim_opa_exec_cb(void *obj, int32_t value)
|
|
{
|
|
lv_obj_set_style_opa((lv_obj_t *)obj, value, LV_STATE_DEFAULT);
|
|
}
|
|
|
|
static void anim_move_exec_cb(void *obj, int32_t value)
|
|
{
|
|
lv_obj_set_x((lv_obj_t *)obj, value * 0.5);
|
|
lv_obj_set_y((lv_obj_t *)obj, value);
|
|
}
|
|
|
|
static void display_animation_task(void *args)
|
|
{
|
|
page = lv_obj_create(lv_scr_act());
|
|
lv_obj_set_size(page, 320, 240);
|
|
lv_obj_align(page, LV_ALIGN_CENTER, 0, 0);
|
|
|
|
lv_obj_t *espressif_img = lv_img_create(page);
|
|
lv_obj_set_style_opa(espressif_img, LV_OPA_TRANSP, LV_STATE_DEFAULT);
|
|
lv_obj_align(espressif_img, LV_ALIGN_CENTER, 0, 0);
|
|
lv_img_set_src(espressif_img, &logo);
|
|
|
|
lv_anim_t anim_1;
|
|
lv_anim_init(&anim_1);
|
|
lv_anim_set_var(&anim_1, espressif_img);
|
|
lv_anim_set_values(&anim_1, LV_OPA_TRANSP, LV_OPA_COVER);
|
|
lv_anim_set_time(&anim_1, 1000);
|
|
lv_anim_set_exec_cb(&anim_1, anim_opa_exec_cb);
|
|
lv_anim_set_ready_cb(&anim_1, animation_opa_ready_callback);
|
|
|
|
lv_anim_t anim_2;
|
|
lv_anim_init(&anim_2);
|
|
lv_anim_set_var(&anim_2, espressif_img);
|
|
lv_anim_set_values(&anim_2, 0, -85);
|
|
lv_anim_set_time(&anim_2, 500);
|
|
lv_anim_set_exec_cb(&anim_2, anim_move_exec_cb);
|
|
lv_anim_set_ready_cb(&anim_2, animation_move_ready_callback);
|
|
lv_anim_set_user_data(&anim_1, &anim_2);
|
|
lv_anim_start(&anim_1);
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
static void qr_display_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
|
{
|
|
bsp_display_lock(0);
|
|
if (waiting_label && !lv_obj_has_flag(waiting_label, LV_OBJ_FLAG_HIDDEN)) {
|
|
lv_obj_add_flag(waiting_label, LV_OBJ_FLAG_HIDDEN);
|
|
}
|
|
bsp_display_unlock();
|
|
if (event_base == APP_NETWORK_EVENT && event_id == APP_NETWORK_EVENT_QR_DISPLAY) {
|
|
qr_data = (char *)event_data;
|
|
bsp_display_lock(0);
|
|
qrcode = lv_qrcode_create(page);
|
|
lv_obj_align(qrcode, LV_ALIGN_CENTER, 0, 10);
|
|
lv_qrcode_update(qrcode, qr_data, strlen(qr_data));
|
|
tips_label = lv_label_create(page);
|
|
lv_label_set_text_static(tips_label, "Use RainMaker to setup BR");
|
|
lv_obj_align_to(tips_label, qrcode, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
|
|
bsp_display_unlock();
|
|
} else if (event_base == OPENTHREAD_EVENT && event_id == OPENTHREAD_EVENT_ROLE_CHANGED) {
|
|
if (!thread_panid_text) {
|
|
border_router_info_t *info = get_border_router_info();
|
|
bsp_display_lock(0);
|
|
lv_obj_t *thread_img = lv_img_create(page);
|
|
lv_obj_align(thread_img, LV_ALIGN_CENTER, 90, 80);
|
|
lv_img_set_src(thread_img, &Thread);
|
|
|
|
thread_panid_text = lv_label_create(page);
|
|
lv_label_set_text_fmt(thread_panid_text, "panid:0x%x", info->pan_id);
|
|
lv_obj_align_to(thread_panid_text, thread_img, LV_ALIGN_OUT_TOP_MID, 0, -10);
|
|
|
|
lv_obj_t *border_router_obj = lv_btn_create(page);
|
|
lv_obj_set_size(border_router_obj, 280, 60);
|
|
lv_obj_set_style_bg_color(border_router_obj, lv_color_white(), LV_STATE_DEFAULT);
|
|
lv_obj_set_style_bg_color(border_router_obj, lv_palette_lighten(LV_PALETTE_BLUE, 1), LV_STATE_PRESSED);
|
|
lv_obj_set_style_border_width(border_router_obj, 1, LV_PART_MAIN);
|
|
lv_obj_set_style_border_color(border_router_obj, lv_color_black(), LV_PART_MAIN);
|
|
lv_obj_add_event_cb(border_router_obj, show_border_router_info_cb, LV_EVENT_CLICKED, NULL);
|
|
lv_obj_align(border_router_obj, LV_ALIGN_CENTER, 0, -15);
|
|
|
|
lv_obj_t *border_router_label = lv_label_create(page);
|
|
lv_label_set_text_static(border_router_label, "ESP Thread Border Router");
|
|
lv_obj_set_style_text_font(border_router_label, &lv_font_montserrat_20, LV_PART_MAIN);
|
|
lv_obj_align_to(border_router_label, border_router_obj, LV_ALIGN_CENTER, 0, 0);
|
|
|
|
lv_obj_t *wifi_img = lv_img_create(page);
|
|
lv_obj_align(wifi_img, LV_ALIGN_CENTER, -90, 80);
|
|
lv_img_set_src(wifi_img, &wifi);
|
|
|
|
wifi_ssid_text = lv_label_create(page);
|
|
lv_label_set_text_fmt(wifi_ssid_text, "ssid:%s", (char *)(info->stationConfig.sta.ssid));
|
|
lv_obj_align_to(wifi_ssid_text, wifi_img, LV_ALIGN_OUT_TOP_MID, 0, -10);
|
|
|
|
if (qrcode) {
|
|
lv_obj_add_flag(qrcode, LV_OBJ_FLAG_HIDDEN);
|
|
lv_obj_add_flag(tips_label, LV_OBJ_FLAG_HIDDEN);
|
|
}
|
|
bsp_display_unlock();
|
|
}
|
|
} else if (event_base == OPENTHREAD_EVENT && event_id == OPENTHREAD_EVENT_DATASET_CHANGED) {
|
|
br_info_gotten_flag = false;
|
|
border_router_info_t *info = get_border_router_info();
|
|
bsp_display_lock(0);
|
|
if (thread_panid_text) {
|
|
lv_label_set_text_fmt(thread_panid_text, "panid:0x%x", info->pan_id);
|
|
}
|
|
if (br_info_label) {
|
|
lv_label_set_text_fmt(br_info_label, "name: %s\rchannel: %d\rpanid: 0x%x\rextpanid: %llx",
|
|
info->network_name, info->channel, info->pan_id, info->ext_pan_id);
|
|
}
|
|
bsp_display_unlock();
|
|
}
|
|
}
|
|
|
|
void app_m5stack_display_start()
|
|
{
|
|
bsp_i2c_init();
|
|
bsp_display_cfg_t cfg = {.lvgl_port_cfg = ESP_LVGL_PORT_INIT_CONFIG(),
|
|
.buffer_size = BSP_LCD_H_RES * 10,
|
|
.double_buffer = 0,
|
|
.flags = {
|
|
.buff_dma = true,
|
|
.buff_spiram = false,
|
|
}};
|
|
cfg.lvgl_port_cfg.task_affinity = 1;
|
|
bsp_display_start_with_config(&cfg);
|
|
|
|
xTaskCreatePinnedToCore(display_animation_task, "AnimationTask", 2048, NULL, 1, NULL, 1);
|
|
xRefresh_Ui_Handle = xTaskGetCurrentTaskHandle();
|
|
while (true) {
|
|
if (ulTaskNotifyTake(pdTRUE, portMAX_DELAY) == true) {
|
|
/* Wait for m5 stack display start */
|
|
break;
|
|
}
|
|
}
|
|
ESP_LOGI(TAG, "m5 stack animation finish, exec next");
|
|
lv_obj_t *reset_button = lv_btn_create(page);
|
|
lv_obj_set_style_bg_color(reset_button, lv_color_white(), LV_STATE_DEFAULT);
|
|
lv_obj_set_style_bg_color(reset_button, lv_palette_lighten(LV_PALETTE_RED, 1), LV_STATE_PRESSED);
|
|
lv_obj_set_style_border_width(reset_button, 1, LV_PART_MAIN);
|
|
lv_obj_set_style_border_color(reset_button, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
|
|
lv_obj_align(reset_button, LV_ALIGN_TOP_RIGHT, 0, 0);
|
|
lv_obj_set_size(reset_button, 60, 40);
|
|
lv_obj_t *reset_label = lv_label_create(page);
|
|
lv_label_set_text_static(reset_label, LV_SYMBOL_EXTRA_SYNC);
|
|
lv_obj_align_to(reset_label, reset_button, LV_ALIGN_CENTER, 0, 0);
|
|
lv_obj_add_event_cb(reset_button, btn_event_cb, LV_EVENT_CLICKED, NULL);
|
|
|
|
waiting_label = lv_label_create(page);
|
|
lv_label_set_text_static(waiting_label, "Waiting for BR initialization");
|
|
lv_obj_align(waiting_label, LV_ALIGN_CENTER, 0, 10);
|
|
}
|
|
|
|
void app_register_m5stack_display_event_handler()
|
|
{
|
|
esp_event_handler_register(APP_NETWORK_EVENT, APP_NETWORK_EVENT_QR_DISPLAY, qr_display_event_handler, NULL);
|
|
esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_ROLE_CHANGED, qr_display_event_handler, NULL);
|
|
esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_DATASET_CHANGED, qr_display_event_handler, NULL);
|
|
}
|
|
|
|
#endif /* CONFIG_M5STACK_THREAD_BR_BOARD */
|