Merge branch 'feature-pagenav' into 0.4.0-dev

This commit is contained in:
fvanroie 2021-03-23 12:24:37 +01:00
commit 92ca6bf1d8
30 changed files with 4930 additions and 195 deletions

View File

@ -44,7 +44,7 @@ jobs:
run: |
cat platformio_override.ini
- name: Run PlatformIO
run: pio run -e d1-mini-esp32_ili9341 -e lanbon_l8 -e wt32-sc01 -e d1-mini-esp8266_ili9341 -e linux_sdl_64bits
run: pio run -e d1-mini-esp32_ili9341 -e esp32-touchdown -e huzzah32-featherwing-24 -e huzzah32-featherwing-35 -e lanbon_l8 -e m5stack-core2 -e wt32-sc01 -e d1-mini-esp8266_ili9341 -e linux_sdl_64bits
- name: Upload output file
uses: actions/upload-artifact@v2
with:

View File

@ -518,9 +518,11 @@ typedef void* lv_font_user_data_t;
/*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/
typedef struct {
uint8_t id:8;
uint8_t objid:8;
uint8_t groupid:8;
uint8_t id;
uint8_t transitionid:4;
uint8_t actionid:4;
uint8_t groupid:4;
} lv_obj_user_data_t;
/*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/

View File

@ -582,9 +582,11 @@ typedef void * lv_font_user_data_t;
*==================*/
typedef struct {
uint8_t id:8;
uint8_t objid:8;
uint8_t groupid:8;
uint8_t id;
uint8_t transitionid:4;
uint8_t actionid:4;
uint8_t groupid:4;
} lv_obj_user_data_t;
#if LV_USE_USER_DATA

View File

@ -86,13 +86,15 @@ lib_deps =
src_filter = +<*> -<.git/> -<examples/> -<test/> -<tests/> -<stm32f4/> -<lv_font_montserrat_*.c>
extra_scripts = tools/copy_fw.py ; tools/pre:extra_script.py
; -- Platform specific build flags
[esp32]
framework = arduino
platform = espressif32
board_build.partitions = user_setups/esp32/partition_app1536k_spiffs1024k.csv
board_upload.flash_size=4MB
board_upload.maximum_size = 4194304
board_build.partitions = user_setups/esp32/partition_app1704k_spiffs720k.csv
; ----- crash reporter
monitor_filters = esp32_exception_decoder
@ -143,9 +145,10 @@ ps_ram =
-mfix-esp32-psram-cache-issue
extra_scripts =
${env.extra_scripts}
tools/copy_partitions.py
tools/esp_merge_bin.py
tools/analyze_elf.py
; ${env.extra_scripts}
; tools/copy_partitions.py
; -- The ESP32 has 2 SPI Hardware Busses available to use:
vspi =
@ -191,6 +194,8 @@ build_flags=
-D HASP_USE_ETHERNET=0
-D HASP_USE_CONFIG=1 ; Native application, not library
extra_scripts = tools/copy_fw.py ; tools/pre:extra_script.py
lib_ignore =
ESP32 BLE Arduino
GxTFT
@ -200,6 +205,7 @@ lib_ignore =
lib_deps =
[stm32f4]
framework = arduino
platform = ststm32

View File

@ -6,11 +6,11 @@
[platformio]
extra_configs =
; Uncomment or edit the lines to show more User Setups in the PIO sidebar
; user_setups/darwin_sdl/*.ini
; user_setups/esp32/*.ini
; user_setups/esp8266/*.ini
; user_setups/stm32f4xx/*.ini
; user_setups/darwin_sdl/*.ini
; user_setups/linux_sdl/*.ini
; user_setups/stm32f4xx/*.ini
; user_setups/win32/*.ini
[override]
@ -24,15 +24,16 @@ extra_default_envs =
; Comment unneeded environments or create extra
; d1-mini-esp32_ili9341
; d1-mini-esp8266_ili9341
; lolind32pro-lolintft24
; esp32dev-mrb3511
; esp12e-st7735
; d132-unoshield
; nodemcu32s-raspi
; esp12e-st7735
; esp32dev-mrb3511
; esp32dev-ili9488
; lanbon_l8
; wt32-sc01
; lolin-d32-pro_ili9341
; my_custom_build
; nodemcu32s-raspi
; wt32-sc01
; ttgo_esp32_poe-ili9341
;endregion
;region -- Define your local COM ports for each environment ---
@ -55,16 +56,16 @@ upload_port = 192.168.4.4 ; IP of the ESP
upload_protocol = espota ; Use ArduinoOTA after flashing over serial
upload_flags = --port=3232 ; --auth=haspadmin ; OTA password
[env:ttgo_esp32_poe-lolintft24]
[env:ttgo_esp32_poe-ili9341]
monitor_port = COM9 ; Change to the correct port
;upload_port = ${env:ttgo_esp32_poe-lolintft24.monitor_port}
;upload_port = ${env:ttgo_esp32_poe-ili9341.monitor_port}
upload_port = 192.168.4.5 ; IP of the ESP
upload_protocol = espota ; Use ArduinoOTA after flashing over serial
upload_flags = --port=3232 ; --auth=haspadmin ; OTA password
[env:lolind32pro-lolintft24]
monitor_port = COM3 ; Change to the correct port
upload_port = ${env:lolind32pro-lolintft24.monitor_port}
[env:lolin-d32-pro_ili9341]
monitor_port = COM5 ; Change to the correct port
upload_port = ${env:lolin-d32-pro_ili9341.monitor_port}
;endregion
;region -- Custom Environment configuration example -----------------

View File

@ -32,6 +32,7 @@
#endif
#include "hasplib.h"
#include "hasp.h"
#include "lv_theme_hasp.h"
#include "dev/device.h"
@ -74,7 +75,6 @@ LV_IMG_DECLARE(img_bubble_pattern)
/**********************
* GLOBAL FUNCTIONS
**********************/
void haspLoadPage(const char* pages);
////////////////////////////////////////////////////////////////////////////////////////////////////
uint8_t hasp_sleep_state = HASP_SLEEP_OFF; // Used in hasp_drv_touch.cpp
@ -92,7 +92,6 @@ lv_style_t style_mbox_bg; /*Black bg. style with opacity*/
lv_obj_t* kb;
// lv_font_t * defaultFont;
lv_obj_t* pages[HASP_NUM_PAGES];
static lv_font_t* haspFonts[4] = {nullptr, nullptr, nullptr, nullptr};
uint8_t current_page = 1;
@ -175,42 +174,6 @@ void haspEverySecond()
dispatchEverySecond();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Get Page Object by PageID
*/
lv_obj_t* get_page_obj(uint8_t pageid)
{
if(pageid == 0) return lv_layer_top(); // 254
if(pageid == 255) return lv_layer_sys();
if(pageid > sizeof pages / sizeof *pages) return NULL; // >=0
return pages[pageid - PAGE_START_INDEX];
}
bool get_page_id(lv_obj_t* obj, uint8_t* pageid)
{
lv_obj_t* page = lv_obj_get_screen(obj);
if(!page) return false;
if(page == lv_layer_top()) {
*pageid = 0; // 254
return true;
}
if(page == lv_layer_sys()) {
*pageid = 255;
return true;
}
for(uint8_t i = 0; i < sizeof pages / sizeof *pages; i++) {
if(page == pages[i]) {
*pageid = i + PAGE_START_INDEX;
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void haspDisconnect()
@ -256,7 +219,7 @@ void haspReconnect()
void haspProgressVal(uint8_t val)
{
lv_obj_t* layer = lv_disp_get_layer_sys(NULL);
lv_obj_t* bar = hasp_find_obj_from_parent_id(get_page_obj(255), (uint8_t)10);
lv_obj_t* bar = hasp_find_obj_from_parent_id(haspPages.get_obj(255), (uint8_t)10);
if(layer && bar) {
if(val == 255) {
if(!lv_obj_get_hidden(bar)) {
@ -285,7 +248,7 @@ void haspProgressVal(uint8_t val)
// Sets the value string of the global progress bar
void haspProgressMsg(const char* msg)
{
lv_obj_t* bar = hasp_find_obj_from_parent_id(get_page_obj(255), (uint8_t)10);
lv_obj_t* bar = hasp_find_obj_from_parent_id(haspPages.get_obj(255), (uint8_t)10);
if(bar) {
char value_str[10];
@ -363,7 +326,7 @@ void haspSetup(void)
/* ********** Font Initializations ********** */
LOG_WARNING(TAG_ATTR, "%s %d %x", __FILE__, __LINE__, nullptr);
LOG_WARNING(TAG_ATTR, "%s %d %x", __FILE__, __LINE__, haspFonts[1]);
LOG_WARNING(TAG_ATTR, "%s %d %x", __FILE__, __LINE__, haspFonts[0]);
// LOG_WARNING(TAG_ATTR, "%s %d %x", __FILE__, __LINE__, &robotocondensed_regular_16_nokern);
#if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0
@ -375,7 +338,7 @@ void haspSetup(void)
// WARNING: hasp_font needs to be null !
if(lv_zifont_font_init(&hasp_font, haspZiFontPath, 32) != 0) {
LOG_ERROR(TAG_HASP, F("Failed to set font to %s"), haspZiFontPath);
haspFonts[1] = LV_FONT_DEFAULT;
haspFonts[0] = LV_THEME_DEFAULT_FONT_SMALL;
} else {
// defaultFont = haspFonts[0];
haspFonts[0] = hasp_font; // save it
@ -388,7 +351,7 @@ void haspSetup(void)
#endif
if(haspFonts[0] == nullptr) haspFonts[0] = LV_THEME_DEFAULT_FONT_SMALL;
// if(haspFonts[1] == nullptr) haspFonts[1] = LV_THEME_DEFAULT_FONT_NORMAL;
if(haspFonts[1] == nullptr) haspFonts[1] = LV_THEME_DEFAULT_FONT_NORMAL;
if(haspFonts[2] == nullptr) haspFonts[2] = LV_THEME_DEFAULT_FONT_SUBTITLE;
if(haspFonts[3] == nullptr) haspFonts[3] = LV_THEME_DEFAULT_FONT_TITLE;
@ -482,9 +445,6 @@ void haspSetup(void)
}
/* Create all screens using the theme */
for(int i = 0; i < (sizeof pages / sizeof *pages); i++) {
pages[i] = lv_obj_create(NULL, NULL);
}
#if HASP_USE_WIFI > 0
if(!wifiShowAP()) {
@ -492,8 +452,9 @@ void haspSetup(void)
}
#endif
haspLoadPage(haspPagesPath);
haspSetPage(haspStartPage);
haspPages.init(haspStartPage);
haspPages.load_jsonl(haspPagesPath);
haspPages.set(haspStartPage, LV_SCR_LOAD_ANIM_NONE);
}
/**********************
@ -563,7 +524,7 @@ void haspGetVersion(char* version, size_t len)
void haspClearPage(uint16_t pageid)
{
lv_obj_t* page = get_page_obj(pageid);
lv_obj_t* page = haspPages.get_obj(pageid);
if(!page || (pageid > HASP_NUM_PAGES)) {
LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid);
} else if(page == lv_layer_sys() /*|| page == lv_layer_top()*/) {
@ -581,7 +542,7 @@ uint8_t haspGetPage()
void haspSetPage(uint8_t pageid)
{
lv_obj_t* page = get_page_obj(pageid);
lv_obj_t* page = haspPages.get_obj(pageid);
if(!page || pageid == 0 || pageid > HASP_NUM_PAGES) {
LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid);
} else {

View File

@ -19,8 +19,6 @@
#include "dev/device.h"
#endif
#define NORMALIZE(a, b, c) map(a, b, c, 0, 0xFFFFU)
#ifdef __cplusplus
extern "C" {
#endif
@ -56,13 +54,6 @@ void haspEverySecond(void);
void haspReconnect(void);
void haspDisconnect(void);
lv_obj_t* get_page_obj(uint8_t pageid);
bool get_page_id(lv_obj_t* obj, uint8_t* pageid);
void haspSetPage(uint8_t id);
uint8_t haspGetPage();
void haspClearPage(uint16_t pageid);
void haspGetVersion(char* version, size_t len);
// void haspBackground(uint16_t pageid, uint16_t imageid);

View File

@ -1406,6 +1406,15 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* p
update ? (void)(obj->user_data.groupid = (uint8_t)val) : hasp_out_int(obj, attr, obj->user_data.groupid);
break; // attribute_found
case ATTR_ACTION:
update ? (void)(obj->user_data.actionid = (uint8_t)val) : hasp_out_int(obj, attr, obj->user_data.actionid);
break; // attribute_found
case ATTR_TRANSITION:
update ? (void)(obj->user_data.transitionid = (uint8_t)val)
: hasp_out_int(obj, attr, obj->user_data.transitionid);
break; // attribute_found
case ATTR_OBJ:
if(update) LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attr_p);
hasp_out_str(obj, attr, get_obj_type_name(obj));

View File

@ -312,6 +312,8 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t)
#define ATTR_MAP 45628
/* hasp user data */
#define ATTR_ACTION 42102
#define ATTR_TRANSITION 10933
#define ATTR_GROUPID 48986
#define ATTR_OBJID 41010
#define ATTR_OBJ 53623

View File

@ -748,7 +748,7 @@ void dispatch_parse_json(const char*, const char* payload)
}
// guiStart();
} else if(json.is<JsonObject>()) { // handle json as a jsonl
uint8_t savedPage = haspGetPage();
uint8_t savedPage = haspPages.get();
hasp_new_object(json.as<JsonObject>(), savedPage);
// #ifdef ARDUINO
@ -776,7 +776,7 @@ void dispatch_parse_jsonl(Stream& stream)
void dispatch_parse_jsonl(std::istream& stream)
#endif
{
uint8_t savedPage = haspGetPage();
uint8_t savedPage = haspPages.get();
size_t line = 1;
DynamicJsonDocument jsonl(MQTT_MAX_PACKET_SIZE / 2 + 128); // max ~256 characters per line
DeserializationError jsonError = deserializeJson(jsonl, stream);
@ -820,63 +820,71 @@ void dispatch_output_current_page()
char payload[8];
memcpy_P(topic, PSTR("page"), 5);
snprintf_P(payload, sizeof(payload), PSTR("%d"), haspGetPage());
snprintf_P(payload, sizeof(payload), PSTR("%d"), haspPages.get());
dispatch_state_subtopic(topic, payload);
}
// Get or Set a page
// Dispatch Page Get or Set
void dispatch_page_next(lv_scr_load_anim_t animation)
{
haspPages.next(animation);
dispatch_output_current_page();
}
void dispatch_page_prev(lv_scr_load_anim_t animation)
{
haspPages.prev(animation);
dispatch_output_current_page();
}
void dispatch_page_back(lv_scr_load_anim_t animation)
{
haspPages.back(animation);
dispatch_output_current_page();
}
void dispatch_set_page(uint8_t pageid)
{
dispatch_set_page(pageid, LV_SCR_LOAD_ANIM_NONE);
}
void dispatch_set_page(uint8_t pageid, lv_scr_load_anim_t animation)
{
haspPages.set(pageid, animation);
dispatch_output_current_page();
}
void dispatch_page(const char*, const char* page)
{
if(strlen(page) > 0) {
if(Utilities::is_only_digits(page)) {
uint8_t pageid = atoi(page);
haspSetPage(pageid);
} else {
if(!strcasecmp_P(page, PSTR("prev"))) {
dispatch_page_prev();
} else if(!strcasecmp_P(page, PSTR("next"))) {
dispatch_page_next();
} else {
LOG_WARNING(TAG_MSGR, PSTR(D_DISPATCH_INVALID_PAGE), page);
}
return;
}
if(strlen(page) == 0) {
dispatch_output_current_page(); // No payload, send current page
return;
}
dispatch_output_current_page();
}
void dispatch_page_next()
{
uint8_t page = haspGetPage();
if(page >= HASP_NUM_PAGES) {
page = 1;
lv_scr_load_anim_t animation = LV_SCR_LOAD_ANIM_NONE;
if(Utilities::is_only_digits(page)) {
uint8_t pageid = atoi(page);
dispatch_set_page(pageid, animation);
} else if(!strcasecmp_P(page, PSTR("prev"))) {
dispatch_page_prev(animation);
} else if(!strcasecmp_P(page, PSTR("next"))) {
dispatch_page_next(animation);
} else if(!strcasecmp_P(page, PSTR("back"))) {
dispatch_page_back(animation);
} else {
page++;
LOG_WARNING(TAG_MSGR, PSTR(D_DISPATCH_INVALID_PAGE), page);
}
haspSetPage(page);
dispatch_output_current_page();
}
void dispatch_page_prev()
{
uint8_t page = haspGetPage();
if(page == 1) {
page = HASP_NUM_PAGES;
} else {
page--;
}
haspSetPage(page);
dispatch_output_current_page();
}
// Clears a page id or the current page if empty
void dispatch_clear_page(const char*, const char* page)
{
uint8_t pageid = haspGetPage();
if(strlen(page) > 0) pageid = atoi(page);
haspClearPage(pageid);
uint8_t pageid;
if(strlen(page) > 0)
pageid = atoi(page);
else
pageid = haspPages.get();
haspPages.clear(pageid);
}
void dispatch_dim(const char*, const char* level)
@ -1046,8 +1054,8 @@ void dispatch_output_statusupdate(const char*, const char*)
haspDevice.get_free_heap(), haspDevice.get_heap_fragmentation(), haspDevice.get_core_version());
strcat(data, buffer);
snprintf_P(buffer, sizeof(buffer), PSTR("\"canUpdate\":\"false\",\"page\":%u,\"numPages\":%u,"), haspGetPage(),
(HASP_NUM_PAGES));
snprintf_P(buffer, sizeof(buffer), PSTR("\"canUpdate\":\"false\",\"page\":%u,\"numPages\":%u,"),
haspPages.get(), haspPages.count());
strcat(data, buffer);
// #if defined(ARDUINO_ARCH_ESP8266)

View File

@ -47,9 +47,11 @@ void dispatch_parse_jsonl(std::istream& stream);
void dispatch_clear_page(const char* page);
void dispatch_json_error(uint8_t tag, DeserializationError& jsonError);
// void dispatchPage(uint8_t page);
void dispatch_page_next();
void dispatch_page_prev();
// void dispatch_set_page(uint8_t pageid);
void dispatch_set_page(uint8_t pageid, lv_scr_load_anim_t effectid);
void dispatch_page_next(lv_scr_load_anim_t effectid);
void dispatch_page_prev(lv_scr_load_anim_t effectid);
void dispatch_page_back(lv_scr_load_anim_t effectid);
void dispatch_dim(const char* level);
void dispatch_backlight(const char*, const char* payload);
@ -60,6 +62,7 @@ void dispatch_reboot(bool saveConfig);
void dispatch_output_idle_state(uint8_t state);
void dispatch_output_statusupdate(const char*, const char*);
void dispatch_current_state();
void dispatch_output_current_page();
void dispatch_gpio_input_event(uint8_t pin, uint8_t group, uint8_t eventid);
bool dispatch_get_event_state(uint8_t eventid);

View File

@ -24,6 +24,10 @@
#include "hasplib.h"
#define HASP_NUM_PAGE_PREV (HASP_NUM_PAGES + 1)
#define HASP_NUM_PAGE_BACK (HASP_NUM_PAGES + 2)
#define HASP_NUM_PAGE_NEXT (HASP_NUM_PAGES + 3)
const char** btnmatrix_default_map; // memory pointer to lvgl default btnmatrix map
// static unsigned long last_change_event = 0;
static bool last_press_was_short = false; // Avoid SHORT + UP double events
@ -71,7 +75,7 @@ lv_obj_t* hasp_find_obj_from_parent_id(lv_obj_t* parent, uint8_t objid)
bool hasp_find_id_from_obj(lv_obj_t* obj, uint8_t* pageid, uint8_t* objid)
{
if(!get_page_id(obj, pageid)) return false;
if(!haspPages.get_id(obj, pageid)) return false;
if(!(obj->user_data.id > 0)) return false;
// memcpy(objid, &obj->user_data.id, sizeof(lv_obj_user_data_t));
*objid = obj->user_data.id;
@ -364,8 +368,30 @@ void generic_event_handler(lv_obj_t* obj, lv_event_t event)
return;
}
hasp_update_sleep_state(); // wakeup?
dispatch_object_generic_event(obj, eventid); // send object event
hasp_update_sleep_state(); // wakeup?
/* If an actionid is attached, perform that action on UP event only */
if(obj->user_data.actionid) {
if(eventid == HASP_EVENT_UP || eventid == HASP_EVENT_SHORT) {
lv_scr_load_anim_t transitionid = (lv_scr_load_anim_t)obj->user_data.transitionid;
switch(obj->user_data.actionid) {
case HASP_NUM_PAGE_PREV:
haspPages.prev(transitionid);
break;
case HASP_NUM_PAGE_BACK:
haspPages.back(transitionid);
break;
case HASP_NUM_PAGE_NEXT:
haspPages.next(transitionid);
break;
default:
haspPages.set(obj->user_data.actionid, transitionid);
}
dispatch_output_current_page();
}
} else {
dispatch_object_generic_event(obj, eventid); // send normal object event
}
dispatch_normalized_group_value(obj->user_data.groupid, obj, dispatch_get_event_state(eventid), HASP_EVENT_OFF,
HASP_EVENT_ON);
}
@ -587,7 +613,7 @@ void object_set_normalized_group_value(uint8_t groupid, lv_obj_t* src_obj, int16
if(min == max) return;
for(uint8_t page = 0; page < HASP_NUM_PAGES; page++) {
object_set_group_value(get_page_obj(page), groupid, val);
object_set_group_value(haspPages.get_obj(page), groupid, val);
// uint8_t startid = 1;
// for(uint8_t objid = startid; objid < 20; objid++) {
// lv_obj_t* obj = hasp_find_obj_from_parent_id(get_page_obj(page), objid);
@ -611,7 +637,7 @@ void object_set_normalized_group_value(uint8_t groupid, lv_obj_t* src_obj, int16
// Used in the dispatcher & hasp_new_object
void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char* attr, const char* payload)
{
if(lv_obj_t* obj = hasp_find_obj_from_parent_id(get_page_obj(pageid), objid)) {
if(lv_obj_t* obj = hasp_find_obj_from_parent_id(haspPages.get_obj(pageid), objid)) {
hasp_process_obj_attribute(obj, attr, payload, strlen(payload) > 0);
} else {
LOG_WARNING(TAG_HASP, F(D_OBJECT_UNKNOWN " " HASP_OBJECT_NOTATION), pageid, objid);
@ -657,17 +683,23 @@ int hasp_parse_json_attributes(lv_obj_t* obj, const JsonObject& doc)
*/
void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id)
{
/* Page selection: page is the default parent_obj */
uint8_t pageid = config[FPSTR(FP_PAGE)].isNull() ? saved_page_id : config[FPSTR(FP_PAGE)].as<uint8_t>();
lv_obj_t* parent_obj = get_page_obj(pageid);
/* Page selection */
uint8_t pageid = saved_page_id;
if(!config[FPSTR(FP_PAGE)].isNull()) {
pageid = config[FPSTR(FP_PAGE)].as<uint8_t>();
config.remove(FPSTR(FP_PAGE));
}
/* Page with pageid is the default parent_obj */
lv_obj_t* parent_obj = haspPages.get_obj(pageid);
if(!parent_obj) {
LOG_WARNING(TAG_HASP, F(D_OBJECT_PAGE_UNKNOWN), pageid);
return;
} else {
saved_page_id = pageid; /* save the current pageid */
saved_page_id = pageid; /* save the current pageid for next objects */
}
// lv_obj_t * parent_obj = page;
/* A custom parentid was set */
if(!config[FPSTR(FP_PARENTID)].isNull()) {
uint8_t parentid = config[FPSTR(FP_PARENTID)].as<uint8_t>();
parent_obj = hasp_find_obj_from_parent_id(parent_obj, parentid);
@ -677,13 +709,15 @@ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id)
} else {
LOG_VERBOSE(TAG_HASP, F("Parent ID " HASP_OBJECT_NOTATION " found"), pageid, parentid);
}
config.remove(FPSTR(FP_PARENTID));
}
uint16_t sdbm = 0;
uint8_t id = config[FPSTR(FP_ID)].as<uint8_t>();
uint8_t groupid = config[FPSTR(FP_GROUPID)].as<uint8_t>();
uint8_t id = config[FPSTR(FP_ID)].as<uint8_t>();
config.remove(FPSTR(FP_ID));
/* Define Objects*/
/* Create the object if it does not exist */
lv_obj_t* obj = hasp_find_obj_from_parent_id(parent_obj, id);
if(!obj) {
@ -695,9 +729,11 @@ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id)
return; // comments
} else {
sdbm = Utilities::get_sdbm(config[FPSTR(FP_OBJ)].as<const char*>());
config.remove(FPSTR(FP_OBJ));
}
} else {
sdbm = config[FPSTR(FP_OBJID)].as<uint8_t>();
config.remove(FPSTR(FP_OBJID));
}
switch(sdbm) {
@ -1033,19 +1069,17 @@ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id)
LOG_VERBOSE(TAG_HASP, F(D_BULLET HASP_OBJECT_NOTATION " = %s"), pageid, temp, list.type[0]);
/* test double-check */
lv_obj_t* test = hasp_find_obj_from_parent_id(get_page_obj(pageid), (uint8_t)temp);
lv_obj_t* test = hasp_find_obj_from_parent_id(haspPages.get_obj(pageid), (uint8_t)temp);
if(test != obj) {
LOG_ERROR(TAG_HASP, F(D_OBJECT_MISMATCH));
return;
} else {
// object created successfully
}
}
/* do not process these attributes */
config.remove(FPSTR(FP_PAGE));
config.remove(FPSTR(FP_ID));
config.remove(FPSTR(FP_OBJ));
config.remove(FPSTR(FP_OBJID)); // TODO: obsolete objid
config.remove(FPSTR(FP_PARENTID));
} else {
// object already exists
}
hasp_parse_json_attributes(obj, config);
}

152
src/hasp/hasp_page.cpp Normal file
View File

@ -0,0 +1,152 @@
/* MIT License - Copyright (c) 2019-2021 Francis Van Roie
For full license information read the LICENSE file in the project folder */
#include "hasp_conf.h"
#include "hasplib.h"
#include "hasp_page.h"
namespace hasp {
Page::Page()
{
// LVGL is not yet initialized at construction time
}
size_t Page::count()
{
return sizeof(_pages) / sizeof(*_pages);
}
void Page::init(uint8_t start_page)
{
for(int i = 0; i < count(); i++) {
_pages[i] = lv_obj_create(NULL, NULL);
uint16_t thispage = i + PAGE_START_INDEX;
_meta_data[i].prev = thispage == PAGE_START_INDEX ? HASP_NUM_PAGES : thispage - PAGE_START_INDEX;
_meta_data[i].next = thispage == HASP_NUM_PAGES ? PAGE_START_INDEX : thispage + PAGE_START_INDEX;
_meta_data[i].back = start_page;
}
}
void Page::clear(uint16_t pageid)
{
lv_obj_t* page = get_obj(pageid);
if(!page || (pageid > HASP_NUM_PAGES)) {
LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid);
} else if(page == lv_layer_sys() /*|| page == lv_layer_top()*/) {
LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_LAYER));
} else {
LOG_TRACE(TAG_HASP, F(D_HASP_CLEAR_PAGE), pageid);
lv_obj_clean(page);
}
}
// void Page::set(uint8_t pageid)
// {
// set(pageid, LV_SCR_LOAD_ANIM_NONE);
// }
void Page::set(uint8_t pageid, lv_scr_load_anim_t animation)
{
lv_obj_t* page = get_obj(pageid);
if(!page || pageid == 0 || pageid > HASP_NUM_PAGES) {
LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid);
} else {
LOG_TRACE(TAG_HASP, F(D_HASP_CHANGE_PAGE), pageid);
_current_page = pageid;
lv_scr_load_anim(page, animation, 500, 0, false);
hasp_object_tree(page, pageid, 0);
}
}
void Page::next(lv_scr_load_anim_t animation)
{
set(_meta_data[_current_page - PAGE_START_INDEX].next, animation);
}
void Page::prev(lv_scr_load_anim_t animation)
{
set(_meta_data[_current_page - PAGE_START_INDEX].prev, animation);
}
void Page::back(lv_scr_load_anim_t animation)
{
set(_meta_data[_current_page - PAGE_START_INDEX].back, animation);
}
uint8_t Page::get()
{
return _current_page;
}
void Page::load_jsonl(const char* pagesfile)
{
#if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0
if(pagesfile[0] == '\0') return;
if(!filesystemSetup()) {
LOG_ERROR(TAG_HASP, F("FS not mounted. Failed to load %s"), pagesfile);
return;
}
if(!HASP_FS.exists(pagesfile)) {
LOG_ERROR(TAG_HASP, F("Non existing file %s"), pagesfile);
return;
}
LOG_TRACE(TAG_HASP, F("Loading file %s"), pagesfile);
File file = HASP_FS.open(pagesfile, "r");
dispatch_parse_jsonl(file);
file.close();
LOG_INFO(TAG_HASP, F("File %s loaded"), pagesfile);
#else
#if HASP_USE_EEPROM > 0
LOG_TRACE(TAG_HASP, F("Loading jsonl from EEPROM..."));
EepromStream eepromStream(4096, 1024);
dispatch_parse_jsonl(eepromStream);
LOG_INFO(TAG_HASP, F("Loaded jsonl from EEPROM"));
#endif
#endif
}
lv_obj_t* Page::get_obj(uint8_t pageid)
{
if(pageid == 0) return lv_layer_top(); // 254
if(pageid == 255) return lv_layer_sys();
if(pageid > count()) return NULL; // >=0
return _pages[pageid - PAGE_START_INDEX];
}
bool Page::get_id(lv_obj_t* obj, uint8_t* pageid)
{
lv_obj_t* page = lv_obj_get_screen(obj);
if(!page) return false;
if(page == lv_layer_top()) {
*pageid = 0;
return true;
}
if(page == lv_layer_sys()) {
*pageid = 255;
return true;
}
for(uint8_t i = 0; i < count(); i++) {
if(page == _pages[i]) {
*pageid = i + PAGE_START_INDEX;
return true;
}
}
return false;
}
} // namespace hasp
hasp::Page haspPages;

55
src/hasp/hasp_page.h Normal file
View File

@ -0,0 +1,55 @@
/* MIT License - Copyright (c) 2019-2021 Francis Van Roie
For full license information read the LICENSE file in the project folder */
#ifndef HASP_PAGES_H
#define HASP_PAGES_H
#include "hasp_conf.h"
#include "hasplib.h"
/*********************
* DEFINES
*********************/
#define PAGE_START_INDEX 1 // Page number of array index 0
/**********************
* TYPEDEFS
**********************/
typedef struct hasp_page_meta_data_t
{
uint8_t prev : 4;
uint8_t next : 4;
uint8_t back : 4;
};
namespace hasp {
class Page {
private:
hasp_page_meta_data_t _meta_data[HASP_NUM_PAGES]; // index 0 = Page 1 etc.
lv_obj_t* _pages[HASP_NUM_PAGES]; // index 0 = Page 1 etc.
uint8_t _current_page;
public:
Page();
size_t count();
void init(uint8_t start_page);
void clear(uint16_t pageid);
// void set(uint8_t pageid);
void set(uint8_t pageid, lv_scr_load_anim_t animation);
void next(lv_scr_load_anim_t animation);
void prev(lv_scr_load_anim_t animation);
void back(lv_scr_load_anim_t animation);
uint8_t get();
void load_jsonl(const char* pagesfile);
lv_obj_t* get_obj(uint8_t pageid);
bool get_id(lv_obj_t* obj, uint8_t* pageid);
};
} // namespace hasp
using hasp::Page;
extern hasp::Page haspPages;
#endif // HASP_PAGES_H

View File

@ -4,6 +4,7 @@
#include "hasp/hasp_attribute.h"
#include "hasp/hasp_dispatch.h"
#include "hasp/hasp_object.h"
#include "hasp/hasp_page.h"
#include "hasp/hasp_parser.h"
#include "hasp/hasp_utilities.h"
#include "hasp/hasp_lvfs.h"

View File

@ -92,7 +92,7 @@
#define D_OTA_CHECK_UPDATE "Checking updates URL: %s"
#define D_OTA_CHECK_COMPLETE "Update check complete"
#define D_OTA_CHECK_FAILED "Update check failed: %s"
#define D_OTA_UPDATE_FIRMWARE "OTA Update firmware"
#define D_OTA_UPDATE_FIRMWARE "OTA Firmware Update"
#define D_OTA_UPDATE_COMPLETE "OTA Update complete"
#define D_OTA_UPDATE_APPLY "Applying Firmware & Reboot"
#define D_OTA_UPDATE_FAILED "OTA Update failed"

View File

@ -89,13 +89,13 @@
#define D_JSONL_FAILED "JSONL verwerking mislukt op lijn %d"
#define D_JSONL_SUCCEEDED "Jsonl volledig verwerkt"
#define D_OTA_CHECK_UPDATE "Checking updates URL: %s"
#define D_OTA_CHECK_COMPLETE "Update check complete"
#define D_OTA_CHECK_UPDATE "Controle update URL: %s"
#define D_OTA_CHECK_COMPLETE "Update controle klaar"
#define D_OTA_CHECK_FAILED "Update check failed: %s"
#define D_OTA_UPDATE_FIRMWARE "OTA Update firmware"
#define D_OTA_UPDATE_COMPLETE "OTA Update complete"
#define D_OTA_UPDATE_APPLY "Applying Firmware & Reboot"
#define D_OTA_UPDATE_FAILED "OTA Update failed"
#define D_OTA_UPDATE_FIRMWARE "OTA Firmware bijwerken"
#define D_OTA_UPDATE_COMPLETE "OTA Firmware bijgewerkt"
#define D_OTA_UPDATE_APPLY "Firmware Schrijven & Herstart"
#define D_OTA_UPDATE_FAILED "OTA Update mislukt"
#define D_HTTP_HASP_DESIGN "HASP Ontwerp"
#define D_HTTP_INFORMATION "Informatie"

View File

@ -95,7 +95,7 @@ extern bool debugAnsiCodes;
ConsoleInput debugConsole(&Serial, HASP_CONSOLE_BUFFER);
unsigned long debugLastMillis = 0;
uint16_t debugTelePeriod = 300;
extern dispatch_conf_t dispatch_setings;
// #if HASP_USE_SYSLOG > 0
// void syslogSend(uint8_t priority, const char * debugText)
@ -158,8 +158,8 @@ bool debugGetConfig(const JsonObject& settings)
if(debugSerialBaud != settings[FPSTR(FP_CONFIG_BAUD)].as<uint16_t>()) changed = true;
settings[FPSTR(FP_CONFIG_BAUD)] = debugSerialBaud;
if(debugTelePeriod != settings[FPSTR(FP_DEBUG_TELEPERIOD)].as<uint16_t>()) changed = true;
settings[FPSTR(FP_DEBUG_TELEPERIOD)] = debugTelePeriod;
if(dispatch_setings.teleperiod != settings[FPSTR(FP_DEBUG_TELEPERIOD)].as<uint16_t>()) changed = true;
settings[FPSTR(FP_DEBUG_TELEPERIOD)] = dispatch_setings.teleperiod;
#if HASP_USE_SYSLOG > 0
if(strcmp(debugSyslogHost, settings[FPSTR(FP_CONFIG_HOST)].as<String>().c_str()) != 0) changed = true;
@ -196,7 +196,7 @@ bool debugSetConfig(const JsonObject& settings)
changed |= configSet(debugSerialBaud, settings[FPSTR(FP_CONFIG_BAUD)], F("debugSerialBaud"));
/* Teleperiod Settings*/
changed |= configSet(debugTelePeriod, settings[FPSTR(FP_DEBUG_TELEPERIOD)], F("debugTelePeriod"));
changed |= configSet(dispatch_setings.teleperiod, settings[FPSTR(FP_DEBUG_TELEPERIOD)], F("debugTelePeriod"));
/* Syslog Settings*/
#if HASP_USE_SYSLOG > 0
@ -340,19 +340,20 @@ void debugLoop(void)
switch(keypress = debugConsole.readKey()) {
case ConsoleInput::KEY_PAGE_UP:
dispatch_page_next();
dispatch_page_next(LV_SCR_LOAD_ANIM_NONE);
break;
case ConsoleInput::KEY_PAGE_DOWN:
dispatch_page_prev();
dispatch_page_prev(LV_SCR_LOAD_ANIM_NONE);
break;
case(ConsoleInput::KEY_FN)...(ConsoleInput::KEY_FN + 12):
haspSetPage(keypress - ConsoleInput::KEY_FN - 1);
dispatch_set_page(keypress - ConsoleInput::KEY_FN, LV_SCR_LOAD_ANIM_NONE);
break;
}
} while(keypress != 0);
}
void printLocalTime()
{
char buffer[128];

View File

@ -14,12 +14,14 @@
#include "dev/device.h"
#include "hasp_gui.h"
#include "hal/hasp_hal.h"
#include "hasp/hasp_dispatch.h"
#include "hasp_debug.h"
#include "hasp_config.h"
#include "hal/hasp_hal.h"
#include "hasp/hasp_utilities.h"
#include "hasp/hasp_dispatch.h"
#include "hasp/hasp_page.h"
#include "hasp/hasp.h"
#if HASP_USE_HTTP > 0
@ -374,9 +376,11 @@ void webHandleScreenshot()
if(webServer.hasArg(F("a"))) {
if(webServer.arg(F("a")) == F("next")) {
dispatch_page_next();
dispatch_page_next(LV_SCR_LOAD_ANIM_NONE);
} else if(webServer.arg(F("a")) == F("prev")) {
dispatch_page_prev();
dispatch_page_prev(LV_SCR_LOAD_ANIM_NONE);
} else if(webServer.arg(F("a")) == F("back")) {
dispatch_page_back(LV_SCR_LOAD_ANIM_NONE);
}
}
@ -559,7 +563,7 @@ void webHandleInfo()
// String(LV_HASP_VER_RES_MAX); httpMessage += F("<br/><b>LCD Version: </b>")) +
// String(lcdVersion);
httpMessage += F("</p/><p><b>LCD Active Page: </b>");
httpMessage += String(haspGetPage());
httpMessage += String(haspPages.get());
/* Wifi Stats */
#if HASP_USE_WIFI > 0
@ -1601,7 +1605,7 @@ void webHandleDebugConfig()
httpMessage += getOption(7488, F("74880"), baudrate == 7488);
httpMessage += getOption(11520, F("115200"), baudrate == 11520);
httpMessage += F("</select></p><p><b>Telemetry Period</b> <i><small>(Seconds, 0=disable)</small></i> "
"<input id='teleperiod' required name='teleperiod' type='number' min='0' max='65535' value='");
"<input id='tele' required name='tele' type='number' min='0' max='65535' value='");
httpMessage += settings[FPSTR(FP_DEBUG_TELEPERIOD)].as<String>();
httpMessage += F("'></p>");
@ -1967,7 +1971,7 @@ void httpSetup()
webServer.on(F("/page/"), []() {
String pageid = webServer.arg(F("page"));
webServer.send(200, PSTR("text/plain"), "Page: '" + pageid + "'");
haspSetPage(pageid.toInt());
dispatch_set_page(pageid.toInt(), LV_SCR_LOAD_ANIM_NONE);
});
#if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0

97
tools/esp_merge_bin.py Normal file
View File

@ -0,0 +1,97 @@
Import('env')
import os
import sys
import shutil
import subprocess
buildFlags = env.ParseFlags(env['BUILD_FLAGS'])
OUTPUT_DIR = "build_output{}".format(os.path.sep)
platform = env.PioPlatform()
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32")
FRAMEWORK_DIR = "{}{}".format(FRAMEWORK_DIR, os.path.sep)
def get_fw_version(source, target, env):
global HASP_VER_MAJ
global HASP_VER_MIN
global HASP_VER_REV
for item in buildFlags.get("CPPDEFINES"):
if (type(item) is list):
if (item[0]=="HASP_VER_MAJ"): HASP_VER_MAJ = item[1]
if (item[0]=="HASP_VER_MIN"): HASP_VER_MIN = item[1]
if (item[0]=="HASP_VER_REV"): HASP_VER_REV = item[1]
print(" * %s = %s" % (item[0],item[1]))
else:
print(" * %s" % item)
def copy_merge_bins(source, target, env):
version = 'v' + str(HASP_VER_MAJ) + '.' + str(HASP_VER_MIN) + '.' + str(HASP_VER_REV)
name =str(target[0]).split(os.path.sep)[2]
flash_size = env.GetProjectOption("board_upload.flash_size")
bootloader = "{}tools{}sdk{}bin{}bootloader_dio_40m.bin".format(FRAMEWORK_DIR, os.path.sep, os.path.sep, os.path.sep, os.path.sep)
partitions = "{}{}partitions.bin".format(env.subst("$BUILD_DIR"), os.path.sep)
boot_app0 = "{}tools{}partitions{}boot_app0.bin".format(FRAMEWORK_DIR, os.path.sep, os.path.sep, os.path.sep)
firmware_dst ="{}firmware{}{}_full_{}_{}.bin".format(OUTPUT_DIR, os.path.sep, name, flash_size, version)
firmware_src = str(target[0])
# check if output directories exist and create if necessary
if not os.path.isdir(OUTPUT_DIR):
os.mkdir(OUTPUT_DIR)
for d in ['firmware', 'map']:
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)):
os.mkdir("{}{}".format(OUTPUT_DIR, d))
# check if new target files exist and remove if necessary
for f in [firmware_dst]:
if os.path.isfile(f):
os.remove(f)
print(bootloader)
print(partitions)
print(boot_app0)
print(firmware_src)
print(firmware_dst)
print(flash_size)
process = subprocess.Popen(['python', 'tools/esptool_with_merge_bin.py', '--chip', 'esp32', 'merge_bin', '--output', firmware_dst, '--flash_mode', 'dio', '--flash_size', flash_size, '0x1000', bootloader, '0x8000', partitions, '0xe000', boot_app0, '0x10000', firmware_src],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
stdout, stderr
print(stdout.decode("utf-8") )
print(stderr.decode("utf-8") )
def copy_ota(source, target, env):
version = 'v' + str(HASP_VER_MAJ) + '.' + str(HASP_VER_MIN) + '.' + str(HASP_VER_REV)
name =str(target[0]).split(os.path.sep)[2]
firmware_src = str(target[0])
firmware_dst ="{}firmware{}{}_ota_{}.bin".format(OUTPUT_DIR, os.path.sep, name, version)
# check if output directories exist and create if necessary
if not os.path.isdir(OUTPUT_DIR):
os.mkdir(OUTPUT_DIR)
for d in ['firmware', 'map']:
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)):
os.mkdir("{}{}".format(OUTPUT_DIR, d))
# check if new target files exist and remove if necessary
for f in [firmware_dst]:
if os.path.isfile(f):
os.remove(f)
print(firmware_src)
print(firmware_dst)
# copy firmware.bin to firmware/<variant>.bin
shutil.copy(firmware_src, firmware_dst)
env.AddPreAction("$BUILD_DIR/${PROGNAME}.bin", [get_fw_version])
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [copy_merge_bins])
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [copy_ota])

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,3 @@ lib_ignore =
${env.lib_ignore}
${esp32.lib_ignore}
;endregion
extra_scripts =
${env.extra_scripts}
${esp32.extra_scripts}

View File

@ -51,5 +51,4 @@ lib_ignore =
${env.lib_ignore}
; ${esp32.lib_ignore}
lv_drv_fsmc_ili9341
;endregion

View File

@ -13,8 +13,7 @@ board = esp32cam
build_flags =
${env.build_flags}
${esp32.build_flags}
-DBOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue
${esp32.ps_ram}
;region -- TFT_eSPI build options ------------------------
${lcd.raspberrypi}

View File

@ -54,7 +54,3 @@ lib_ignore =
${esp32.lib_ignore}
ESP32 BLE Arduino
;endregion
extra_scripts =
${env.extra_scripts}
${esp32.extra_scripts}

View File

@ -7,7 +7,7 @@
; !! This board already defines TFT_CS, TFT_DC and TFT_RST !!
[env:lolind32pro-lolintft24]
[env:lolin-d32-pro_ili9341]
extends = esp32
board = lolin_d32_pro
@ -41,7 +41,3 @@ lib_ignore =
${env.lib_ignore}
${esp32.lib_ignore}
;endregion
extra_scripts =
${env.extra_scripts}
${esp32.extra_scripts}

View File

@ -53,7 +53,3 @@ lib_ignore =
lv_drv_fsmc_ili9341
lv_drivers
;endregion
extra_scripts =
${env.extra_scripts}
${esp32.extra_scripts}

View File

@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x1A0000,
app1, app, ota_1, 0x1B0000, 0x1A0000,
spiffs, data, spiffs, 0x350000, 0x0B0000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x1A0000
5 app1 app ota_1 0x1B0000 0x1A0000
6 spiffs data spiffs 0x350000 0x0B0000

View File

@ -6,7 +6,7 @@
; - xpt2046 touch controller ;
;***************************************************;
[env:ttgo_esp32_poe-lolintft24]
[env:ttgo_esp32_poe-ili9341]
extends = esp32
board = esp32dev

View File

@ -42,7 +42,3 @@ lib_ignore =
${env.lib_ignore}
${esp32.lib_ignore}
;endregion
extra_scripts =
${env.extra_scripts}
${esp32.extra_scripts}